Commit 365437cb authored by Edward Hervey's avatar Edward Hervey 🤘

gst/qtdemux/: Process 'ctts' atoms, which are present in AVC ISO files (.mov...

gst/qtdemux/: Process 'ctts' atoms, which are present in AVC ISO files (.mov files with h264 video).

Original commit message from CVS:
* gst/qtdemux/qtdemux.c: (gst_qtdemux_prepare_current_sample),
(gst_qtdemux_chain), (qtdemux_parse_samples):
* gst/qtdemux/qtdemux_dump.c: (qtdemux_dump_ctts):
* gst/qtdemux/qtdemux_dump.h:
* gst/qtdemux/qtdemux_fourcc.h:
* gst/qtdemux/qtdemux_types.c:
Process 'ctts' atoms, which are present in AVC ISO files (.mov files
with h264 video).
Use the offset present in 'ctts' to calculate the PTS for each packet
and set the PTS on outgoing buffers.
Fixes #423283
parent 51ef42dd
2007-03-28 Edward Hervey <edward@fluendo.com>
* gst/qtdemux/qtdemux.c: (gst_qtdemux_prepare_current_sample),
(gst_qtdemux_chain), (qtdemux_parse_samples):
* gst/qtdemux/qtdemux_dump.c: (qtdemux_dump_ctts):
* gst/qtdemux/qtdemux_dump.h:
* gst/qtdemux/qtdemux_fourcc.h:
* gst/qtdemux/qtdemux_types.c:
Process 'ctts' atoms, which are present in AVC ISO files (.mov files
with h264 video).
Use the offset present in 'ctts' to calculate the PTS for each packet
and set the PTS on outgoing buffers.
Fixes #423283
2007-03-27 Julien MOUTTE <julien@moutte.net> 2007-03-27 Julien MOUTTE <julien@moutte.net>
* ext/xvid/gstxviddec.c: (gst_xviddec_chain): Add some * ext/xvid/gstxviddec.c: (gst_xviddec_chain): Add some
......
...@@ -88,6 +88,7 @@ struct _QtDemuxSample ...@@ -88,6 +88,7 @@ struct _QtDemuxSample
guint32 chunk; guint32 chunk;
guint32 size; guint32 size;
guint64 offset; guint64 offset;
GstClockTimeDiff pts_offset; /* Add this value to timestamp to get the pts */
guint64 timestamp; /* In GstClockTime */ guint64 timestamp; /* In GstClockTime */
guint64 duration; /* in GstClockTime */ guint64 duration; /* in GstClockTime */
gboolean keyframe; /* TRUE when this packet is a keyframe */ gboolean keyframe; /* TRUE when this packet is a keyframe */
...@@ -1147,9 +1148,9 @@ gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux, ...@@ -1147,9 +1148,9 @@ gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
/* now get the info for the sample we're at */ /* now get the info for the sample we're at */
sample = &stream->samples[stream->sample_index]; sample = &stream->samples[stream->sample_index];
*timestamp = sample->timestamp + sample->pts_offset;
*offset = sample->offset; *offset = sample->offset;
*size = sample->size; *size = sample->size;
*timestamp = sample->timestamp;
*duration = sample->duration; *duration = sample->duration;
*keyframe = stream->all_keyframe || sample->keyframe; *keyframe = stream->all_keyframe || sample->keyframe;
...@@ -1687,9 +1688,15 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf) ...@@ -1687,9 +1688,15 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT, GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
GST_FOURCC_ARGS (stream->fourcc)); GST_FOURCC_ARGS (stream->fourcc));
GST_BUFFER_TIMESTAMP (outbuf) = if (stream->samples[stream->sample_index].pts_offset) {
stream->samples[stream->sample_index].timestamp; demux->last_ts = stream->samples[stream->sample_index].timestamp;
demux->last_ts = GST_BUFFER_TIMESTAMP (outbuf); GST_BUFFER_TIMESTAMP (outbuf) = demux->last_ts +
stream->samples[stream->sample_index].pts_offset;
} else {
GST_BUFFER_TIMESTAMP (outbuf) =
stream->samples[stream->sample_index].timestamp;
demux->last_ts = GST_BUFFER_TIMESTAMP (outbuf);
}
GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (outbuf) =
stream->samples[stream->sample_index].duration; stream->samples[stream->sample_index].duration;
...@@ -2265,6 +2272,7 @@ qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, ...@@ -2265,6 +2272,7 @@ qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream,
GNode *co64; GNode *co64;
GNode *stts; GNode *stts;
GNode *stss; GNode *stss;
GNode *ctts;
const guint8 *stsc_data, *stsz_data, *stco_data; const guint8 *stsc_data, *stsz_data, *stco_data;
int sample_size; int sample_size;
int sample_index; int sample_index;
...@@ -2481,6 +2489,24 @@ qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, ...@@ -2481,6 +2489,24 @@ qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream,
} }
} }
} }
/* composition time to sample */
if ((ctts = qtdemux_tree_get_child_by_type (stbl, FOURCC_ctts))) {
const guint8 *ctts_data = (const guint8 *) ctts->data;
guint32 n_entries = QT_UINT32 (ctts_data + 12);
guint32 count;
gint32 soffset;
/* Fill in the pts_offsets */
for (i = 0, j = 0; (j < stream->n_samples) && (i < n_entries); i++) {
count = QT_UINT32 (ctts_data + 16 + i * 8);
soffset = QT_UINT32 (ctts_data + 20 + i * 8);
for (k = 0; k < count; k++, j++) {
/* we operate with very small soffset values here, it shouldn't overflow */
samples[j].pts_offset = soffset * GST_SECOND / stream->timescale;
}
}
}
done: done:
return TRUE; return TRUE;
......
...@@ -297,6 +297,26 @@ qtdemux_dump_stco (GstQTDemux * qtdemux, guint8 * buffer, int depth) ...@@ -297,6 +297,26 @@ qtdemux_dump_stco (GstQTDemux * qtdemux, guint8 * buffer, int depth)
} }
} }
void
qtdemux_dump_ctts (GstQTDemux * qtdemux, guint8 * buffer, int depth)
{
int i;
int n;
int offset;
GST_LOG ("%*s version/flags: %08x", depth, "", QT_UINT32 (buffer + 8));
n = QT_UINT32 (buffer + 12);
GST_LOG ("%*s n entries: %d", depth, "", n);
offset = 16;
for (i = 0; i < n; i++) {
GST_LOG ("%*s sample count :%8d offset: %8d",
depth, "", QT_UINT32 (buffer + offset),
QT_UINT32 (buffer + offset + 4));
offset += 8;
}
}
void void
qtdemux_dump_co64 (GstQTDemux * qtdemux, guint8 * buffer, int depth) qtdemux_dump_co64 (GstQTDemux * qtdemux, guint8 * buffer, int depth)
{ {
......
...@@ -41,6 +41,7 @@ void qtdemux_dump_stco (GstQTDemux * qtdemux, guint8 * buffer, int depth); ...@@ -41,6 +41,7 @@ void qtdemux_dump_stco (GstQTDemux * qtdemux, guint8 * buffer, int depth);
void qtdemux_dump_co64 (GstQTDemux * qtdemux, guint8 * buffer, int depth); void qtdemux_dump_co64 (GstQTDemux * qtdemux, guint8 * buffer, int depth);
void qtdemux_dump_dcom (GstQTDemux * qtdemux, guint8 * buffer, int depth); void qtdemux_dump_dcom (GstQTDemux * qtdemux, guint8 * buffer, int depth);
void qtdemux_dump_cmvd (GstQTDemux * qtdemux, guint8 * buffer, int depth); void qtdemux_dump_cmvd (GstQTDemux * qtdemux, guint8 * buffer, int depth);
void qtdemux_dump_ctts (GstQTDemux * qtdemux, guint8 * buffer, int depth);
void qtdemux_dump_unknown (GstQTDemux * qtdemux, guint8 * buffer, int depth); void qtdemux_dump_unknown (GstQTDemux * qtdemux, guint8 * buffer, int depth);
void qtdemux_node_dump (GstQTDemux * qtdemux, GNode * node); void qtdemux_node_dump (GstQTDemux * qtdemux, GNode * node);
......
...@@ -126,6 +126,7 @@ G_BEGIN_DECLS ...@@ -126,6 +126,7 @@ G_BEGIN_DECLS
#define FOURCC_alis GST_MAKE_FOURCC('a','l','i','s') #define FOURCC_alis GST_MAKE_FOURCC('a','l','i','s')
#define FOURCC_url_ GST_MAKE_FOURCC('u','r','l',' ') #define FOURCC_url_ GST_MAKE_FOURCC('u','r','l',' ')
#define FOURCC_frma GST_MAKE_FOURCC('f','r','m','a') #define FOURCC_frma GST_MAKE_FOURCC('f','r','m','a')
#define FOURCC_ctts GST_MAKE_FOURCC('c','t','t','s')
G_END_DECLS G_END_DECLS
......
...@@ -107,6 +107,7 @@ static const QtNodeType qt_node_types[] = { ...@@ -107,6 +107,7 @@ static const QtNodeType qt_node_types[] = {
{FOURCC_rmda, "rmda", QT_FLAG_CONTAINER,}, {FOURCC_rmda, "rmda", QT_FLAG_CONTAINER,},
{FOURCC_rdrf, "rdrf", 0,}, {FOURCC_rdrf, "rdrf", 0,},
{FOURCC__gen, "Custom Genre", QT_FLAG_CONTAINER,}, {FOURCC__gen, "Custom Genre", QT_FLAG_CONTAINER,},
{FOURCC_ctts, "Composition time to sample", 0, qtdemux_dump_ctts},
{0, "unknown", 0,}, {0, "unknown", 0,},
}; };
static const int n_qt_node_types = static const int n_qt_node_types =
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment