gst/qtdemux/: Add support for video/mj2 mime-type and its additional atoms/boxes.

Original commit message from CVS:
* gst/qtdemux/qtdemux.c: (gst_qtdemux_change_state),
(gst_qtdemux_loop_state_header), (qtdemux_parse_node),
(qtdemux_parse_trak), (qtdemux_video_caps):
* gst/qtdemux/qtdemux.h:
* gst/qtdemux/qtdemux_fourcc.h:
* gst/qtdemux/qtdemux_types.c:
Add support for video/mj2 mime-type and its additional atoms/boxes.
Fixes #550646.
This commit is contained in:
Mark Nauwelaerts 2008-09-03 12:39:35 +00:00
parent d64815f75f
commit bf5ffabf4c
5 changed files with 137 additions and 3 deletions

View file

@ -1,3 +1,14 @@
2008-09-03 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
* gst/qtdemux/qtdemux.c: (gst_qtdemux_change_state),
(gst_qtdemux_loop_state_header), (qtdemux_parse_node),
(qtdemux_parse_trak), (qtdemux_video_caps):
* gst/qtdemux/qtdemux.h:
* gst/qtdemux/qtdemux_fourcc.h:
* gst/qtdemux/qtdemux_types.c:
Add support for video/mj2 mime-type and its additional atoms/boxes.
Fixes #550646.
2008-09-03 Stefan Kost <ensonic@users.sf.net>
* gst/debug/gsttaginject.c:

View file

