mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-02 21:48:55 +00:00
gst/qtdemux/: Add suppport for theora in quicktime according to XiphQT.
Original commit message from CVS: * gst/qtdemux/qtdemux.c: (gst_qtdemux_change_state), (gst_qtdemux_prepare_current_sample), (gst_qtdemux_loop_state_movie), (qtdemux_parse_theora_extension), (qtdemux_parse_node), (qtdemux_parse_trak), (qtdemux_video_caps): * gst/qtdemux/qtdemux_fourcc.h: * gst/qtdemux/qtdemux_types.c: Add suppport for theora in quicktime according to XiphQT.
This commit is contained in:
parent
66ca1b2280
commit
a4540bca1e
4 changed files with 158 additions and 0 deletions
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
|||
2007-11-15 Wim Taymans <wim.taymans@gmail.com>
|
||||
|
||||
* gst/qtdemux/qtdemux.c: (gst_qtdemux_change_state),
|
||||
(gst_qtdemux_prepare_current_sample),
|
||||
(gst_qtdemux_loop_state_movie), (qtdemux_parse_theora_extension),
|
||||
(qtdemux_parse_node), (qtdemux_parse_trak), (qtdemux_video_caps):
|
||||
* gst/qtdemux/qtdemux_fourcc.h:
|
||||
* gst/qtdemux/qtdemux_types.c:
|
||||
Add suppport for theora in quicktime according to XiphQT.
|
||||
|
||||
2007-11-15 Edgard Lima <edgard.lima@indt.org.br>
|
||||
|
||||
* sys/v4l2/gstv4l2src.c: (gst_v4l2src_class_init),
|
||||
|
|
|
@ -130,6 +130,7 @@ struct _QtDemuxStream
|
|||
|
||||
/* if we use chunks or samples */
|
||||
gboolean sampled;
|
||||
guint padding;
|
||||
|
||||
/* video info */
|
||||
gint width;
|
||||
|
@ -153,6 +154,9 @@ struct _QtDemuxStream
|
|||
/* when a discontinuity is pending */
|
||||
gboolean discont;
|
||||
|
||||
/* list of buffers to push first */
|
||||
GSList *buffers;
|
||||
|
||||
/* if we need to clip this buffer. This is only needed for uncompressed
|
||||
* data */
|
||||
gboolean need_clip;
|
||||
|
@ -912,6 +916,11 @@ gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
|
|||
for (n = 0; n < qtdemux->n_streams; n++) {
|
||||
QtDemuxStream *stream = qtdemux->streams[n];
|
||||
|
||||
while (stream->buffers) {
|
||||
gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
|
||||
stream->buffers =
|
||||
g_slist_delete_link (stream->buffers, stream->buffers);
|
||||
}
|
||||
if (stream->pad)
|
||||
gst_element_remove_pad (element, stream->pad);
|
||||
if (stream->samples)
|
||||
|
@ -1170,6 +1179,21 @@ gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
|
|||
GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
|
||||
stream->sample_index, stream->n_samples);
|
||||
|
||||
/* send out pending buffers */
|
||||
while (stream->buffers) {
|
||||
GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
|
||||
|
||||
if (stream->discont) {
|
||||
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
|
||||
stream->discont = FALSE;
|
||||
}
|
||||
gst_buffer_set_caps (buffer, stream->caps);
|
||||
|
||||
gst_pad_push (stream->pad, buffer);
|
||||
|
||||
stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
|
||||
}
|
||||
|
||||
if (stream->sample_index >= stream->n_samples)
|
||||
goto eos;
|
||||
|
||||
|
@ -1182,6 +1206,12 @@ gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
|
|||
*duration = sample->duration;
|
||||
*keyframe = stream->all_keyframe || sample->keyframe;
|
||||
|
||||
/* add padding */
|
||||
if (stream->padding) {
|
||||
*offset += stream->padding;
|
||||
*size -= stream->padding;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
/* special cases */
|
||||
|
@ -1489,6 +1519,8 @@ gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
|
|||
|
||||
GST_BUFFER_TIMESTAMP (buf) = timestamp;
|
||||
GST_BUFFER_DURATION (buf) = duration;
|
||||
GST_BUFFER_OFFSET (buf) = -1;
|
||||
GST_BUFFER_OFFSET_END (buf) = -1;
|
||||
|
||||
if (stream->need_clip)
|
||||
buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
|
||||
|
@ -2113,6 +2145,66 @@ qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, guint8 * buf,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
|
||||
GNode * xdxt)
|
||||
{
|
||||
int len = QT_UINT32 (xdxt->data);
|
||||
guint8 *buf = xdxt->data;
|
||||
guint8 *end = buf + len;
|
||||
GstBuffer *buffer;
|
||||
|
||||
/* skip size and type */
|
||||
buf += 8;
|
||||
end -= 8;
|
||||
|
||||
while (buf < end) {
|
||||
gint size;
|
||||
guint32 type;
|
||||
|
||||
size = QT_UINT32 (buf);
|
||||
type = QT_FOURCC (buf + 4);
|
||||
|
||||
GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
|
||||
|
||||
if (buf + size > end || size <= 0)
|
||||
break;
|
||||
|
||||
buf += 8;
|
||||
size -= 8;
|
||||
|
||||
GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
|
||||
GST_FOURCC_ARGS (type));
|
||||
|
||||
switch (type) {
|
||||
case FOURCC_tCtH:
|
||||
buffer = gst_buffer_new_and_alloc (size);
|
||||
memcpy (GST_BUFFER_DATA (buffer), buf, size);
|
||||
stream->buffers = g_slist_append (stream->buffers, buffer);
|
||||
GST_LOG_OBJECT (qtdemux, "parsing theora header");
|
||||
break;
|
||||
case FOURCC_tCt_:
|
||||
buffer = gst_buffer_new_and_alloc (size);
|
||||
memcpy (GST_BUFFER_DATA (buffer), buf, size);
|
||||
stream->buffers = g_slist_append (stream->buffers, buffer);
|
||||
GST_LOG_OBJECT (qtdemux, "parsing theora comment");
|
||||
break;
|
||||
case FOURCC_tCtC:
|
||||
buffer = gst_buffer_new_and_alloc (size);
|
||||
memcpy (GST_BUFFER_DATA (buffer), buf, size);
|
||||
stream->buffers = g_slist_append (stream->buffers, buffer);
|
||||
GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
|
||||
break;
|
||||
default:
|
||||
GST_WARNING_OBJECT (qtdemux,
|
||||
"unknown theora cookie %" GST_FOURCC_FORMAT, type);
|
||||
break;
|
||||
}
|
||||
buf += size;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, guint8 * buffer,
|
||||
int length)
|
||||
|
@ -2225,6 +2317,27 @@ qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, guint8 * buffer,
|
|||
qtdemux_parse_container (qtdemux, node, buffer + 12, end);
|
||||
break;
|
||||
}
|
||||
case FOURCC_XiTh:
|
||||
{
|
||||
guint32 version;
|
||||
guint32 offset;
|
||||
|
||||
version = QT_UINT32 (buffer + 12);
|
||||
GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
|
||||
|
||||
switch (version) {
|
||||
case 0x00000001:
|
||||
offset = 0x62;
|
||||
break;
|
||||
default:
|
||||
GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
|
||||
offset = 0;
|
||||
break;
|
||||
}
|
||||
if (offset)
|
||||
qtdemux_parse_container (qtdemux, node, buffer + offset, end);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -2983,6 +3096,25 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
|
|||
"depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
|
||||
break;
|
||||
}
|
||||
case FOURCC_XiTh:
|
||||
{
|
||||
GNode *xith, *xdxt;
|
||||
|
||||
GST_DEBUG_OBJECT (qtdemux, "found XiTh");
|
||||
xith = qtdemux_tree_get_child_by_type (stsd, FOURCC_XiTh);
|
||||
if (!xith)
|
||||
break;
|
||||
|
||||
xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
|
||||
if (!xdxt)
|
||||
break;
|
||||
|
||||
GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
|
||||
/* collect the headers and store them in a stream list so that we can
|
||||
* send them out first */
|
||||
qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -4072,6 +4204,13 @@ qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
|
|||
_codec ("VP3");
|
||||
caps = gst_caps_from_string ("video/x-vp3");
|
||||
break;
|
||||
case GST_MAKE_FOURCC ('X', 'i', 'T', 'h'):
|
||||
_codec ("Theora");
|
||||
caps = gst_caps_from_string ("video/x-theora");
|
||||
/* theora uses one byte of padding in the data stream because it does not
|
||||
* allow 0 sized packets while theora does */
|
||||
stream->padding = 1;
|
||||
break;
|
||||
case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
|
||||
default:
|
||||
{
|
||||
|
|
|
@ -128,6 +128,13 @@ G_BEGIN_DECLS
|
|||
#define FOURCC_frma GST_MAKE_FOURCC('f','r','m','a')
|
||||
#define FOURCC_ctts GST_MAKE_FOURCC('c','t','t','s')
|
||||
|
||||
/* Xiph fourcc */
|
||||
#define FOURCC_XiTh GST_MAKE_FOURCC('X','i','T','h')
|
||||
#define FOURCC_XdxT GST_MAKE_FOURCC('X','d','x','T')
|
||||
#define FOURCC_tCtH GST_MAKE_FOURCC('t','C','t','H')
|
||||
#define FOURCC_tCt_ GST_MAKE_FOURCC('t','C','t','#')
|
||||
#define FOURCC_tCtC GST_MAKE_FOURCC('t','C','t','C')
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_QTDEMUX_FOURCC_H__ */
|
||||
|
|
|
@ -108,6 +108,8 @@ static const QtNodeType qt_node_types[] = {
|
|||
{FOURCC_rdrf, "rdrf", 0,},
|
||||
{FOURCC__gen, "Custom Genre", QT_FLAG_CONTAINER,},
|
||||
{FOURCC_ctts, "Composition time to sample", 0, qtdemux_dump_ctts},
|
||||
{FOURCC_XiTh, "XiTh", 0},
|
||||
{FOURCC_XdxT, "XdxT", 0},
|
||||
{0, "unknown", 0,},
|
||||
};
|
||||
static const int n_qt_node_types =
|
||||
|
|
Loading…
Reference in a new issue