mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-24 08:08:22 +00:00
dashdemux: Store parsed moof and extract offsets of sync samples in it
https://bugzilla.gnome.org/show_bug.cgi?id=741104
This commit is contained in:
parent
6dbfb1133c
commit
5b943135ac
2 changed files with 213 additions and 26 deletions
|
@ -216,6 +216,12 @@ struct _GstDashDemuxClockDrift
|
||||||
GstClock *ntp_clock;
|
GstClock *ntp_clock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
guint64 start_offset, end_offset;
|
||||||
|
/* TODO: Timestamp and duration */
|
||||||
|
} GstDashStreamSyncSample;
|
||||||
|
|
||||||
/* GObject */
|
/* GObject */
|
||||||
static void gst_dash_demux_set_property (GObject * object, guint prop_id,
|
static void gst_dash_demux_set_property (GObject * object, guint prop_id,
|
||||||
const GValue * value, GParamSpec * pspec);
|
const GValue * value, GParamSpec * pspec);
|
||||||
|
@ -1172,6 +1178,13 @@ gst_dash_demux_stream_seek (GstAdaptiveDemuxStream * stream, gboolean forward,
|
||||||
GstDashDemuxStream *dashstream = (GstDashDemuxStream *) stream;
|
GstDashDemuxStream *dashstream = (GstDashDemuxStream *) stream;
|
||||||
GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (stream->demux);
|
GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (stream->demux);
|
||||||
|
|
||||||
|
if (dashstream->moof)
|
||||||
|
gst_isoff_moof_box_free (dashstream->moof);
|
||||||
|
dashstream->moof = NULL;
|
||||||
|
if (dashstream->moof_sync_samples)
|
||||||
|
g_array_free (dashstream->moof_sync_samples, TRUE);
|
||||||
|
dashstream->moof_sync_samples = NULL;
|
||||||
|
|
||||||
if (gst_mpd_client_has_isoff_ondemand_profile (dashdemux->client)) {
|
if (gst_mpd_client_has_isoff_ondemand_profile (dashdemux->client)) {
|
||||||
if (dashstream->sidx_parser.status == GST_ISOFF_SIDX_PARSER_FINISHED) {
|
if (dashstream->sidx_parser.status == GST_ISOFF_SIDX_PARSER_FINISHED) {
|
||||||
gst_dash_demux_stream_sidx_seek (dashstream, forward, flags, ts,
|
gst_dash_demux_stream_sidx_seek (dashstream, forward, flags, ts,
|
||||||
|
@ -1266,6 +1279,13 @@ gst_dash_demux_clear_pending_stream_data (GstDashDemux * dashdemux,
|
||||||
dashstream->isobmff_parser.current_start_offset = 0;
|
dashstream->isobmff_parser.current_start_offset = 0;
|
||||||
dashstream->isobmff_parser.current_offset = 0;
|
dashstream->isobmff_parser.current_offset = 0;
|
||||||
dashstream->isobmff_parser.current_size = 0;
|
dashstream->isobmff_parser.current_size = 0;
|
||||||
|
|
||||||
|
if (dashstream->moof)
|
||||||
|
gst_isoff_moof_box_free (dashstream->moof);
|
||||||
|
dashstream->moof = NULL;
|
||||||
|
if (dashstream->moof_sync_samples)
|
||||||
|
g_array_free (dashstream->moof_sync_samples, TRUE);
|
||||||
|
dashstream->moof_sync_samples = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
|
@ -1276,12 +1296,29 @@ gst_dash_demux_stream_advance_fragment (GstAdaptiveDemuxStream * stream)
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (stream->pad, "Advance fragment");
|
GST_DEBUG_OBJECT (stream->pad, "Advance fragment");
|
||||||
|
|
||||||
|
if (dashstream->isobmff_adapter)
|
||||||
|
gst_adapter_clear (dashstream->isobmff_adapter);
|
||||||
|
dashstream->isobmff_parser.current_fourcc = 0;
|
||||||
|
dashstream->isobmff_parser.current_start_offset = 0;
|
||||||
|
dashstream->isobmff_parser.current_offset = 0;
|
||||||
|
dashstream->isobmff_parser.current_size = 0;
|
||||||
|
|
||||||
|
if (dashstream->moof)
|
||||||
|
gst_isoff_moof_box_free (dashstream->moof);
|
||||||
|
dashstream->moof = NULL;
|
||||||
|
if (dashstream->moof_sync_samples)
|
||||||
|
g_array_free (dashstream->moof_sync_samples, TRUE);
|
||||||
|
dashstream->moof_sync_samples = NULL;
|
||||||
|
|
||||||
if (gst_mpd_client_has_isoff_ondemand_profile (dashdemux->client)) {
|
if (gst_mpd_client_has_isoff_ondemand_profile (dashdemux->client)) {
|
||||||
if (gst_dash_demux_stream_advance_subfragment (stream))
|
if (gst_dash_demux_stream_advance_subfragment (stream))
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_dash_demux_clear_pending_stream_data (dashdemux, dashstream);
|
gst_isoff_sidx_parser_clear (&dashstream->sidx_parser);
|
||||||
|
gst_isoff_sidx_parser_init (&dashstream->sidx_parser);
|
||||||
|
if (dashstream->sidx_adapter)
|
||||||
|
gst_adapter_clear (dashstream->sidx_adapter);
|
||||||
|
|
||||||
return gst_mpd_client_advance_segment (dashdemux->client,
|
return gst_mpd_client_advance_segment (dashdemux->client,
|
||||||
dashstream->active_stream, stream->demux->segment.rate > 0.0);
|
dashstream->active_stream, stream->demux->segment.rate > 0.0);
|
||||||
|
@ -1805,12 +1842,13 @@ gst_dash_demux_parse_isobmff (GstAdaptiveDemux * demux,
|
||||||
|
|
||||||
if (dash_stream->isobmff_parser.current_fourcc == GST_ISOFF_FOURCC_MOOF) {
|
if (dash_stream->isobmff_parser.current_fourcc == GST_ISOFF_FOURCC_MOOF) {
|
||||||
GstByteReader sub_reader;
|
GstByteReader sub_reader;
|
||||||
GstMoofBox *moof;
|
|
||||||
|
|
||||||
|
g_assert (dash_stream->moof == NULL);
|
||||||
|
g_assert (dash_stream->moof_sync_samples == NULL);
|
||||||
gst_byte_reader_get_sub_reader (&reader, &sub_reader, size - header_size);
|
gst_byte_reader_get_sub_reader (&reader, &sub_reader, size - header_size);
|
||||||
moof = gst_isoff_moof_box_parse (&sub_reader);
|
dash_stream->moof = gst_isoff_moof_box_parse (&sub_reader);
|
||||||
/* TODO: Do something with this */
|
dash_stream->moof_offset =
|
||||||
gst_isoff_moof_box_free (moof);
|
dash_stream->isobmff_parser.current_start_offset;
|
||||||
} else {
|
} else {
|
||||||
gst_byte_reader_skip (&reader, size - header_size);
|
gst_byte_reader_skip (&reader, size - header_size);
|
||||||
}
|
}
|
||||||
|
@ -1871,6 +1909,132 @@ gst_dash_demux_parse_isobmff (GstAdaptiveDemux * demux,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_dash_demux_find_sync_samples (GstAdaptiveDemux * demux,
|
||||||
|
GstAdaptiveDemuxStream * stream)
|
||||||
|
{
|
||||||
|
GstDashDemuxStream *dash_stream = (GstDashDemuxStream *) stream;
|
||||||
|
guint i;
|
||||||
|
guint32 track_id = 0;
|
||||||
|
guint64 prev_traf_end;
|
||||||
|
|
||||||
|
if (!dash_stream->moof)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
dash_stream->moof_sync_samples =
|
||||||
|
g_array_new (FALSE, FALSE, sizeof (GstDashStreamSyncSample));
|
||||||
|
|
||||||
|
prev_traf_end = dash_stream->moof_offset;
|
||||||
|
|
||||||
|
/* generate table of keyframes and offsets */
|
||||||
|
for (i = 0; i < dash_stream->moof->traf->len; i++) {
|
||||||
|
GstTrafBox *traf = &g_array_index (dash_stream->moof->traf, GstTrafBox, i);
|
||||||
|
guint64 traf_offset = 0, prev_trun_end;
|
||||||
|
guint j;
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
track_id = traf->tfhd.track_id;
|
||||||
|
} else if (track_id != traf->tfhd.track_id) {
|
||||||
|
GST_ERROR_OBJECT (stream->pad,
|
||||||
|
"moof with trafs of different track ids (%u != %u)", track_id,
|
||||||
|
traf->tfhd.track_id);
|
||||||
|
g_array_free (dash_stream->moof_sync_samples, TRUE);
|
||||||
|
dash_stream->moof_sync_samples = NULL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (traf->tfhd.flags & GST_TFHD_FLAGS_BASE_DATA_OFFSET_PRESENT) {
|
||||||
|
traf_offset = traf->tfhd.base_data_offset;
|
||||||
|
} else if (traf->tfhd.flags & GST_TFHD_FLAGS_DEFAULT_BASE_IS_MOOF) {
|
||||||
|
traf_offset = dash_stream->moof_offset;
|
||||||
|
} else {
|
||||||
|
traf_offset = prev_traf_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_trun_end = traf_offset;
|
||||||
|
|
||||||
|
for (j = 0; j < traf->trun->len; j++) {
|
||||||
|
GstTrunBox *trun = &g_array_index (traf->trun, GstTrunBox, j);
|
||||||
|
guint64 trun_offset, prev_sample_end;
|
||||||
|
guint k;
|
||||||
|
|
||||||
|
if (trun->flags & GST_TRUN_FLAGS_DATA_OFFSET_PRESENT) {
|
||||||
|
trun_offset = traf_offset + trun->data_offset;
|
||||||
|
} else {
|
||||||
|
trun_offset = prev_trun_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_sample_end = trun_offset;
|
||||||
|
for (k = 0; k < trun->samples->len; k++) {
|
||||||
|
GstTrunSample *sample =
|
||||||
|
&g_array_index (trun->samples, GstTrunSample, k);
|
||||||
|
guint64 sample_offset;
|
||||||
|
guint32 sample_flags;
|
||||||
|
#if 0
|
||||||
|
guint32 sample_duration;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sample_offset = prev_sample_end;
|
||||||
|
|
||||||
|
if (trun->flags & GST_TRUN_FLAGS_SAMPLE_FLAGS_PRESENT) {
|
||||||
|
sample_flags = sample->sample_flags;
|
||||||
|
} else if ((trun->flags & GST_TRUN_FLAGS_FIRST_SAMPLE_FLAGS_PRESENT)
|
||||||
|
&& k == 0) {
|
||||||
|
sample_flags = trun->first_sample_flags;
|
||||||
|
} else if (traf->
|
||||||
|
tfhd.flags & GST_TFHD_FLAGS_DEFAULT_SAMPLE_FLAGS_PRESENT) {
|
||||||
|
sample_flags = traf->tfhd.default_sample_flags;
|
||||||
|
} else {
|
||||||
|
GST_ERROR_OBJECT (stream->pad, "Sample flags given by trex");
|
||||||
|
g_array_free (dash_stream->moof_sync_samples, TRUE);
|
||||||
|
dash_stream->moof_sync_samples = NULL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (trun->flags & GST_TRUN_FLAGS_SAMPLE_DURATION_PRESENT) {
|
||||||
|
sample_duration = sample->sample_duration;
|
||||||
|
} else if (traf->
|
||||||
|
tfhd.flags & GST_TFHD_FLAGS_DEFAULT_SAMPLE_DURATION_PRESENT) {
|
||||||
|
sample_duration = traf->tfhd.default_sample_duration;
|
||||||
|
} else {
|
||||||
|
GST_ERROR_OBJECT (stream->pad, "Sample duration given by trex");
|
||||||
|
g_array_free (dash_stream->moof_sync_samples, TRUE);
|
||||||
|
dash_stream->moof_sync_samples = NULL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (trun->flags & GST_TRUN_FLAGS_SAMPLE_SIZE_PRESENT) {
|
||||||
|
prev_sample_end += sample->sample_size;
|
||||||
|
} else if (traf->
|
||||||
|
tfhd.flags & GST_TFHD_FLAGS_DEFAULT_SAMPLE_SIZE_PRESENT) {
|
||||||
|
prev_sample_end += traf->tfhd.default_sample_size;
|
||||||
|
} else {
|
||||||
|
GST_ERROR_OBJECT (stream->pad, "Sample size given by trex");
|
||||||
|
g_array_free (dash_stream->moof_sync_samples, TRUE);
|
||||||
|
dash_stream->moof_sync_samples = NULL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Non-non-sync sample aka sync sample */
|
||||||
|
if (!GST_ISOFF_SAMPLE_FLAGS_SAMPLE_IS_NON_SYNC_SAMPLE (sample_flags)) {
|
||||||
|
GstDashStreamSyncSample sync_sample =
|
||||||
|
{ sample_offset, prev_sample_end - 1 };
|
||||||
|
/* TODO: need timestamps so we can decide to download or not */
|
||||||
|
g_array_append_val (dash_stream->moof_sync_samples, sync_sample);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_trun_end = prev_sample_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_traf_end = prev_trun_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_dash_demux_data_received (GstAdaptiveDemux * demux,
|
gst_dash_demux_data_received (GstAdaptiveDemux * demux,
|
||||||
GstAdaptiveDemuxStream * stream, GstBuffer * buffer)
|
GstAdaptiveDemuxStream * stream, GstBuffer * buffer)
|
||||||
|
@ -1891,13 +2055,21 @@ gst_dash_demux_data_received (GstAdaptiveDemux * demux,
|
||||||
buffer)) != GST_FLOW_OK)
|
buffer)) != GST_FLOW_OK)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (dash_stream->isobmff_parser.current_fourcc == GST_ISOFF_FOURCC_MDAT
|
if (dash_stream->isobmff_parser.current_fourcc == GST_ISOFF_FOURCC_MDAT) {
|
||||||
&& gst_adapter_available (dash_stream->isobmff_adapter) > 0) {
|
gst_dash_demux_find_sync_samples (demux, stream);
|
||||||
|
if (gst_adapter_available (dash_stream->isobmff_adapter) > 0) {
|
||||||
buffer =
|
buffer =
|
||||||
gst_adapter_take_buffer (dash_stream->isobmff_adapter,
|
gst_adapter_take_buffer (dash_stream->isobmff_adapter,
|
||||||
gst_adapter_available (dash_stream->isobmff_adapter));
|
gst_adapter_available (dash_stream->isobmff_adapter));
|
||||||
|
GST_BUFFER_OFFSET (buffer) =
|
||||||
|
dash_stream->isobmff_parser.current_offset;
|
||||||
|
dash_stream->isobmff_parser.current_offset +=
|
||||||
|
gst_buffer_get_size (buffer);
|
||||||
|
GST_BUFFER_OFFSET_END (buffer) =
|
||||||
|
dash_stream->isobmff_parser.current_offset;
|
||||||
ret = gst_adaptive_demux_stream_push_buffer (stream, buffer);
|
ret = gst_adaptive_demux_stream_push_buffer (stream, buffer);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -2004,8 +2176,9 @@ gst_dash_demux_data_received (GstAdaptiveDemux * demux,
|
||||||
|
|
||||||
/* Leftover in the adapter is actual mdat data if any */
|
/* Leftover in the adapter is actual mdat data if any */
|
||||||
if (dash_stream->isobmff_parser.current_fourcc ==
|
if (dash_stream->isobmff_parser.current_fourcc ==
|
||||||
GST_ISOFF_FOURCC_MDAT
|
GST_ISOFF_FOURCC_MDAT) {
|
||||||
&& gst_adapter_available (dash_stream->isobmff_adapter) > 0) {
|
gst_dash_demux_find_sync_samples (demux, stream);
|
||||||
|
if (gst_adapter_available (dash_stream->isobmff_adapter) > 0) {
|
||||||
GstBuffer *buffer2 =
|
GstBuffer *buffer2 =
|
||||||
gst_adapter_take_buffer (dash_stream->isobmff_adapter,
|
gst_adapter_take_buffer (dash_stream->isobmff_adapter,
|
||||||
gst_adapter_available (dash_stream->isobmff_adapter));
|
gst_adapter_available (dash_stream->isobmff_adapter));
|
||||||
|
@ -2015,6 +2188,7 @@ gst_dash_demux_data_received (GstAdaptiveDemux * demux,
|
||||||
else
|
else
|
||||||
buffer = buffer2;
|
buffer = buffer2;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
g_assert (buffer || !advance);
|
g_assert (buffer || !advance);
|
||||||
}
|
}
|
||||||
|
@ -2054,13 +2228,22 @@ gst_dash_demux_data_received (GstAdaptiveDemux * demux,
|
||||||
buffer)) != GST_FLOW_OK)
|
buffer)) != GST_FLOW_OK)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (dash_stream->isobmff_parser.current_fourcc == GST_ISOFF_FOURCC_MDAT
|
if (dash_stream->isobmff_parser.current_fourcc == GST_ISOFF_FOURCC_MDAT) {
|
||||||
&& gst_adapter_available (dash_stream->isobmff_adapter) > 0) {
|
gst_dash_demux_find_sync_samples (demux, stream);
|
||||||
|
|
||||||
|
if (gst_adapter_available (dash_stream->isobmff_adapter) > 0) {
|
||||||
buffer =
|
buffer =
|
||||||
gst_adapter_take_buffer (dash_stream->isobmff_adapter,
|
gst_adapter_take_buffer (dash_stream->isobmff_adapter,
|
||||||
gst_adapter_available (dash_stream->isobmff_adapter));
|
gst_adapter_available (dash_stream->isobmff_adapter));
|
||||||
|
GST_BUFFER_OFFSET (buffer) =
|
||||||
|
dash_stream->isobmff_parser.current_offset;
|
||||||
|
dash_stream->isobmff_parser.current_offset +=
|
||||||
|
gst_buffer_get_size (buffer);
|
||||||
|
GST_BUFFER_OFFSET_END (buffer) =
|
||||||
|
dash_stream->isobmff_parser.current_offset;
|
||||||
ret = gst_adaptive_demux_stream_push_buffer (stream, buffer);
|
ret = gst_adaptive_demux_stream_push_buffer (stream, buffer);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,10 @@ struct _GstDashDemuxStream
|
||||||
guint64 current_offset;
|
guint64 current_offset;
|
||||||
guint64 current_size;
|
guint64 current_size;
|
||||||
} isobmff_parser;
|
} isobmff_parser;
|
||||||
|
|
||||||
|
GstMoofBox *moof;
|
||||||
|
guint64 moof_offset;
|
||||||
|
GArray *moof_sync_samples;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue