diff options
Diffstat (limited to 'gst/avi/gstavidemux.c')
-rw-r--r-- | gst/avi/gstavidemux.c | 191 |
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 | ||
58 | GST_DEBUG_CATEGORY_STATIC (avidemux_debug); | 58 | GST_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. */ | ||
1068 | static void | ||
1069 | gst_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. */ | ||
2037 | static void | ||
2038 | gst_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 | |||
2087 | static inline GstAviStream * | 2090 | static inline GstAviStream * |
2088 | gst_avi_demux_stream_for_id (GstAviDemux * avi, guint32 id) | 2091 | gst_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 */ |
3527 | done: | 3530 | done: |
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 */ |