@ -259,7 +259,8 @@ static GstStaticPadTemplate gst_qtdemux_sink_template =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/quicktime; audio/x-m4a; application/x-3gp")
GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
"application/x-3gp")
);
static GstStaticPadTemplate gst_qtdemux_videosrc_template =
@ -1032,6 +1033,7 @@ gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
g_free (stream->segments);
g_free (stream);
}
qtdemux->major_brand = 0;
qtdemux->n_streams = 0;
qtdemux->n_video_streams = 0;
qtdemux->n_audio_streams = 0;
@ -1131,6 +1133,25 @@ gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
qtdemux->state);
break;
}
case FOURCC_ftyp:
{
GstBuffer *ftyp;
/* extract major brand; might come in handy for ISO vs QT issues */
ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &ftyp);
if (ret != GST_FLOW_OK)
goto beach;
cur_offset += length;
qtdemux->offset += length;
/* only consider at least a sufficiently complete ftyp atom */
if (length >= 20) {
qtdemux->major_brand = QT_FOURCC (GST_BUFFER_DATA (ftyp) + 8);
GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
GST_FOURCC_ARGS (qtdemux->major_brand));
}
gst_buffer_unref (ftyp);
break;
}
default:
{
GST_LOG_OBJECT (qtdemux,
@ -2627,6 +2648,11 @@ qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, guint8 * buffer,
}
break;
}
case FOURCC_mjp2:
{
qtdemux_parse_container (qtdemux, node, buffer + 86, end);
break;
}
case FOURCC_meta:
{
GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
@ -3256,8 +3282,12 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
goto corrupt_file;
if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd)))
goto corrupt_file;
if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
/* be nice for some crooked mjp2 files that use mhdr for mdhd */
if (qtdemux->major_brand != FOURCC_mjp2 ||
!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
goto corrupt_file;
}
version = QT_UINT32 ((guint8 *) mdhd->data + 8);
GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
@ -3391,6 +3421,75 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
}
break;
}
case FOURCC_mjp2:
{
GNode *jp2h, *colr, *mjp2, *field, *prefix;
const guint8 *data;
guint32 fourcc = 0;
GST_DEBUG_OBJECT (qtdemux, "found mjp2");
/* some required atoms */
mjp2 = qtdemux_tree_get_child_by_type (stsd, FOURCC_mjp2);
if (!mjp2)
break;
jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
if (!jp2h)
break;
colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
if (!colr)
break;
GST_DEBUG_OBJECT (qtdemux, "found colr");
/* try to extract colour space info */
if (QT_UINT8 (colr->data + 8) == 1) {
switch (QT_UINT32 (colr->data + 11)) {
case 16:
fourcc = GST_MAKE_FOURCC ('s', 'R', 'G', 'B');
break;
case 17:
fourcc = GST_MAKE_FOURCC ('G', 'R', 'A', 'Y');
break;
case 18:
fourcc = GST_MAKE_FOURCC ('s', 'Y', 'U', 'V');
break;
default:
break;
}
}
if (fourcc)
gst_caps_set_simple (stream->caps,
"fourcc", GST_TYPE_FOURCC, fourcc, NULL);
/* some optional atoms */
field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
/* indicate possible fields in caps */
if (field) {
data = field->data + 8;
if (*data != 1)
gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
(gint) * data, NULL);
}
/* add codec_data if provided */
if (prefix) {
GstBuffer *buf;
gint len;
GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
data = prefix->data;
len = QT_UINT32 (data);
if (len > 0x8) {
len -= 0x8;
buf = gst_buffer_new_and_alloc (len);
memcpy (GST_BUFFER_DATA (buf), data + 8, len);
gst_caps_set_simple (stream->caps,
"codec_data", GST_TYPE_BUFFER, buf, NULL);
gst_buffer_unref (buf);
}
}
break;
}
case FOURCC_SVQ3:
case FOURCC_VP31:
{
@ -3611,6 +3710,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
case FOURCC_QDMC:
{
gint len = QT_UINT32 (stsd_data);
/* seems to be always = 116 = 0x74 */
break;
}
@ -4430,6 +4530,12 @@ qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
_codec ("Motion-JPEG format B");
caps = gst_caps_from_string ("video/x-mjpeg-b");
break;
case GST_MAKE_FOURCC ('m', 'j', 'p', '2'):
_codec ("JPEG-2000");
/* override to what it should be according to spec, avoid palette_data */
stream->bits_per_sample = 24;
caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
break;
case GST_MAKE_FOURCC ('S', 'V', 'Q', '3'):
_codec ("Sorensen video v.3");
caps = gst_caps_from_string ("video/x-svq, " "svqversion = (int) 3");

View file

@ -59,6 +59,7 @@ struct _GstQTDemux {
gint n_video_streams;
gint n_audio_streams;
guint major_brand;
GNode *moov_node;
GNode *moov_node_compressed;

View file

@ -24,6 +24,7 @@
G_BEGIN_DECLS
#define FOURCC_ftyp GST_MAKE_FOURCC('f','t','y','p')
#define FOURCC_moov GST_MAKE_FOURCC('m','o','o','v')
#define FOURCC_mvhd GST_MAKE_FOURCC('m','v','h','d')
#define FOURCC_clip GST_MAKE_FOURCC('c','l','i','p')
@ -133,6 +134,15 @@ G_BEGIN_DECLS
#define FOURCC_keyw GST_MAKE_FOURCC('k','e','y','w')
#define FOURCC_kywd GST_MAKE_FOURCC('k','y','w','d')
/* ISO Motion JPEG 2000 fourcc */
#define FOURCC_mjp2 GST_MAKE_FOURCC('m','j','p','2')
#define FOURCC_jp2h GST_MAKE_FOURCC('j','p','2','h')
#define FOURCC_colr GST_MAKE_FOURCC('c','o','l','r')
#define FOURCC_fiel GST_MAKE_FOURCC('f','i','e','l')
#define FOURCC_jp2x GST_MAKE_FOURCC('j','p','2','x')
/* some buggy hardware's notion of mdhd */
#define FOURCC_mhdr GST_MAKE_FOURCC('m','h','d','r')
/* Xiph fourcc */
#define FOURCC_XiTh GST_MAKE_FOURCC('X','i','T','h')
#define FOURCC_XdxT GST_MAKE_FOURCC('X','d','x','T')

View file

@ -78,6 +78,12 @@ static const QtNodeType qt_node_types[] = {
{FOURCC_hint, "hint", 0,},
{FOURCC_mp4a, "mp4a", 0,},
{FOURCC_mp4v, "mp4v", 0,},
{FOURCC_mjp2, "mjp2", 0,},
{FOURCC_mhdr, "mhdr", QT_FLAG_CONTAINER,},
{FOURCC_jp2h, "jp2h", QT_FLAG_CONTAINER,},
{FOURCC_colr, "colr", 0,},
{FOURCC_fiel, "fiel", 0,},
{FOURCC_jp2x, "jp2x", 0,},
{FOURCC_wave, "wave", QT_FLAG_CONTAINER},
{FOURCC_appl, "appl", QT_FLAG_CONTAINER},
{FOURCC_esds, "esds", 0},