summaryrefslogtreecommitdiff
path: root/gst/avi/gstavidemux.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst/avi/gstavidemux.c')
-rw-r--r--gst/avi/gstavidemux.c191
1 files changed, 95 insertions, 96 deletions
diff --git a/gst/avi/gstavidemux.c b/gst/avi/gstavidemux.c
index 0765bd856..9ec8d71df 100644
--- a/gst/avi/gstavidemux.c
+++ b/gst/avi/gstavidemux.c
@@ -53,7 +53,7 @@
53#include <gst/base/gstadapter.h> 53#include <gst/base/gstadapter.h>
54 54
55 55
56#define DIV_ROUND_UP(s,v) ((s) + ((v)-1) / (v)) 56#define DIV_ROUND_UP(s,v) (((s) + ((v)-1)) / (v))
57 57
58GST_DEBUG_CATEGORY_STATIC (avidemux_debug); 58GST_DEBUG_CATEGORY_STATIC (avidemux_debug);
59#define GST_CAT_DEFAULT avidemux_debug 59#define GST_CAT_DEFAULT avidemux_debug
@@ -1004,33 +1004,51 @@ gst_avi_demux_add_index (GstAviDemux * avi, GstAviStream * stream,
1004{ 1004{
1005 /* ensure index memory */ 1005 /* ensure index memory */
1006 if (G_UNLIKELY (stream->idx_n >= stream->idx_max)) { 1006 if (G_UNLIKELY (stream->idx_n >= stream->idx_max)) {
1007 guint idx_max = stream->idx_max;
1008 GstAviIndexEntry *new_idx;
1009
1007 /* we need to make some more room */ 1010 /* we need to make some more room */
1008 if (stream->idx_max == 0) { 1011 if (idx_max == 0) {
1009 /* initial size guess, assume each stream has an equal amount of entries, 1012 /* initial size guess, assume each stream has an equal amount of entries,
1010 * overshoot with at least 8K */ 1013 * overshoot with at least 8K */
1011 stream->idx_max = 1014 idx_max = (num / avi->num_streams) + (8192 / sizeof (GstAviIndexEntry));
1012 (num / avi->num_streams) + (8192 / sizeof (GstAviIndexEntry));
1013 } else { 1015 } else {
1014 stream->idx_max += 8192 / sizeof (GstAviIndexEntry); 1016 idx_max += 8192 / sizeof (GstAviIndexEntry);
1015 GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "expanded index to %u", 1017 GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "expanded index from %u to %u",
1016 stream->idx_max); 1018 stream->idx_max, idx_max);
1017 } 1019 }
1018 stream->index = g_try_renew (GstAviIndexEntry, stream->index, 1020 new_idx = g_try_renew (GstAviIndexEntry, stream->index, idx_max);
1019 stream->idx_max); 1021 /* out of memory, if this fails stream->index is untouched. */
1020 if (G_UNLIKELY (!stream->index)) 1022 if (G_UNLIKELY (!new_idx))
1021 return FALSE; 1023 return FALSE;
1024 /* use new index */
1025 stream->index = new_idx;
1026 stream->idx_max = idx_max;
1022 } 1027 }
1023 1028
1024 /* update stream stats and total size */ 1029 /* update entry total and stream stats. The entry total can be converted to
1025 entry->total = stream->total_bytes; 1030 * the timestamp of the entry easily. */
1026 stream->total_bytes += entry->size;
1027 if (stream->strh->type == GST_RIFF_FCC_auds) { 1031 if (stream->strh->type == GST_RIFF_FCC_auds) {
1028 gint blockalign = stream->strf.auds->blockalign; 1032 gint blockalign;
1033
1034 if (stream->is_vbr) {
1035 entry->total = stream->total_blocks;
1036 } else {
1037 entry->total = stream->total_bytes;
1038 }
1039 blockalign = stream->strf.auds->blockalign;
1029 if (blockalign > 0) 1040 if (blockalign > 0)
1030 stream->total_blocks += DIV_ROUND_UP (entry->size, blockalign); 1041 stream->total_blocks += DIV_ROUND_UP (entry->size, blockalign);
1031 else 1042 else
1032 stream->total_blocks++; 1043 stream->total_blocks++;
1044 } else {
1045 if (stream->is_vbr) {
1046 entry->total = stream->idx_n;
1047 } else {
1048 entry->total = stream->total_bytes;
1049 }
1033 } 1050 }
1051 stream->total_bytes += entry->size;
1034 if (ENTRY_IS_KEYFRAME (entry)) 1052 if (ENTRY_IS_KEYFRAME (entry))
1035 stream->n_keyframes++; 1053 stream->n_keyframes++;
1036 1054
@@ -1045,6 +1063,58 @@ gst_avi_demux_add_index (GstAviDemux * avi, GstAviStream * stream,
1045 return TRUE; 1063 return TRUE;
1046} 1064}
1047 1065
1066/* given @entry_n in @stream, calculate info such as timestamps and
1067 * offsets for the entry. */
1068static void
1069gst_avi_demux_get_buffer_info (GstAviDemux * avi, GstAviStream * stream,
1070 guint entry_n, GstClockTime * timestamp, GstClockTime * ts_end,
1071 guint64 * offset, guint64 * offset_end)
1072{
1073 GstAviIndexEntry *entry;
1074
1075 entry = &stream->index[entry_n];
1076
1077 if (stream->is_vbr) {
1078 /* VBR stream next timestamp */
1079 if (stream->strh->type == GST_RIFF_FCC_auds) {
1080 if (timestamp)
1081 *timestamp =
1082 avi_stream_convert_frames_to_time_unchecked (stream, entry->total);
1083 if (ts_end)
1084 *ts_end = avi_stream_convert_frames_to_time_unchecked (stream,
1085 entry->total + 1);
1086 } else {
1087 if (timestamp)
1088 *timestamp =
1089 avi_stream_convert_frames_to_time_unchecked (stream, entry_n);
1090 if (ts_end)
1091 *ts_end = avi_stream_convert_frames_to_time_unchecked (stream,
1092 entry_n + 1);
1093 }
1094 } else {
1095 /* constant rate stream */
1096 if (timestamp)
1097 *timestamp =
1098 avi_stream_convert_bytes_to_time_unchecked (stream, entry->total);
1099 if (ts_end)
1100 *ts_end = avi_stream_convert_bytes_to_time_unchecked (stream,
1101 entry->total + entry->size);
1102 }
1103 if (stream->strh->type == GST_RIFF_FCC_vids) {
1104 /* video offsets are the frame number */
1105 if (offset)
1106 *offset = entry_n;
1107 if (offset_end)
1108 *offset_end = entry_n + 1;
1109 } else {
1110 /* no offsets for audio */
1111 if (offset)
1112 *offset = -1;
1113 if (offset_end)
1114 *offset_end = -1;
1115 }
1116}
1117
1048/* collect and debug stats about the indexes for all streams. 1118/* collect and debug stats about the indexes for all streams.
1049 * This method is also responsible for filling in the stream duration 1119 * This method is also responsible for filling in the stream duration
1050 * as measured by the amount of index entries. */ 1120 * as measured by the amount of index entries. */
@@ -1058,9 +1128,7 @@ gst_avi_demux_do_index_stats (GstAviDemux * avi)
1058 1128
1059 /* get stream stats now */ 1129 /* get stream stats now */
1060 for (i = 0; i < avi->num_streams; i++) { 1130 for (i = 0; i < avi->num_streams; i++) {
1061 GstAviIndexEntry *entry;
1062 GstAviStream *stream; 1131 GstAviStream *stream;
1063 guint64 total;
1064 1132
1065 if (G_UNLIKELY (!(stream = &avi->stream[i]))) 1133 if (G_UNLIKELY (!(stream = &avi->stream[i])))
1066 continue; 1134 continue;
@@ -1069,24 +1137,11 @@ gst_avi_demux_do_index_stats (GstAviDemux * avi)
1069 if (G_UNLIKELY (!stream->index || stream->idx_n == 0)) 1137 if (G_UNLIKELY (!stream->index || stream->idx_n == 0))
1070 continue; 1138 continue;
1071 1139
1072 entry = &stream->index[stream->idx_n - 1]; 1140 /* we interested in the end_ts of the last entry, which is the total
1073 total = entry->total + entry->size; 1141 * duration of this stream */
1142 gst_avi_demux_get_buffer_info (avi, stream, stream->idx_n - 1,
1143 NULL, &stream->idx_duration, NULL, NULL);
1074 1144
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 1145#ifndef GST_DISABLE_GST_DEBUG
1091 total_idx += stream->idx_n; 1146 total_idx += stream->idx_n;
1092 total_max += stream->idx_max; 1147 total_max += stream->idx_max;
@@ -2032,58 +2087,6 @@ gst_avi_demux_index_for_time (GstAviDemux * avi,
2032 return index; 2087 return index;
2033} 2088}
2034 2089
2035/* given @entry_n in @stream, calculate info such as timestamps and
2036 * offsets for the entry. */
2037static void
2038gst_avi_demux_get_buffer_info (GstAviDemux * avi, GstAviStream * stream,
2039 guint entry_n, GstClockTime * timestamp, GstClockTime * ts_end,
2040 guint64 * offset, guint64 * offset_end)
2041{
2042 GstAviIndexEntry *entry;
2043
2044 entry = &stream->index[entry_n];
2045
2046 if (stream->is_vbr) {
2047 /* VBR stream next timestamp */
2048 if (stream->strh->type == GST_RIFF_FCC_auds) {
2049 if (timestamp)
2050 *timestamp =
2051 avi_stream_convert_frames_to_time_unchecked (stream, entry->total);
2052 if (ts_end)
2053 *ts_end = avi_stream_convert_frames_to_time_unchecked (stream,
2054 entry->total + entry->size);
2055 } else {
2056 if (timestamp)
2057 *timestamp =
2058 avi_stream_convert_frames_to_time_unchecked (stream, entry_n);
2059 if (ts_end)
2060 *ts_end = avi_stream_convert_frames_to_time_unchecked (stream,
2061 entry_n + 1);
2062 }
2063 } else {
2064 /* constant rate stream */
2065 if (timestamp)
2066 *timestamp =
2067 avi_stream_convert_bytes_to_time_unchecked (stream, entry->total);
2068 if (ts_end)
2069 *ts_end = avi_stream_convert_bytes_to_time_unchecked (stream,
2070 entry->total + entry->size);
2071 }
2072 if (stream->strh->type == GST_RIFF_FCC_vids) {
2073 /* video offsets are the frame number */
2074 if (offset)
2075 *offset = entry_n;
2076 if (offset_end)
2077 *offset_end = entry_n + 1;
2078 } else {
2079 /* no offsets for audio */
2080 if (offset)
2081 *offset = -1;
2082 if (offset_end)
2083 *offset_end = -1;
2084 }
2085}
2086
2087static inline GstAviStream * 2090static inline GstAviStream *
2088gst_avi_demux_stream_for_id (GstAviDemux * avi, guint32 id) 2091gst_avi_demux_stream_for_id (GstAviDemux * avi, guint32 id)
2089{ 2092{
@@ -3525,7 +3528,8 @@ gst_avi_demux_combine_flows (GstAviDemux * avi, GstAviStream * stream,
3525 /* if we get here, all other pads were unlinked and we return 3528 /* if we get here, all other pads were unlinked and we return
3526 * NOT_LINKED then */ 3529 * NOT_LINKED then */
3527done: 3530done:
3528 GST_LOG_OBJECT (avi, "combined return %s", gst_flow_get_name (ret)); 3531 GST_LOG_OBJECT (avi, "combined %s to return %s",
3532 gst_flow_get_name (stream->last_flow), gst_flow_get_name (ret));
3529 return ret; 3533 return ret;
3530} 3534}
3531 3535
@@ -3737,23 +3741,20 @@ gst_avi_demux_loop_data (GstAviDemux * avi)
3737 3741
3738 gst_buffer_set_caps (buf, GST_PAD_CAPS (stream->pad)); 3742 gst_buffer_set_caps (buf, GST_PAD_CAPS (stream->pad));
3739 3743
3744 /* update current position in the segment */
3745 gst_segment_set_last_stop (&avi->segment, GST_FORMAT_TIME, timestamp);
3746
3740 GST_DEBUG_OBJECT (avi, "Pushing buffer of size %u, ts %" 3747 GST_DEBUG_OBJECT (avi, "Pushing buffer of size %u, ts %"
3741 GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", off %" G_GUINT64_FORMAT 3748 GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", off %" G_GUINT64_FORMAT
3742 ", off_end %" G_GUINT64_FORMAT " on pad %s", 3749 ", off_end %" G_GUINT64_FORMAT,
3743 GST_BUFFER_SIZE (buf), GST_TIME_ARGS (timestamp), 3750 GST_BUFFER_SIZE (buf), GST_TIME_ARGS (timestamp),
3744 GST_TIME_ARGS (duration), GST_BUFFER_OFFSET (buf), 3751 GST_TIME_ARGS (duration), out_offset, out_offset_end);
3745 GST_BUFFER_OFFSET_END (buf), GST_PAD_NAME (stream->pad));
3746
3747 /* update current position in the segment */
3748 gst_segment_set_last_stop (&avi->segment, GST_FORMAT_TIME, timestamp);
3749 3752
3750 ret = gst_pad_push (stream->pad, buf); 3753 ret = gst_pad_push (stream->pad, buf);
3751 3754
3752 /* mark as processed, we increment the frame and byte counters then 3755 /* mark as processed, we increment the frame and byte counters then
3753 * leave the while loop and return the GstFlowReturn */ 3756 * leave the while loop and return the GstFlowReturn */
3754 processed = TRUE; 3757 processed = TRUE;
3755 GST_DEBUG_OBJECT (avi, "Processed buffer %u: %s", stream->current_entry,
3756 gst_flow_get_name (ret));
3757 3758
3758 if (avi->segment.rate < 0) { 3759 if (avi->segment.rate < 0) {
3759 if (timestamp > avi->segment.stop && ret == GST_FLOW_UNEXPECTED) { 3760 if (timestamp > avi->segment.stop && ret == GST_FLOW_UNEXPECTED) {
@@ -4072,8 +4073,6 @@ gst_avi_demux_loop (GstPad * pad)
4072 goto pause; 4073 goto pause;
4073 } 4074 }
4074 4075
4075 GST_LOG_OBJECT (avi, "state: %d res:%s", avi->state, gst_flow_get_name (res));
4076
4077 return; 4076 return;
4078 4077
4079 /* ERRORS */ 4078 /* ERRORS */