summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gst/avi/gstavidemux.c403
1 files changed, 165 insertions, 238 deletions
diff --git a/gst/avi/gstavidemux.c b/gst/avi/gstavidemux.c
index 43a8a16cb..0765bd856 100644
--- a/gst/avi/gstavidemux.c
+++ b/gst/avi/gstavidemux.c
@@ -995,7 +995,117 @@ too_small:
995 } 995 }
996} 996}
997 997
998#if 0 998/* add an entry to the index of a stream. @num should be an estimate of the
999 * total amount of index entries for all streams and is used to dynamically
1000 * allocate memory for the index entries. */
1001static inline gboolean
1002gst_avi_demux_add_index (GstAviDemux * avi, GstAviStream * stream,
1003 guint num, GstAviIndexEntry * entry)
1004{
1005 /* ensure index memory */
1006 if (G_UNLIKELY (stream->idx_n >= stream->idx_max)) {
1007 /* we need to make some more room */
1008 if (stream->idx_max == 0) {
1009 /* initial size guess, assume each stream has an equal amount of entries,
1010 * overshoot with at least 8K */
1011 stream->idx_max =
1012 (num / avi->num_streams) + (8192 / sizeof (GstAviIndexEntry));
1013 } else {
1014 stream->idx_max += 8192 / sizeof (GstAviIndexEntry);
1015 GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "expanded index to %u",
1016 stream->idx_max);
1017 }
1018 stream->index = g_try_renew (GstAviIndexEntry, stream->index,
1019 stream->idx_max);
1020 if (G_UNLIKELY (!stream->index))
1021 return FALSE;
1022 }
1023
1024 /* update stream stats and total size */
1025 entry->total = stream->total_bytes;
1026 stream->total_bytes += entry->size;
1027 if (stream->strh->type == GST_RIFF_FCC_auds) {
1028 gint blockalign = stream->strf.auds->blockalign;
1029 if (blockalign > 0)
1030 stream->total_blocks += DIV_ROUND_UP (entry->size, blockalign);
1031 else
1032 stream->total_blocks++;
1033 }
1034 if (ENTRY_IS_KEYFRAME (entry))
1035 stream->n_keyframes++;
1036
1037 /* and add */
1038 GST_LOG_OBJECT (avi,
1039 "Adding stream %u, index entry %d, kf %d, size %u "
1040 ", offset %" G_GUINT64_FORMAT ", total %" G_GUINT64_FORMAT, stream->num,
1041 stream->idx_n, ENTRY_IS_KEYFRAME (entry), entry->size, entry->offset,
1042 entry->total);
1043 stream->index[stream->idx_n++] = *entry;
1044
1045 return TRUE;
1046}
1047
1048/* collect and debug stats about the indexes for all streams.
1049 * This method is also responsible for filling in the stream duration
1050 * as measured by the amount of index entries. */
1051static void
1052gst_avi_demux_do_index_stats (GstAviDemux * avi)
1053{
1054 guint i;
1055#ifndef GST_DISABLE_GST_DEBUG
1056 guint total_idx = 0, total_max = 0;
1057#endif
1058
1059 /* get stream stats now */
1060 for (i = 0; i < avi->num_streams; i++) {
1061 GstAviIndexEntry *entry;
1062 GstAviStream *stream;
1063 guint64 total;
1064
1065 if (G_UNLIKELY (!(stream = &avi->stream[i])))
1066 continue;
1067 if (G_UNLIKELY (!stream->strh))
1068 continue;
1069 if (G_UNLIKELY (!stream->index || stream->idx_n == 0))
1070 continue;
1071
1072 entry = &stream->index[stream->idx_n - 1];
1073 total = entry->total + entry->size;
1074
1075 /* calculate duration */
1076 if (stream->is_vbr) {
1077 /* VBR stream next timestamp */
1078 if (stream->strh->type == GST_RIFF_FCC_auds) {
1079 stream->idx_duration =
1080 avi_stream_convert_frames_to_time_unchecked (stream, total);
1081 } else {
1082 stream->idx_duration =
1083 avi_stream_convert_frames_to_time_unchecked (stream, stream->idx_n);
1084 }
1085 } else {
1086 /* constant rate stream */
1087 stream->idx_duration = avi_stream_convert_bytes_to_time_unchecked (stream,
1088 total);
1089 }
1090#ifndef GST_DISABLE_GST_DEBUG
1091 total_idx += stream->idx_n;
1092 total_max += stream->idx_max;
1093#endif
1094 GST_INFO_OBJECT (avi, "Stream %d, dur %" GST_TIME_FORMAT ", %6u entries, "
1095 "%5u keyframes, entry size = %2u, total size = %10u, allocated %10u",
1096 i, GST_TIME_ARGS (stream->idx_duration), stream->idx_n,
1097 stream->n_keyframes, (guint) sizeof (GstAviIndexEntry),
1098 (guint) (stream->idx_n * sizeof (GstAviIndexEntry)),
1099 (guint) (stream->idx_max * sizeof (GstAviIndexEntry)));
1100 }
1101#ifndef GST_DISABLE_GST_DEBUG
1102 total_idx *= sizeof (GstAviIndexEntry);
1103 total_max *= sizeof (GstAviIndexEntry);
1104#endif
1105 GST_INFO_OBJECT (avi, "%u bytes for index vs %u ideally, %u wasted",
1106 total_max, total_idx, total_max - total_idx);
1107}
1108
999/* 1109/*
1000 * gst_avi_demux_parse_subindex: 1110 * gst_avi_demux_parse_subindex:
1001 * @avi: Avi object 1111 * @avi: Avi object
@@ -1008,36 +1118,32 @@ too_small:
1008 * found. 1118 * found.
1009 * 1119 *
1010 * Reads superindex (openDML-2 spec stuff) from the provided data. 1120 * Reads superindex (openDML-2 spec stuff) from the provided data.
1011 * The buffer will be discarded after use.
1012 * The buffer should contain a GST_RIFF_TAG_ix?? chunk. 1121 * The buffer should contain a GST_RIFF_TAG_ix?? chunk.
1013 * 1122 *
1014 * Returns: TRUE on success, FALSE otherwise. Errors are fatal, we 1123 * Returns: TRUE on success, FALSE otherwise. Errors are fatal, we
1015 * throw an error, caller should bail out asap. 1124 * throw an error, caller should bail out asap.
1016 */ 1125 */
1017static gboolean 1126static gboolean
1018gst_avi_demux_parse_subindex (GstAviDemux * avi, 1127gst_avi_demux_parse_subindex (GstAviDemux * avi, GstAviStream * stream,
1019 GstBuffer * buf, GstAviStream * stream, GList ** _entries_list) 1128 GstBuffer * buf)
1020{ 1129{
1021 guint8 *data = GST_BUFFER_DATA (buf); 1130 guint8 *data;
1022 guint16 bpe; 1131 guint16 bpe;
1023 guint32 num, i; 1132 guint32 num, i;
1024 guint64 baseoff; 1133 guint64 baseoff;
1025 gst_avi_index_entry *entries, *entry;
1026 GList *entries_list = NULL;
1027 guint size; 1134 guint size;
1028 1135
1029#ifndef GST_DISABLE_GST_DEBUG 1136 if (!buf)
1030 gulong _nr_keyframes = 0; 1137 return TRUE;
1031#endif
1032
1033 *_entries_list = NULL;
1034 1138
1035 size = buf ? GST_BUFFER_SIZE (buf) : 0; 1139 size = GST_BUFFER_SIZE (buf);
1036 1140
1037 /* check size */ 1141 /* check size */
1038 if (size < 24) 1142 if (size < 24)
1039 goto too_small; 1143 goto too_small;
1040 1144
1145 data = GST_BUFFER_DATA (buf);
1146
1041 /* We don't support index-data yet */ 1147 /* We don't support index-data yet */
1042 if (data[3] & 0x80) 1148 if (data[3] & 0x80)
1043 goto not_implemented; 1149 goto not_implemented;
@@ -1059,94 +1165,36 @@ gst_avi_demux_parse_subindex (GstAviDemux * avi,
1059 1165
1060 /* If there's nothing, just return ! */ 1166 /* If there's nothing, just return ! */
1061 if (num == 0) 1167 if (num == 0)
1062 return TRUE; 1168 goto empty_index;
1063
1064 if (!(entries = g_try_new (gst_avi_index_entry, num)))
1065 goto out_of_mem;
1066 1169
1067 GST_INFO_OBJECT (avi, "Parsing subindex, nr_entries = %6d", num); 1170 GST_INFO_OBJECT (avi, "Parsing subindex, nr_entries = %6d", num);
1068 1171
1069 for (i = 0; i < num; i++) { 1172 for (i = 0; i < num; i++) {
1070 gint64 next_ts; 1173 GstAviIndexEntry entry;
1071
1072 entry = &entries[i];
1073 1174
1074 if (size < 24 + bpe * (i + 1)) 1175 if (size < 24 + bpe * (i + 1))
1075 break; 1176 break;
1076 1177
1077 /* fill in */ 1178 /* fill in offset and size. offset contains the keyframe flag in the
1078 entry->offset = baseoff + GST_READ_UINT32_LE (&data[24 + bpe * i]); 1179 * upper bit*/
1079 entry->size = GST_READ_UINT32_LE (&data[24 + bpe * i + 4]); 1180 entry.offset = baseoff + GST_READ_UINT32_LE (&data[24 + bpe * i]);
1080 entry->flags = 1181 entry.size = GST_READ_UINT32_LE (&data[24 + bpe * i + 4]);
1081 (entry->size & 0x80000000) ? 0 : GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME; 1182 /* handle flags */
1082 entry->size &= ~0x80000000;
1083 entry->index_nr = i;
1084 entry->stream_nr = stream->num;
1085
1086 if (stream->strh->type == GST_RIFF_FCC_auds) { 1183 if (stream->strh->type == GST_RIFF_FCC_auds) {
1087 /* all audio frames are keyframes */ 1184 /* all audio frames are keyframes */
1088 entry->flags |= GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME; 1185 ENTRY_SET_KEYFRAME (&entry);
1089 }
1090#ifndef GST_DISABLE_GST_DEBUG
1091 if (entry->flags & GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME)
1092 _nr_keyframes++;
1093#endif
1094
1095 /* stream duration unknown, now we can calculate it */
1096 if (stream->idx_duration == -1)
1097 stream->idx_duration = 0;
1098
1099 /* timestamps */
1100 entry->ts = stream->idx_duration;
1101 if (stream->is_vbr) {
1102 /* VBR stream next timestamp */
1103 if (stream->strh->type == GST_RIFF_FCC_auds) {
1104 next_ts = avi_stream_convert_frames_to_time_unchecked (stream,
1105 stream->total_blocks + 1);
1106 } else {
1107 next_ts = avi_stream_convert_frames_to_time_unchecked (stream,
1108 stream->idx_n + 1);
1109 }
1110 } else { 1186 } else {
1111 /* CBR get next timestamp */ 1187 /* else read flags */
1112 next_ts = avi_stream_convert_bytes_to_time_unchecked (stream, 1188 entry.flags = (entry.size & 0x80000000) ? 0 : GST_AVI_KEYFRAME;
1113 stream->total_bytes + entry->size);
1114 }
1115 /* duration is next - current */
1116 entry->dur = next_ts - entry->ts;
1117
1118 /* stream position */
1119 entry->bytes_before = stream->total_bytes;
1120 entry->frames_before = stream->idx_n;
1121
1122 stream->total_bytes += entry->size;
1123 stream->idx_n++;
1124 if (stream->strh->type == GST_RIFF_FCC_auds) {
1125 if (stream->strf.auds->blockalign > 0)
1126 stream->total_blocks +=
1127 (entry->size + stream->strf.auds->blockalign -
1128 1) / stream->strf.auds->blockalign;
1129 else
1130 stream->total_blocks++;
1131 } 1189 }
1132 stream->idx_duration = next_ts; 1190 entry.size &= ~0x80000000;
1133 1191
1134 entries_list = g_list_prepend (entries_list, entry); 1192 /* and add */
1193 if (G_UNLIKELY (!gst_avi_demux_add_index (avi, stream, num, &entry)))
1194 goto out_of_mem;
1135 } 1195 }
1136
1137 GST_INFO_OBJECT (avi, "Parsed index, %6u/%6u entries, %5lu keyframes, "
1138 "entry size = %2u, total size = %10d", i, num, _nr_keyframes,
1139 (gint) sizeof (gst_avi_index_entry),
1140 (gint) (i * sizeof (gst_avi_index_entry)));
1141
1142 gst_buffer_unref (buf); 1196 gst_buffer_unref (buf);
1143 1197
1144 if (i > 0) {
1145 *_entries_list = g_list_reverse (entries_list);
1146 } else {
1147 g_free (entries);
1148 }
1149
1150 return TRUE; 1198 return TRUE;
1151 1199
1152 /* ERRORS */ 1200 /* ERRORS */
@@ -1154,8 +1202,7 @@ too_small:
1154 { 1202 {
1155 GST_ERROR_OBJECT (avi, 1203 GST_ERROR_OBJECT (avi,
1156 "Not enough data to parse subindex (%d available, 24 needed)", size); 1204 "Not enough data to parse subindex (%d available, 24 needed)", size);
1157 if (buf) 1205 gst_buffer_unref (buf);
1158 gst_buffer_unref (buf);
1159 return TRUE; /* continue */ 1206 return TRUE; /* continue */
1160 } 1207 }
1161not_implemented: 1208not_implemented:
@@ -1165,33 +1212,35 @@ not_implemented:
1165 gst_buffer_unref (buf); 1212 gst_buffer_unref (buf);
1166 return FALSE; 1213 return FALSE;
1167 } 1214 }
1215empty_index:
1216 {
1217 GST_DEBUG_OBJECT (avi, "the index is empty");
1218 gst_buffer_unref (buf);
1219 return TRUE;
1220 }
1168out_of_mem: 1221out_of_mem:
1169 { 1222 {
1170 GST_ELEMENT_ERROR (avi, RESOURCE, NO_SPACE_LEFT, (NULL), 1223 GST_ELEMENT_ERROR (avi, RESOURCE, NO_SPACE_LEFT, (NULL),
1171 ("Cannot allocate memory for %u*%u=%u bytes", 1224 ("Cannot allocate memory for %u*%u=%u bytes",
1172 (guint) sizeof (gst_avi_index_entry), num, 1225 (guint) sizeof (GstAviIndexEntry), num,
1173 (guint) sizeof (gst_avi_index_entry) * num)); 1226 (guint) sizeof (GstAviIndexEntry) * num));
1174 gst_buffer_unref (buf); 1227 gst_buffer_unref (buf);
1175 return FALSE; 1228 return FALSE;
1176 } 1229 }
1177} 1230}
1178#endif
1179 1231
1180#if 0 1232#if 0
1181/* 1233/*
1182 * Read AVI index when streaming 1234 * Read AVI index when streaming
1183 */ 1235 */
1184static void 1236static void
1185gst_avi_demux_read_subindexes_push (GstAviDemux * avi, 1237gst_avi_demux_read_subindexes_push (GstAviDemux * avi)
1186 GList ** index, GList ** alloc_list)
1187{ 1238{
1188 GList *list = NULL;
1189 guint32 tag = 0, size; 1239 guint32 tag = 0, size;
1190 GstBuffer *buf = NULL; 1240 GstBuffer *buf = NULL;
1191 gint i, n; 1241 gint i, n;
1192 1242
1193 GST_DEBUG_OBJECT (avi, "gst_avi_demux_read_subindexes_push for %d streams", 1243 GST_DEBUG_OBJECT (avi, "read subindexes for %d streams", avi->num_streams);
1194 avi->num_streams);
1195 1244
1196 for (n = 0; n < avi->num_streams; n++) { 1245 for (n = 0; n < avi->num_streams; n++) {
1197 GstAviStream *stream = &avi->stream[n]; 1246 GstAviStream *stream = &avi->stream[n];
@@ -1214,43 +1263,37 @@ gst_avi_demux_read_subindexes_push (GstAviDemux * avi,
1214 GST_BUFFER_DATA (buf) = gst_adapter_take (avi->adapter, size); 1263 GST_BUFFER_DATA (buf) = gst_adapter_take (avi->adapter, size);
1215 GST_BUFFER_SIZE (buf) = size; 1264 GST_BUFFER_SIZE (buf) = size;
1216 1265
1217 if (!gst_avi_demux_parse_subindex (avi, buf, stream, &list)) 1266 if (!gst_avi_demux_parse_subindex (avi, stream, buf))
1218 continue; 1267 continue;
1219 if (list) {
1220 GST_DEBUG_OBJECT (avi, " adding %d entries", g_list_length (list));
1221 *alloc_list = g_list_append (*alloc_list, list->data);
1222 *index = g_list_concat (*index, list);
1223 }
1224 } 1268 }
1225 1269
1226 g_free (stream->indexes); 1270 g_free (stream->indexes);
1227 stream->indexes = NULL; 1271 stream->indexes = NULL;
1228 } 1272 }
1229 GST_DEBUG_OBJECT (avi, "index %s", ((*index) ? "!= 0" : "== 0")); 1273 /* get stream stats now */
1274 gst_avi_demux_do_index_stats (avi);
1275
1276 avi->have_index = TRUE;
1230} 1277}
1231#endif 1278#endif
1232 1279
1233#if 0
1234/* 1280/*
1235 * Read AVI index 1281 * Read AVI index
1236 */ 1282 */
1237static void 1283static void
1238gst_avi_demux_read_subindexes_pull (GstAviDemux * avi, 1284gst_avi_demux_read_subindexes_pull (GstAviDemux * avi)
1239 GList ** index, GList ** alloc_list)
1240{ 1285{
1241 GList *list = NULL;
1242 guint32 tag; 1286 guint32 tag;
1243 GstBuffer *buf; 1287 GstBuffer *buf;
1244 gint i, n; 1288 gint i, n;
1245 1289
1246 GST_DEBUG_OBJECT (avi, "gst_avi_demux_read_subindexes_pull for %d streams", 1290 GST_DEBUG_OBJECT (avi, "read subindexes for %d streams", avi->num_streams);
1247 avi->num_streams);
1248 1291
1249 for (n = 0; n < avi->num_streams; n++) { 1292 for (n = 0; n < avi->num_streams; n++) {
1250 GstAviStream *stream = &avi->stream[n]; 1293 GstAviStream *stream = &avi->stream[n];
1251 1294
1252 for (i = 0; stream->indexes[i] != GST_BUFFER_OFFSET_NONE; i++) { 1295 for (i = 0; stream->indexes[i] != GST_BUFFER_OFFSET_NONE; i++) {
1253 if (gst_riff_read_chunk (GST_ELEMENT (avi), avi->sinkpad, 1296 if (gst_riff_read_chunk (GST_ELEMENT_CAST (avi), avi->sinkpad,
1254 &stream->indexes[i], &tag, &buf) != GST_FLOW_OK) 1297 &stream->indexes[i], &tag, &buf) != GST_FLOW_OK)
1255 continue; 1298 continue;
1256 else if ((tag != GST_MAKE_FOURCC ('i', 'x', '0' + stream->num / 10, 1299 else if ((tag != GST_MAKE_FOURCC ('i', 'x', '0' + stream->num / 10,
@@ -1265,23 +1308,18 @@ gst_avi_demux_read_subindexes_pull (GstAviDemux * avi,
1265 continue; 1308 continue;
1266 } 1309 }
1267 1310
1268 if (!gst_avi_demux_parse_subindex (avi, buf, stream, &list)) 1311 if (!gst_avi_demux_parse_subindex (avi, stream, buf))
1269 continue; 1312 continue;
1270 if (list) {
1271 GST_DEBUG_OBJECT (avi, " adding %5d entries, total %2d %5d",
1272 g_list_length (list), g_list_length (*alloc_list),
1273 g_list_length (*index));
1274 *alloc_list = g_list_append (*alloc_list, list->data);
1275 *index = g_list_concat (*index, list);
1276 }
1277 } 1313 }
1278 1314
1279 g_free (stream->indexes); 1315 g_free (stream->indexes);
1280 stream->indexes = NULL; 1316 stream->indexes = NULL;
1281 } 1317 }
1282 GST_DEBUG_OBJECT (avi, "index %s", ((*index) ? "!= 0" : "== 0")); 1318 /* get stream stats now */
1319 gst_avi_demux_do_index_stats (avi);
1320
1321 avi->have_index = TRUE;
1283} 1322}
1284#endif
1285 1323
1286/* 1324/*
1287 * gst_avi_demux_riff_parse_vprp: 1325 * gst_avi_demux_riff_parse_vprp:
@@ -2046,117 +2084,6 @@ gst_avi_demux_get_buffer_info (GstAviDemux * avi, GstAviStream * stream,
2046 } 2084 }
2047} 2085}
2048 2086
2049/* collect and debug stats about the indexes for all streams.
2050 * This method is also responsible for filling in the stream duration
2051 * as measured by the amount of index entries. */
2052static void
2053gst_avi_demux_do_index_stats (GstAviDemux * avi)
2054{
2055 guint i;
2056#ifndef GST_DISABLE_GST_DEBUG
2057 guint total_idx = 0, total_max = 0;
2058#endif
2059
2060 /* get stream stats now */
2061 for (i = 0; i < avi->num_streams; i++) {
2062 GstAviIndexEntry *entry;
2063 GstAviStream *stream;
2064 guint64 total;
2065
2066 if (G_UNLIKELY (!(stream = &avi->stream[i])))
2067 continue;
2068 if (G_UNLIKELY (!stream->strh))
2069 continue;
2070 if (G_UNLIKELY (!stream->index || stream->idx_n == 0))
2071 continue;
2072
2073 entry = &stream->index[stream->idx_n - 1];
2074 total = entry->total + entry->size;
2075
2076 /* calculate duration */
2077 if (stream->is_vbr) {
2078 /* VBR stream next timestamp */
2079 if (stream->strh->type == GST_RIFF_FCC_auds) {
2080 stream->idx_duration =
2081 avi_stream_convert_frames_to_time_unchecked (stream, total);
2082 } else {
2083 stream->idx_duration =
2084 avi_stream_convert_frames_to_time_unchecked (stream, stream->idx_n);
2085 }
2086 } else {
2087 /* constant rate stream */
2088 stream->idx_duration = avi_stream_convert_bytes_to_time_unchecked (stream,
2089 total);
2090 }
2091#ifndef GST_DISABLE_GST_DEBUG
2092 total_idx += stream->idx_n;
2093 total_max += stream->idx_max;
2094#endif
2095 GST_INFO_OBJECT (avi, "Stream %d, dur %" GST_TIME_FORMAT ", %6u entries, "
2096 "%5u keyframes, entry size = %2u, total size = %10u, allocated %10u",
2097 i, GST_TIME_ARGS (stream->idx_duration), stream->idx_n,
2098 stream->n_keyframes, (guint) sizeof (GstAviIndexEntry),
2099 (guint) (stream->idx_n * sizeof (GstAviIndexEntry)),
2100 (guint) (stream->idx_max * sizeof (GstAviIndexEntry)));
2101 }
2102#ifndef GST_DISABLE_GST_DEBUG
2103 total_idx *= sizeof (GstAviIndexEntry);
2104 total_max *= sizeof (GstAviIndexEntry);
2105#endif
2106 GST_INFO_OBJECT (avi, "%u bytes for index vs %u ideally, %u wasted",
2107 total_max, total_idx, total_max - total_idx);
2108}
2109
2110/* add an entry to the index of a stream. @num should be an estimate of the
2111 * total amount of index entries for all streams and is used to dynamically
2112 * allocate memory for the index entries. */
2113static inline gboolean
2114gst_avi_demux_add_index (GstAviDemux * avi, GstAviStream * stream,
2115 guint num, GstAviIndexEntry * entry)
2116{
2117 /* ensure index memory */
2118 if (G_UNLIKELY (stream->idx_n >= stream->idx_max)) {
2119 /* we need to make some more room */
2120 if (stream->idx_max == 0) {
2121 /* initial size guess, assume each stream has an equal amount of entries,
2122 * overshoot with at least 8K */
2123 stream->idx_max =
2124 (num / avi->num_streams) + (8192 / sizeof (GstAviIndexEntry));
2125 } else {
2126 stream->idx_max += 8192 / sizeof (GstAviIndexEntry);
2127 GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "expanded index to %u",
2128 stream->idx_max);
2129 }
2130 stream->index = g_try_renew (GstAviIndexEntry, stream->index,
2131 stream->idx_max);
2132 if (G_UNLIKELY (!stream->index))
2133 return FALSE;
2134 }
2135
2136 /* update stream stats and total size */
2137 entry->total = stream->total_bytes;
2138 stream->total_bytes += entry->size;
2139 if (stream->strh->type == GST_RIFF_FCC_auds) {
2140 gint blockalign = stream->strf.auds->blockalign;
2141 if (blockalign > 0)
2142 stream->total_blocks += DIV_ROUND_UP (entry->size, blockalign);
2143 else
2144 stream->total_blocks++;
2145 }
2146 if (ENTRY_IS_KEYFRAME (entry))
2147 stream->n_keyframes++;
2148
2149 /* and add */
2150 GST_LOG_OBJECT (avi,
2151 "Adding stream %u, index entry %d, kf %d, size %u "
2152 ", offset %" G_GUINT64_FORMAT ", total %" G_GUINT64_FORMAT, stream->num,
2153 stream->idx_n, ENTRY_IS_KEYFRAME (entry), entry->size, entry->offset,
2154 entry->total);
2155 stream->index[stream->idx_n++] = *entry;
2156
2157 return TRUE;
2158}
2159
2160static inline GstAviStream * 2087static inline GstAviStream *
2161gst_avi_demux_stream_for_id (GstAviDemux * avi, guint32 id) 2088gst_avi_demux_stream_for_id (GstAviDemux * avi, guint32 id)
2162{ 2089{
@@ -2199,7 +2126,7 @@ gst_avi_demux_parse_index (GstAviDemux * avi, GstBuffer * buf)
2199 guint32 id; 2126 guint32 id;
2200 2127
2201 if (!buf) 2128 if (!buf)
2202 goto empty_list; 2129 return FALSE;
2203 2130
2204 data = GST_BUFFER_DATA (buf); 2131 data = GST_BUFFER_DATA (buf);
2205 size = GST_BUFFER_SIZE (buf); 2132 size = GST_BUFFER_SIZE (buf);
@@ -2265,6 +2192,8 @@ gst_avi_demux_parse_index (GstAviDemux * avi, GstBuffer * buf)
2265 2192
2266 n++; 2193 n++;
2267 } 2194 }
2195 gst_buffer_unref (buf);
2196
2268 /* get stream stats now */ 2197 /* get stream stats now */
2269 gst_avi_demux_do_index_stats (avi); 2198 gst_avi_demux_do_index_stats (avi);
2270 2199
@@ -2281,6 +2210,7 @@ gst_avi_demux_parse_index (GstAviDemux * avi, GstBuffer * buf)
2281empty_list: 2210empty_list:
2282 { 2211 {
2283 GST_DEBUG_OBJECT (avi, "empty index"); 2212 GST_DEBUG_OBJECT (avi, "empty index");
2213 gst_buffer_unref (buf);
2284 return FALSE; 2214 return FALSE;
2285 } 2215 }
2286out_of_mem: 2216out_of_mem:
@@ -2289,6 +2219,7 @@ out_of_mem:
2289 ("Cannot allocate memory for %u*%u=%u bytes", 2219 ("Cannot allocate memory for %u*%u=%u bytes",
2290 (guint) sizeof (GstAviIndexEntry), num, 2220 (guint) sizeof (GstAviIndexEntry), num,
2291 (guint) sizeof (GstAviIndexEntry) * num)); 2221 (guint) sizeof (GstAviIndexEntry) * num));
2222 gst_buffer_unref (buf);
2292 return FALSE; 2223 return FALSE;
2293 } 2224 }
2294} 2225}
@@ -2353,7 +2284,6 @@ gst_avi_demux_stream_index (GstAviDemux * avi)
2353 GST_FOURCC_FORMAT, GST_BUFFER_SIZE (buf), GST_FOURCC_ARGS (tag)); 2284 GST_FOURCC_FORMAT, GST_BUFFER_SIZE (buf), GST_FOURCC_ARGS (tag));
2354 2285
2355 gst_avi_demux_parse_index (avi, buf); 2286 gst_avi_demux_parse_index (avi, buf);
2356 gst_buffer_unref (buf);
2357 2287
2358#ifndef GST_DISABLE_GST_DEBUG 2288#ifndef GST_DISABLE_GST_DEBUG
2359 /* debug our indexes */ 2289 /* debug our indexes */
@@ -2492,7 +2422,7 @@ gst_avi_demux_stream_scan (GstAviDemux * avi)
2492 GstFlowReturn res; 2422 GstFlowReturn res;
2493 GstAviStream *stream; 2423 GstAviStream *stream;
2494 GstFormat format; 2424 GstFormat format;
2495 guint64 pos; 2425 guint64 pos = 0;
2496 guint64 length; 2426 guint64 length;
2497 gint64 tmplength; 2427 gint64 tmplength;
2498 guint32 tag = 0; 2428 guint32 tag = 0;
@@ -2501,8 +2431,7 @@ gst_avi_demux_stream_scan (GstAviDemux * avi)
2501 /* FIXME: 2431 /* FIXME:
2502 * - implement non-seekable source support. 2432 * - implement non-seekable source support.
2503 */ 2433 */
2504 GST_DEBUG_OBJECT (avi, 2434 GST_DEBUG_OBJECT (avi, "Creating index");
2505 "Creating index starting at offset %" G_GUINT64_FORMAT, pos);
2506 2435
2507 /* get the size of the file */ 2436 /* get the size of the file */
2508 format = GST_FORMAT_BYTES; 2437 format = GST_FORMAT_BYTES;
@@ -3116,13 +3045,11 @@ skipping_done:
3116 GST_DEBUG_OBJECT (avi, "skipping done ... (streams=%u, stream[0].indexes=%p)", 3045 GST_DEBUG_OBJECT (avi, "skipping done ... (streams=%u, stream[0].indexes=%p)",
3117 avi->num_streams, avi->stream[0].indexes); 3046 avi->num_streams, avi->stream[0].indexes);
3118 3047
3119#if 0
3120 /* create or read stream index (for seeking) */ 3048 /* create or read stream index (for seeking) */
3121 if (avi->stream[0].indexes != NULL) { 3049 if (avi->stream[0].indexes != NULL) {
3122 /* we read a super index already (gst_avi_demux_parse_superindex() ) */ 3050 /* we read a super index already (gst_avi_demux_parse_superindex() ) */
3123 gst_avi_demux_read_subindexes_pull (avi, &index, &alloc); 3051 gst_avi_demux_read_subindexes_pull (avi);
3124 } 3052 }
3125#endif
3126 if (!avi->have_index) { 3053 if (!avi->have_index) {
3127 if (avi->avih->flags & GST_RIFF_AVIH_HASINDEX) 3054 if (avi->avih->flags & GST_RIFF_AVIH_HASINDEX)
3128 gst_avi_demux_stream_index (avi); 3055 gst_avi_demux_stream_index (avi);