mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-18 07:47:17 +00:00
qtdemux: split large raw audio samples
In order to deal with a file that has samples that are 24 seconds long. Seeking still doesn't work with such files.
This commit is contained in:
parent
364433c105
commit
5bd2864101
1 changed files with 67 additions and 8 deletions
|
@ -219,6 +219,8 @@ struct _QtDemuxStream
|
|||
gboolean all_keyframe; /* TRUE when all samples are keyframes (no stss) */
|
||||
guint32 min_duration; /* duration in timescale of first sample, used for figuring out
|
||||
the framerate, in timescale units */
|
||||
guint32 offset_in_sample;
|
||||
guint32 max_buffer_size;
|
||||
|
||||
/* if we use chunks or samples */
|
||||
gboolean sampled;
|
||||
|
@ -1089,6 +1091,7 @@ gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
|
|||
|
||||
/* position changed, we have a discont */
|
||||
str->sample_index = index;
|
||||
str->offset_in_sample = 0;
|
||||
/* Each time we move in the stream we store the position where we are
|
||||
* starting from */
|
||||
str->from_sample = index;
|
||||
|
@ -1327,6 +1330,7 @@ gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment)
|
|||
|
||||
stream->time_position = desired_offset;
|
||||
stream->sample_index = -1;
|
||||
stream->offset_in_sample = 0;
|
||||
stream->segment_index = -1;
|
||||
stream->last_ret = GST_FLOW_OK;
|
||||
stream->sent_eos = FALSE;
|
||||
|
@ -3303,6 +3307,7 @@ gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
|
|||
|
||||
/* move to next sample */
|
||||
stream->sample_index++;
|
||||
stream->offset_in_sample = 0;
|
||||
|
||||
/* get current segment */
|
||||
segment = &stream->segments[stream->segment_index];
|
||||
|
@ -3773,7 +3778,8 @@ gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
|
|||
guint64 pts = GST_CLOCK_TIME_NONE;
|
||||
guint64 duration = 0;
|
||||
gboolean keyframe = FALSE;
|
||||
guint size = 0;
|
||||
guint sample_size = 0;
|
||||
guint size;
|
||||
gint index;
|
||||
gint i;
|
||||
|
||||
|
@ -3830,23 +3836,33 @@ gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
|
|||
|
||||
/* fetch info for the current sample of this stream */
|
||||
if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &offset,
|
||||
&size, &dts, &pts, &duration, &keyframe)))
|
||||
&sample_size, &dts, &pts, &duration, &keyframe)))
|
||||
goto eos_stream;
|
||||
|
||||
GST_LOG_OBJECT (qtdemux,
|
||||
GST_DEBUG_OBJECT (qtdemux,
|
||||
"pushing from stream %d, offset %" G_GUINT64_FORMAT
|
||||
", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
|
||||
", duration %" GST_TIME_FORMAT, index, offset, size,
|
||||
", duration %" GST_TIME_FORMAT, index, offset, sample_size,
|
||||
GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
|
||||
|
||||
/* hmm, empty sample, skip and move to next sample */
|
||||
if (G_UNLIKELY (size <= 0))
|
||||
if (G_UNLIKELY (sample_size <= 0))
|
||||
goto next;
|
||||
|
||||
/* last pushed sample was out of boundary, goto next sample */
|
||||
if (G_UNLIKELY (stream->last_ret == GST_FLOW_EOS))
|
||||
goto next;
|
||||
|
||||
if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
|
||||
size = sample_size;
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (qtdemux,
|
||||
"size %d larger than stream max_buffer_size %d, trimming",
|
||||
sample_size, stream->max_buffer_size);
|
||||
size =
|
||||
MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
|
||||
offset);
|
||||
|
||||
|
@ -3855,13 +3871,43 @@ gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
|
|||
buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
|
||||
}
|
||||
|
||||
ret = gst_qtdemux_pull_atom (qtdemux, offset, size, &buf);
|
||||
ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
|
||||
size, &buf);
|
||||
if (G_UNLIKELY (ret != GST_FLOW_OK))
|
||||
goto beach;
|
||||
|
||||
if (size != sample_size) {
|
||||
pts += gst_util_uint64_scale_int (GST_SECOND,
|
||||
stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
|
||||
dts += gst_util_uint64_scale_int (GST_SECOND,
|
||||
stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
|
||||
duration = gst_util_uint64_scale_int (GST_SECOND,
|
||||
size / stream->bytes_per_frame, stream->timescale);
|
||||
}
|
||||
|
||||
ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
|
||||
dts, pts, duration, keyframe, min_time, offset);
|
||||
|
||||
if (size != sample_size) {
|
||||
QtDemuxSample *sample = &stream->samples[stream->sample_index];
|
||||
QtDemuxSegment *segment = &stream->segments[stream->segment_index];
|
||||
|
||||
GstClockTime time_position = gst_util_uint64_scale (sample->timestamp +
|
||||
stream->offset_in_sample / stream->bytes_per_frame, GST_SECOND,
|
||||
stream->timescale);
|
||||
if (time_position >= segment->media_start) {
|
||||
/* inside the segment, update time_position, looks very familiar to
|
||||
* GStreamer segments, doesn't it? */
|
||||
stream->time_position = (time_position - segment->media_start) +
|
||||
segment->time;
|
||||
} else {
|
||||
/* not yet in segment, time does not yet increment. This means
|
||||
* that we are still prerolling keyframes to the decoder so it can
|
||||
* decode the first sample of the segment. */
|
||||
stream->time_position = segment->time;
|
||||
}
|
||||
}
|
||||
|
||||
/* combine flows */
|
||||
ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
|
||||
/* ignore unlinked, we will not push on the pad anymore and we will EOS when
|
||||
|
@ -3869,6 +3915,12 @@ gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
|
|||
if (ret == GST_FLOW_EOS)
|
||||
ret = GST_FLOW_OK;
|
||||
|
||||
stream->offset_in_sample += size;
|
||||
if (stream->offset_in_sample >= sample_size) {
|
||||
gst_qtdemux_advance_sample (qtdemux, stream);
|
||||
}
|
||||
goto beach;
|
||||
|
||||
next:
|
||||
gst_qtdemux_advance_sample (qtdemux, stream);
|
||||
|
||||
|
@ -4009,8 +4061,10 @@ next_entry_size (GstQTDemux * demux)
|
|||
for (i = 0; i < demux->n_streams; i++) {
|
||||
stream = demux->streams[i];
|
||||
|
||||
if (stream->sample_index == -1)
|
||||
if (stream->sample_index == -1) {
|
||||
stream->sample_index = 0;
|
||||
stream->offset_in_sample = 0;
|
||||
}
|
||||
|
||||
if (stream->sample_index >= stream->n_samples) {
|
||||
GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
|
||||
|
@ -4469,6 +4523,7 @@ gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
|
|||
ret = gst_qtdemux_combine_flows (demux, stream, ret);
|
||||
|
||||
stream->sample_index++;
|
||||
stream->offset_in_sample = 0;
|
||||
|
||||
/* update current offset and figure out size of next buffer */
|
||||
GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
|
||||
|
@ -5805,7 +5860,8 @@ qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
|
|||
|
||||
for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
|
||||
GST_LOG_OBJECT (qtdemux, "Creating entry %d with offset %"
|
||||
G_GUINT64_FORMAT, (guint) (cur - samples), stream->chunk_offset);
|
||||
G_GUINT64_FORMAT "and size %d",
|
||||
(guint) (cur - samples), stream->chunk_offset, cur->size);
|
||||
|
||||
cur->offset = chunk_offset;
|
||||
chunk_offset += cur->size;
|
||||
|
@ -6504,6 +6560,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
|
|||
stream->segment_index = -1;
|
||||
stream->time_position = 0;
|
||||
stream->sample_index = -1;
|
||||
stream->offset_in_sample = 0;
|
||||
stream->last_ret = GST_FLOW_OK;
|
||||
|
||||
if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
|
||||
|
@ -9987,6 +10044,8 @@ qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
|
|||
name = gst_structure_get_name (s);
|
||||
if (g_str_has_prefix (name, "audio/x-raw")) {
|
||||
stream->need_clip = TRUE;
|
||||
stream->max_buffer_size = 4096 * stream->bytes_per_frame;
|
||||
GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
|
||||
}
|
||||
return caps;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue