isomp4: port to 0.11

This commit is contained in:
Mark Nauwelaerts 2011-06-29 12:46:20 +02:00
parent 65bb271a95
commit f886681367
10 changed files with 514 additions and 424 deletions

View file

@ -6,6 +6,7 @@ libgstisomp4_la_LIBADD = \
$(GST_PLUGINS_BASE_LIBS) \ $(GST_PLUGINS_BASE_LIBS) \
-lgstriff-@GST_MAJORMINOR@ \ -lgstriff-@GST_MAJORMINOR@ \
-lgstaudio-@GST_MAJORMINOR@ \ -lgstaudio-@GST_MAJORMINOR@ \
-lgstvideo-@GST_MAJORMINOR@ \
-lgstrtp-@GST_MAJORMINOR@ \ -lgstrtp-@GST_MAJORMINOR@ \
-lgsttag-@GST_MAJORMINOR@ \ -lgsttag-@GST_MAJORMINOR@ \
-lgstpbutils-@GST_MAJORMINOR@ \ -lgstpbutils-@GST_MAJORMINOR@ \

View file

@ -206,9 +206,10 @@ static AtomData *
atom_data_new_from_gst_buffer (guint32 fourcc, const GstBuffer * buf) atom_data_new_from_gst_buffer (guint32 fourcc, const GstBuffer * buf)
{ {
AtomData *data = atom_data_new (fourcc); AtomData *data = atom_data_new (fourcc);
gsize size = gst_buffer_get_size ((GstBuffer *) buf);
atom_data_alloc_mem (data, GST_BUFFER_SIZE (buf)); atom_data_alloc_mem (data, size);
g_memmove (data->data, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); gst_buffer_extract ((GstBuffer *) buf, 0, data->data, size);
return data; return data;
} }
@ -2825,6 +2826,19 @@ atom_moov_add_uint_tag (AtomMOOV * moov, guint32 fourcc, guint32 flags,
} }
} }
static GstBuffer *
_gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
{
GstBuffer *buf;
buf = gst_buffer_new ();
gst_buffer_take_memory (buf, -1,
gst_memory_new_wrapped (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
mem, free_func, size, 0, size));
return buf;
}
void void
atom_moov_add_blob_tag (AtomMOOV * moov, guint8 * data, guint size) atom_moov_add_blob_tag (AtomMOOV * moov, guint8 * data, guint size)
{ {
@ -2843,10 +2857,7 @@ atom_moov_add_blob_tag (AtomMOOV * moov, guint8 * data, guint size)
if (len > size) if (len > size)
return; return;
buf = gst_buffer_new (); buf = _gst_buffer_new_wrapped (data + 8, len - 8, NULL);
GST_BUFFER_SIZE (buf) = len - 8;
GST_BUFFER_DATA (buf) = data + 8;
data_atom = atom_data_new_from_gst_buffer (fourcc, buf); data_atom = atom_data_new_from_gst_buffer (fourcc, buf);
gst_buffer_unref (buf); gst_buffer_unref (buf);
@ -2864,12 +2875,12 @@ atom_moov_add_3gp_tag (AtomMOOV * moov, guint32 fourcc, guint8 * data,
guint8 *bdata; guint8 *bdata;
/* need full atom */ /* need full atom */
buf = gst_buffer_new_and_alloc (size + 4); bdata = g_malloc (size + 4);
bdata = GST_BUFFER_DATA (buf);
/* full atom: version and flags */ /* full atom: version and flags */
GST_WRITE_UINT32_BE (bdata, 0); GST_WRITE_UINT32_BE (bdata, 0);
memcpy (bdata + 4, data, size); memcpy (bdata + 4, data, size);
buf = _gst_buffer_new_wrapped (bdata, size + 4, g_free);
data_atom = atom_data_new_from_gst_buffer (fourcc, buf); data_atom = atom_data_new_from_gst_buffer (fourcc, buf);
gst_buffer_unref (buf); gst_buffer_unref (buf);
@ -3188,13 +3199,12 @@ build_pasp_extension (AtomTRAK * trak, gint par_width, gint par_height)
GstBuffer *buf; GstBuffer *buf;
guint8 *data; guint8 *data;
buf = gst_buffer_new_and_alloc (8); data = g_malloc (8);
data = GST_BUFFER_DATA (buf);
/* ihdr = image header box */ /* ihdr = image header box */
GST_WRITE_UINT32_BE (data, par_width); GST_WRITE_UINT32_BE (data, par_width);
GST_WRITE_UINT32_BE (data + 4, par_height); GST_WRITE_UINT32_BE (data + 4, par_height);
buf = _gst_buffer_new_wrapped (data, 8, g_free);
atom_data = atom_data_new_from_gst_buffer (FOURCC_pasp, buf); atom_data = atom_data_new_from_gst_buffer (FOURCC_pasp, buf);
gst_buffer_unref (buf); gst_buffer_unref (buf);
@ -3942,13 +3952,13 @@ build_esds_extension (AtomTRAK * trak, guint8 object_type, guint8 stream_type,
/* optional DecoderSpecificInfo */ /* optional DecoderSpecificInfo */
if (codec_data) { if (codec_data) {
DecoderSpecificInfoDescriptor *desc; DecoderSpecificInfoDescriptor *desc;
gsize size;
esds->es.dec_conf_desc.dec_specific_info = desc = esds->es.dec_conf_desc.dec_specific_info = desc =
desc_dec_specific_info_new (); desc_dec_specific_info_new ();
desc_dec_specific_info_alloc_data (desc, GST_BUFFER_SIZE (codec_data)); size = gst_buffer_get_size ((GstBuffer *) codec_data);
desc_dec_specific_info_alloc_data (desc, size);
memcpy (desc->data, GST_BUFFER_DATA (codec_data), gst_buffer_extract ((GstBuffer *) codec_data, 0, desc->data, size);
GST_BUFFER_SIZE (codec_data));
} }
return build_atom_info_wrapper ((Atom *) esds, atom_esds_copy_data, return build_atom_info_wrapper ((Atom *) esds, atom_esds_copy_data,
@ -3961,16 +3971,17 @@ build_btrt_extension (guint32 buffer_size_db, guint32 avg_bitrate,
{ {
AtomData *atom_data; AtomData *atom_data;
GstBuffer *buf; GstBuffer *buf;
guint8 *data;
if (buffer_size_db == 0 && avg_bitrate == 0 && max_bitrate == 0) if (buffer_size_db == 0 && avg_bitrate == 0 && max_bitrate == 0)
return 0; return 0;
buf = gst_buffer_new_and_alloc (12); data = g_malloc (12);
GST_WRITE_UINT32_BE (data, buffer_size_db);
GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf), buffer_size_db); GST_WRITE_UINT32_BE (data + 4, max_bitrate);
GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + 4, max_bitrate); GST_WRITE_UINT32_BE (data + 8, avg_bitrate);
GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + 8, avg_bitrate);
buf = _gst_buffer_new_wrapped (data, 12, g_free);
atom_data = atom_data =
atom_data_new_from_gst_buffer (GST_MAKE_FOURCC ('b', 't', 'r', 't'), buf); atom_data_new_from_gst_buffer (GST_MAKE_FOURCC ('b', 't', 'r', 't'), buf);
gst_buffer_unref (buf); gst_buffer_unref (buf);
@ -4022,6 +4033,7 @@ build_mov_aac_extension (AtomTRAK * trak, const GstBuffer * codec_data,
{ {
AtomInfo *esds, *mp4a; AtomInfo *esds, *mp4a;
GstBuffer *buf; GstBuffer *buf;
guint32 tmp = 0;
/* Add ESDS atom to WAVE */ /* Add ESDS atom to WAVE */
esds = build_esds_extension (trak, ESDS_OBJECT_TYPE_MPEG4_P3, esds = build_esds_extension (trak, ESDS_OBJECT_TYPE_MPEG4_P3,
@ -4029,8 +4041,7 @@ build_mov_aac_extension (AtomTRAK * trak, const GstBuffer * codec_data,
/* Add MP4A atom to the WAVE: /* Add MP4A atom to the WAVE:
* not really in spec, but makes offset based players happy */ * not really in spec, but makes offset based players happy */
buf = gst_buffer_new_and_alloc (4); buf = _gst_buffer_new_wrapped (&tmp, 4, NULL);
*((guint32 *) GST_BUFFER_DATA (buf)) = 0;
mp4a = build_codec_data_extension (FOURCC_mp4a, buf); mp4a = build_codec_data_extension (FOURCC_mp4a, buf);
gst_buffer_unref (buf); gst_buffer_unref (buf);
@ -4052,14 +4063,13 @@ build_fiel_extension (gint fields)
{ {
AtomData *atom_data; AtomData *atom_data;
GstBuffer *buf; GstBuffer *buf;
guint8 f = fields;
if (fields == 1) { if (fields == 1) {
return NULL; return NULL;
} }
buf = gst_buffer_new_and_alloc (1); buf = _gst_buffer_new_wrapped (&f, 1, NULL);
GST_BUFFER_DATA (buf)[0] = (guint8) fields;
atom_data = atom_data =
atom_data_new_from_gst_buffer (GST_MAKE_FOURCC ('f', 'i', 'e', 'l'), buf); atom_data_new_from_gst_buffer (GST_MAKE_FOURCC ('f', 'i', 'e', 'l'), buf);
gst_buffer_unref (buf); gst_buffer_unref (buf);
@ -4129,9 +4139,8 @@ build_jp2h_extension (AtomTRAK * trak, gint width, gint height, guint32 fourcc,
cdef_size = 8 + 2 + cdef_array_size * 6; cdef_size = 8 + 2 + cdef_array_size * 6;
} }
buf = gst_buffer_new_and_alloc (idhr_size + colr_size + cmap_size + gst_byte_writer_init_with_size (&writer,
cdef_size); idhr_size + colr_size + cmap_size + cdef_size, TRUE);
gst_byte_writer_init_with_buffer (&writer, buf, FALSE);
/* ihdr = image header box */ /* ihdr = image header box */
gst_byte_writer_put_uint32_be (&writer, 22); gst_byte_writer_put_uint32_be (&writer, 22);
@ -4215,6 +4224,7 @@ build_jp2h_extension (AtomTRAK * trak, gint width, gint height, guint32 fourcc,
} }
g_assert (gst_byte_writer_get_remaining (&writer) == 0); g_assert (gst_byte_writer_get_remaining (&writer) == 0);
buf = gst_byte_writer_reset_and_get_buffer (&writer);
atom_data = atom_data_new_from_gst_buffer (FOURCC_jp2h, buf); atom_data = atom_data_new_from_gst_buffer (FOURCC_jp2h, buf);
gst_buffer_unref (buf); gst_buffer_unref (buf);
@ -4245,10 +4255,6 @@ build_amr_extension (void)
GstBuffer *buf; GstBuffer *buf;
AtomInfo *res; AtomInfo *res;
buf = gst_buffer_new ();
GST_BUFFER_DATA (buf) = ext;
GST_BUFFER_SIZE (buf) = sizeof (ext);
/* vendor */ /* vendor */
GST_WRITE_UINT32_LE (ext, 0); GST_WRITE_UINT32_LE (ext, 0);
/* decoder version */ /* decoder version */
@ -4260,6 +4266,7 @@ build_amr_extension (void)
/* frames per sample */ /* frames per sample */
GST_WRITE_UINT8 (ext + 8, 1); GST_WRITE_UINT8 (ext + 8, 1);
buf = _gst_buffer_new_wrapped (ext, sizeof (ext), NULL);
res = build_codec_data_extension (GST_MAKE_FOURCC ('d', 'a', 'm', 'r'), buf); res = build_codec_data_extension (GST_MAKE_FOURCC ('d', 'a', 'm', 'r'), buf);
gst_buffer_unref (buf); gst_buffer_unref (buf);
return res; return res;
@ -4272,10 +4279,6 @@ build_h263_extension (void)
GstBuffer *buf; GstBuffer *buf;
AtomInfo *res; AtomInfo *res;
buf = gst_buffer_new ();
GST_BUFFER_DATA (buf) = ext;
GST_BUFFER_SIZE (buf) = sizeof (ext);
/* vendor */ /* vendor */
GST_WRITE_UINT32_LE (ext, 0); GST_WRITE_UINT32_LE (ext, 0);
/* decoder version */ /* decoder version */
@ -4285,6 +4288,7 @@ build_h263_extension (void)
GST_WRITE_UINT8 (ext + 5, 10); GST_WRITE_UINT8 (ext + 5, 10);
GST_WRITE_UINT8 (ext + 6, 0); GST_WRITE_UINT8 (ext + 6, 0);
buf = _gst_buffer_new_wrapped (ext, sizeof (ext), NULL);
res = build_codec_data_extension (GST_MAKE_FOURCC ('d', '2', '6', '3'), buf); res = build_codec_data_extension (GST_MAKE_FOURCC ('d', '2', '6', '3'), buf);
gst_buffer_unref (buf); gst_buffer_unref (buf);
return res; return res;
@ -4300,8 +4304,8 @@ build_gama_atom (gdouble gamma)
/* convert to uint32 from fixed point */ /* convert to uint32 from fixed point */
gamma_fp = (guint32) 65536 *gamma; gamma_fp = (guint32) 65536 *gamma;
buf = gst_buffer_new_and_alloc (4); gamma_fp = GUINT32_TO_BE (gamma_fp);
GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf), gamma_fp); buf = _gst_buffer_new_wrapped (&gamma_fp, 4, NULL);
res = build_codec_data_extension (FOURCC_gama, buf); res = build_codec_data_extension (FOURCC_gama, buf);
gst_buffer_unref (buf); gst_buffer_unref (buf);
return res; return res;
@ -4312,14 +4316,17 @@ build_SMI_atom (const GstBuffer * seqh)
{ {
AtomInfo *res; AtomInfo *res;
GstBuffer *buf; GstBuffer *buf;
gsize size;
guint8 *data;
/* the seqh plus its size and fourcc */ /* the seqh plus its size and fourcc */
buf = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (seqh) + 8); size = gst_buffer_get_size ((GstBuffer *) seqh);
data = g_malloc (size + 8);
GST_WRITE_UINT32_LE (GST_BUFFER_DATA (buf), FOURCC_SEQH); GST_WRITE_UINT32_LE (data, FOURCC_SEQH);
GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + 4, GST_BUFFER_SIZE (seqh)); GST_WRITE_UINT32_BE (data + 4, size + 8);
memcpy (GST_BUFFER_DATA (buf) + 8, GST_BUFFER_DATA (seqh), gst_buffer_extract ((GstBuffer *) seqh, 0, data + 8, size);
GST_BUFFER_SIZE (seqh)); buf = _gst_buffer_new_wrapped (data, size + 8, g_free);
res = build_codec_data_extension (FOURCC_SMI_, buf); res = build_codec_data_extension (FOURCC_SMI_, buf);
gst_buffer_unref (buf); gst_buffer_unref (buf);
return res; return res;
@ -4341,8 +4348,7 @@ build_ima_adpcm_atom (gint channels, gint rate, gint blocksize)
within the WAVE header (below), it's little endian. */ within the WAVE header (below), it's little endian. */
fourcc = MS_WAVE_FOURCC (0x11); fourcc = MS_WAVE_FOURCC (0x11);
buf = gst_buffer_new_and_alloc (ima_adpcm_atom_size); data = g_malloc (ima_adpcm_atom_size);
data = GST_BUFFER_DATA (buf);
/* This atom's content is a WAVE header, including 2 bytes of extra data. /* This atom's content is a WAVE header, including 2 bytes of extra data.
Note that all of this is little-endian, unlike most stuff in qt. */ Note that all of this is little-endian, unlike most stuff in qt. */
@ -4359,6 +4365,7 @@ build_ima_adpcm_atom (gint channels, gint rate, gint blocksize)
GST_WRITE_UINT16_LE (data + 16, 2); /* Two extra bytes */ GST_WRITE_UINT16_LE (data + 16, 2); /* Two extra bytes */
GST_WRITE_UINT16_LE (data + 18, samplesperblock); GST_WRITE_UINT16_LE (data + 18, samplesperblock);
buf = _gst_buffer_new_wrapped (data, ima_adpcm_atom_size, g_free);
atom_data = atom_data_new_from_gst_buffer (fourcc, buf); atom_data = atom_data_new_from_gst_buffer (fourcc, buf);
gst_buffer_unref (buf); gst_buffer_unref (buf);
@ -4402,6 +4409,7 @@ AtomInfo *
build_uuid_xmp_atom (GstBuffer * xmp_data) build_uuid_xmp_atom (GstBuffer * xmp_data)
{ {
AtomUUID *uuid; AtomUUID *uuid;
gsize size;
static guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB, static guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
0x97, 0xA9, 0x42, 0xE8, 0x97, 0xA9, 0x42, 0xE8,
0x9C, 0x71, 0x99, 0x94, 0x9C, 0x71, 0x99, 0x94,
@ -4414,9 +4422,10 @@ build_uuid_xmp_atom (GstBuffer * xmp_data)
uuid = atom_uuid_new (); uuid = atom_uuid_new ();
memcpy (uuid->uuid, xmp_uuid, 16); memcpy (uuid->uuid, xmp_uuid, 16);
uuid->data = g_malloc (GST_BUFFER_SIZE (xmp_data)); size = gst_buffer_get_size (xmp_data);
uuid->datalen = GST_BUFFER_SIZE (xmp_data); uuid->data = g_malloc (size);
memcpy (uuid->data, GST_BUFFER_DATA (xmp_data), GST_BUFFER_SIZE (xmp_data)); uuid->datalen = size;
gst_buffer_extract (xmp_data, 0, uuid->data, size);
return build_atom_info_wrapper ((Atom *) uuid, atom_uuid_copy_data, return build_atom_info_wrapper ((Atom *) uuid, atom_uuid_copy_data,
atom_uuid_free); atom_uuid_free);

View file

@ -108,10 +108,15 @@ atoms_recov_write_ftyp_info (FILE * f, AtomFTYP * ftyp, GstBuffer * prefix)
guint64 size = 0; guint64 size = 0;
if (prefix) { if (prefix) {
if (fwrite (GST_BUFFER_DATA (prefix), 1, GST_BUFFER_SIZE (prefix), f) != guint8 *bdata;
GST_BUFFER_SIZE (prefix)) { gsize bsize;
bdata = gst_buffer_map (prefix, &bsize, NULL, GST_MAP_READ);
if (fwrite (bdata, 1, bsize, f) != bsize) {
gst_buffer_unmap (prefix, bdata, bsize);
return FALSE; return FALSE;
} }
gst_buffer_unmap (prefix, bdata, bsize);
} }
if (!atom_ftyp_copy_data (ftyp, &data, &size, &offset)) { if (!atom_ftyp_copy_data (ftyp, &data, &size, &offset)) {
return FALSE; return FALSE;

View file

@ -89,8 +89,8 @@ enum
PROP_FAST_START_MODE PROP_FAST_START_MODE
}; };
GST_BOILERPLATE (GstQTMoovRecover, gst_qt_moov_recover, GstPipeline, #define gst_qt_moov_recover_parent_class parent_class
GST_TYPE_PIPELINE); G_DEFINE_TYPE (GstQTMoovRecover, gst_qt_moov_recover, GST_TYPE_PIPELINE);
/* property functions */ /* property functions */
static void gst_qt_moov_recover_set_property (GObject * object, static void gst_qt_moov_recover_set_property (GObject * object,
@ -103,18 +103,6 @@ static GstStateChangeReturn gst_qt_moov_recover_change_state (GstElement *
static void gst_qt_moov_recover_finalize (GObject * object); static void gst_qt_moov_recover_finalize (GObject * object);
static void
gst_qt_moov_recover_base_init (gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
#if 0
GstQTMoovRecoverClass *klass = (GstQTMoovRecoverClass *) g_class;
#endif
gst_element_class_set_details_simple (element_class, "QT Moov Recover",
"Util", "Recovers unfinished qtmux files",
"Thiago Santos <thiago.sousa.santos@collabora.co.uk>");
}
static void static void
gst_qt_moov_recover_class_init (GstQTMoovRecoverClass * klass) gst_qt_moov_recover_class_init (GstQTMoovRecoverClass * klass)
{ {
@ -156,11 +144,14 @@ gst_qt_moov_recover_class_init (GstQTMoovRecoverClass * klass)
GST_DEBUG_CATEGORY_INIT (gst_qt_moov_recover_debug, "qtmoovrecover", 0, GST_DEBUG_CATEGORY_INIT (gst_qt_moov_recover_debug, "qtmoovrecover", 0,
"QT Moovie Recover"); "QT Moovie Recover");
gst_element_class_set_details_simple (gstelement_class, "QT Moov Recover",
"Util", "Recovers unfinished qtmux files",
"Thiago Santos <thiago.sousa.santos@collabora.co.uk>");
} }
static void static void
gst_qt_moov_recover_init (GstQTMoovRecover * qtmr, gst_qt_moov_recover_init (GstQTMoovRecover * qtmr)
GstQTMoovRecoverClass * qtmr_klass)
{ {
} }

View file

@ -117,6 +117,7 @@
#include <gst/gst.h> #include <gst/gst.h>
#include <gst/base/gstcollectpads.h> #include <gst/base/gstcollectpads.h>
#include <gst/video/video.h>
#include <gst/tag/xmpwriter.h> #include <gst/tag/xmpwriter.h>
#include <sys/types.h> #include <sys/types.h>
@ -220,7 +221,7 @@ static void gst_qt_mux_get_property (GObject * object,
/* pad functions */ /* pad functions */
static GstPad *gst_qt_mux_request_new_pad (GstElement * element, static GstPad *gst_qt_mux_request_new_pad (GstElement * element,
GstPadTemplate * templ, const gchar * name); GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
static void gst_qt_mux_release_pad (GstElement * element, GstPad * pad); static void gst_qt_mux_release_pad (GstElement * element, GstPad * pad);
/* event */ /* event */
@ -515,20 +516,23 @@ gst_qt_mux_prepare_jpc_buffer (GstQTPad * qtpad, GstBuffer * buf,
GstQTMux * qtmux) GstQTMux * qtmux)
{ {
GstBuffer *newbuf; GstBuffer *newbuf;
guint8 *data;
gsize size;
GST_LOG_OBJECT (qtmux, "Preparing jpc buffer"); GST_LOG_OBJECT (qtmux, "Preparing jpc buffer");
if (buf == NULL) if (buf == NULL)
return NULL; return NULL;
newbuf = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (buf) + 8); size = gst_buffer_get_size (buf);
gst_buffer_copy_metadata (newbuf, buf, GST_BUFFER_COPY_ALL); newbuf = gst_buffer_new_and_alloc (size + 8);
gst_buffer_copy_into (newbuf, buf, GST_BUFFER_COPY_ALL, 8, size);
GST_WRITE_UINT32_BE (GST_BUFFER_DATA (newbuf), GST_BUFFER_SIZE (newbuf)); data = gst_buffer_map (newbuf, &size, NULL, GST_MAP_WRITE);
GST_WRITE_UINT32_LE (GST_BUFFER_DATA (newbuf) + 4, FOURCC_jp2c); GST_WRITE_UINT32_BE (data, size);
GST_WRITE_UINT32_LE (data + 4, FOURCC_jp2c);
memcpy (GST_BUFFER_DATA (newbuf) + 8, GST_BUFFER_DATA (buf), gst_buffer_unmap (buf, data, size);
GST_BUFFER_SIZE (buf));
gst_buffer_unref (buf); gst_buffer_unref (buf);
return newbuf; return newbuf;
@ -635,6 +639,8 @@ gst_qt_mux_add_mp4_cover (GstQTMux * qtmux, const GstTagList * list,
GstCaps *caps; GstCaps *caps;
GstStructure *structure; GstStructure *structure;
gint flags = 0; gint flags = 0;
guint8 *data;
gsize size;
g_return_if_fail (gst_tag_get_type (tag) == GST_TYPE_BUFFER); g_return_if_fail (gst_tag_get_type (tag) == GST_TYPE_BUFFER);
@ -645,7 +651,9 @@ gst_qt_mux_add_mp4_cover (GstQTMux * qtmux, const GstTagList * list,
if (!buf) if (!buf)
goto done; goto done;
caps = gst_buffer_get_caps (buf); /* FIXME-0.11 caps metadata ? */
/* caps = gst_buffer_get_caps (buf); */
caps = NULL;
if (!caps) { if (!caps) {
GST_WARNING_OBJECT (qtmux, "preview image without caps"); GST_WARNING_OBJECT (qtmux, "preview image without caps");
goto done; goto done;
@ -665,10 +673,11 @@ gst_qt_mux_add_mp4_cover (GstQTMux * qtmux, const GstTagList * list,
goto done; goto done;
} }
data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT
" -> image size %d", GST_FOURCC_ARGS (fourcc), GST_BUFFER_SIZE (buf)); " -> image size %d", GST_FOURCC_ARGS (fourcc), size);
atom_moov_add_tag (qtmux->moov, fourcc, flags, GST_BUFFER_DATA (buf), atom_moov_add_tag (qtmux->moov, fourcc, flags, data, size);
GST_BUFFER_SIZE (buf)); gst_buffer_unmap (buf, data, size);
done: done:
g_value_unset (&value); g_value_unset (&value);
} }
@ -1095,14 +1104,18 @@ gst_qt_mux_add_metadata_tags (GstQTMux * qtmux, const GstTagList * list)
GstCaps *caps = NULL; GstCaps *caps = NULL;
val = gst_tag_list_get_value_index (list, GST_QT_DEMUX_PRIVATE_TAG, i); val = gst_tag_list_get_value_index (list, GST_QT_DEMUX_PRIVATE_TAG, i);
buf = (GstBuffer *) gst_value_get_mini_object (val); buf = (GstBuffer *) gst_value_get_buffer (val);
if (buf && (caps = gst_buffer_get_caps (buf))) { /* FIXME-0.11 */
if (buf && (caps = NULL /*gst_buffer_get_caps (buf) */ )) {
GstStructure *s; GstStructure *s;
const gchar *style = NULL; const gchar *style = NULL;
guint8 *data;
gsize size;
data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
GST_DEBUG_OBJECT (qtmux, "Found private tag %d/%d; size %d, caps %" GST_DEBUG_OBJECT (qtmux, "Found private tag %d/%d; size %d, caps %"
GST_PTR_FORMAT, i, num_tags, GST_BUFFER_SIZE (buf), caps); GST_PTR_FORMAT, i, num_tags, size, caps);
s = gst_caps_get_structure (caps, 0); s = gst_caps_get_structure (caps, 0);
if (s && (style = gst_structure_get_string (s, "style"))) { if (s && (style = gst_structure_get_string (s, "style"))) {
/* try to prevent some style tag ending up into another variant /* try to prevent some style tag ending up into another variant
@ -1112,10 +1125,10 @@ gst_qt_mux_add_metadata_tags (GstQTMux * qtmux, const GstTagList * list)
(strcmp (style, "iso") == 0 && (strcmp (style, "iso") == 0 &&
qtmux_klass->format == GST_QT_MUX_FORMAT_3GP)) { qtmux_klass->format == GST_QT_MUX_FORMAT_3GP)) {
GST_DEBUG_OBJECT (qtmux, "Adding private tag"); GST_DEBUG_OBJECT (qtmux, "Adding private tag");
atom_moov_add_blob_tag (qtmux->moov, GST_BUFFER_DATA (buf), atom_moov_add_blob_tag (qtmux->moov, data, size);
GST_BUFFER_SIZE (buf));
} }
} }
gst_buffer_unmap (buf, data, size);
gst_caps_unref (caps); gst_caps_unref (caps);
} }
} }
@ -1162,8 +1175,8 @@ _gst_buffer_new_take_data (guint8 * data, guint size)
GstBuffer *buf; GstBuffer *buf;
buf = gst_buffer_new (); buf = gst_buffer_new ();
GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data; gst_buffer_take_memory (buf, -1,
GST_BUFFER_SIZE (buf) = size; gst_memory_new_wrapped (0, data, g_free, size, 0, size));
return buf; return buf;
} }
@ -1173,21 +1186,21 @@ gst_qt_mux_send_buffer (GstQTMux * qtmux, GstBuffer * buf, guint64 * offset,
gboolean mind_fast) gboolean mind_fast)
{ {
GstFlowReturn res; GstFlowReturn res;
guint8 *data; gsize size;
guint size;
g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
data = GST_BUFFER_DATA (buf); size = gst_buffer_get_size (buf);
size = GST_BUFFER_SIZE (buf);
GST_LOG_OBJECT (qtmux, "sending buffer size %d", size); GST_LOG_OBJECT (qtmux, "sending buffer size %d", size);
if (mind_fast && qtmux->fast_start_file) { if (mind_fast && qtmux->fast_start_file) {
gint ret; gint ret;
guint8 *data;
GST_LOG_OBJECT (qtmux, "to temporary file"); GST_LOG_OBJECT (qtmux, "to temporary file");
data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
ret = fwrite (data, sizeof (guint8), size, qtmux->fast_start_file); ret = fwrite (data, sizeof (guint8), size, qtmux->fast_start_file);
gst_buffer_unmap (buf, data, size);
gst_buffer_unref (buf); gst_buffer_unref (buf);
if (ret != size) if (ret != size)
goto write_error; goto write_error;
@ -1195,9 +1208,6 @@ gst_qt_mux_send_buffer (GstQTMux * qtmux, GstBuffer * buf, guint64 * offset,
res = GST_FLOW_OK; res = GST_FLOW_OK;
} else { } else {
GST_LOG_OBJECT (qtmux, "downstream"); GST_LOG_OBJECT (qtmux, "downstream");
buf = gst_buffer_make_metadata_writable (buf);
gst_buffer_set_caps (buf, GST_PAD_CAPS (qtmux->srcpad));
res = gst_pad_push (qtmux->srcpad, buf); res = gst_pad_push (qtmux->srcpad, buf);
} }
@ -1248,16 +1258,19 @@ gst_qt_mux_send_buffered_data (GstQTMux * qtmux, guint64 * offset)
* (somehow optimize copy?) */ * (somehow optimize copy?) */
GST_DEBUG_OBJECT (qtmux, "Sending buffered data"); GST_DEBUG_OBJECT (qtmux, "Sending buffered data");
while (ret == GST_FLOW_OK) { while (ret == GST_FLOW_OK) {
gint r;
const int bufsize = 4096; const int bufsize = 4096;
guint8 *data;
gsize size;
buf = gst_buffer_new_and_alloc (bufsize); buf = gst_buffer_new_and_alloc (bufsize);
r = fread (GST_BUFFER_DATA (buf), sizeof (guint8), bufsize, gst_buffer_map (buf, &size, NULL, GST_MAP_WRITE);
qtmux->fast_start_file); size = fread (data, sizeof (guint8), bufsize, qtmux->fast_start_file);
if (r == 0) if (size == 0) {
gst_buffer_unmap (buf, data, -1);
break; break;
GST_BUFFER_SIZE (buf) = r; }
GST_LOG_OBJECT (qtmux, "Pushing buffered buffer of size %d", r); gst_buffer_unmap (buf, data, size);
GST_LOG_OBJECT (qtmux, "Pushing buffered buffer of size %d", (gint) size);
ret = gst_qt_mux_send_buffer (qtmux, buf, offset, FALSE); ret = gst_qt_mux_send_buffer (qtmux, buf, offset, FALSE);
buf = NULL; buf = NULL;
} }
@ -1354,9 +1367,11 @@ static GstFlowReturn
gst_qt_mux_update_mdat_size (GstQTMux * qtmux, guint64 mdat_pos, gst_qt_mux_update_mdat_size (GstQTMux * qtmux, guint64 mdat_pos,
guint64 mdat_size, guint64 * offset) guint64 mdat_size, guint64 * offset)
{ {
GstEvent *event;
GstBuffer *buf; GstBuffer *buf;
gboolean large_file; gboolean large_file;
GstSegment segment;
guint8 *data;
gsize size;
large_file = (mdat_size > MDAT_LARGE_FILE_LIMIT); large_file = (mdat_size > MDAT_LARGE_FILE_LIMIT);
@ -1364,23 +1379,23 @@ gst_qt_mux_update_mdat_size (GstQTMux * qtmux, guint64 mdat_pos,
mdat_pos += 8; mdat_pos += 8;
/* seek and rewrite the header */ /* seek and rewrite the header */
event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, gst_segment_init (&segment, GST_FORMAT_BYTES);
mdat_pos, GST_CLOCK_TIME_NONE, 0); segment.start = mdat_pos;
gst_pad_push_event (qtmux->srcpad, event); gst_pad_push_event (qtmux->srcpad, gst_event_new_segment (&segment));
if (large_file) { if (large_file) {
buf = gst_buffer_new_and_alloc (sizeof (guint64)); buf = gst_buffer_new_and_alloc (sizeof (guint64));
GST_WRITE_UINT64_BE (GST_BUFFER_DATA (buf), mdat_size + 16); data = gst_buffer_map (buf, &size, NULL, GST_MAP_WRITE);
GST_WRITE_UINT64_BE (data, mdat_size + 16);
} else { } else {
guint8 *data;
buf = gst_buffer_new_and_alloc (16); buf = gst_buffer_new_and_alloc (16);
data = GST_BUFFER_DATA (buf); data = gst_buffer_map (buf, &size, NULL, GST_MAP_WRITE);
GST_WRITE_UINT32_BE (data, 8); GST_WRITE_UINT32_BE (data, 8);
GST_WRITE_UINT32_LE (data + 4, FOURCC_free); GST_WRITE_UINT32_LE (data + 4, FOURCC_free);
GST_WRITE_UINT32_BE (data + 8, mdat_size + 8); GST_WRITE_UINT32_BE (data + 8, mdat_size + 8);
GST_WRITE_UINT32_LE (data + 12, FOURCC_mdat); GST_WRITE_UINT32_LE (data + 12, FOURCC_mdat);
} }
gst_buffer_unmap (buf, data, size);
return gst_qt_mux_send_buffer (qtmux, buf, offset, FALSE); return gst_qt_mux_send_buffer (qtmux, buf, offset, FALSE);
} }
@ -1467,9 +1482,12 @@ gst_qt_mux_set_header_on_caps (GstQTMux * mux, GstBuffer * buf)
GstStructure *structure; GstStructure *structure;
GValue array = { 0 }; GValue array = { 0 };
GValue value = { 0 }; GValue value = { 0 };
GstCaps *caps = GST_PAD_CAPS (mux->srcpad); GstCaps *caps, *tcaps;
tcaps = gst_pad_get_current_caps (mux->srcpad);
caps = gst_caps_copy (tcaps);
gst_caps_unref (tcaps);
caps = gst_caps_copy (GST_PAD_CAPS (mux->srcpad));
structure = gst_caps_get_structure (caps, 0); structure = gst_caps_get_structure (caps, 0);
g_value_init (&array, GST_TYPE_ARRAY); g_value_init (&array, GST_TYPE_ARRAY);
@ -1589,6 +1607,7 @@ gst_qt_mux_start_file (GstQTMux * qtmux)
{ {
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
GstCaps *caps; GstCaps *caps;
GstSegment segment;
GST_DEBUG_OBJECT (qtmux, "starting file"); GST_DEBUG_OBJECT (qtmux, "starting file");
@ -1600,8 +1619,8 @@ gst_qt_mux_start_file (GstQTMux * qtmux)
gst_caps_unref (caps); gst_caps_unref (caps);
/* let downstream know we think in BYTES and expect to do seeking later on */ /* let downstream know we think in BYTES and expect to do seeking later on */
gst_pad_push_event (qtmux->srcpad, gst_segment_init (&segment, GST_FORMAT_BYTES);
gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0)); gst_pad_push_event (qtmux->srcpad, gst_event_new_segment (&segment));
/* initialize our moov recovery file */ /* initialize our moov recovery file */
GST_OBJECT_LOCK (qtmux); GST_OBJECT_LOCK (qtmux);
@ -1760,7 +1779,7 @@ gst_qt_mux_stop_file (GstQTMux * qtmux)
} }
if (qtmux->fragment_sequence) { if (qtmux->fragment_sequence) {
GstEvent *event; GstSegment segment;
if (qtmux->mfra) { if (qtmux->mfra) {
guint8 *data = NULL; guint8 *data = NULL;
@ -1780,7 +1799,6 @@ gst_qt_mux_stop_file (GstQTMux * qtmux)
return GST_FLOW_OK; return GST_FLOW_OK;
} }
timescale = qtmux->timescale; timescale = qtmux->timescale;
/* only mvex duration is updated, /* only mvex duration is updated,
* mvhd should be consistent with empty moov * mvhd should be consistent with empty moov
@ -1790,9 +1808,9 @@ gst_qt_mux_stop_file (GstQTMux * qtmux)
GST_DEBUG_OBJECT (qtmux, "rewriting moov with mvex duration %" GST_DEBUG_OBJECT (qtmux, "rewriting moov with mvex duration %"
GST_TIME_FORMAT, GST_TIME_ARGS (first_ts)); GST_TIME_FORMAT, GST_TIME_ARGS (first_ts));
/* seek and rewrite the header */ /* seek and rewrite the header */
event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, gst_segment_init (&segment, GST_FORMAT_BYTES);
qtmux->mdat_pos, GST_CLOCK_TIME_NONE, 0); segment.start = qtmux->mdat_pos;
gst_pad_push_event (qtmux->srcpad, event); gst_pad_push_event (qtmux->srcpad, gst_event_new_segment (&segment));
/* no need to seek back */ /* no need to seek back */
return gst_qt_mux_send_moov (qtmux, NULL, FALSE); return gst_qt_mux_send_moov (qtmux, NULL, FALSE);
} }
@ -1948,14 +1966,15 @@ flush:
pad->traf = NULL; pad->traf = NULL;
atom_moof_copy_data (moof, &data, &size, &offset); atom_moof_copy_data (moof, &data, &size, &offset);
buffer = _gst_buffer_new_take_data (data, offset); buffer = _gst_buffer_new_take_data (data, offset);
GST_LOG_OBJECT (qtmux, "writing moof size %d", GST_BUFFER_SIZE (buffer)); GST_LOG_OBJECT (qtmux, "writing moof size %d",
gst_buffer_get_size (buffer));
ret = gst_qt_mux_send_buffer (qtmux, buffer, &qtmux->header_size, FALSE); ret = gst_qt_mux_send_buffer (qtmux, buffer, &qtmux->header_size, FALSE);
/* and actual data */ /* and actual data */
total_size = 0; total_size = 0;
for (i = 0; i < atom_array_get_len (&pad->fragment_buffers); i++) { for (i = 0; i < atom_array_get_len (&pad->fragment_buffers); i++) {
total_size += total_size +=
GST_BUFFER_SIZE (atom_array_index (&pad->fragment_buffers, i)); gst_buffer_get_size (atom_array_index (&pad->fragment_buffers, i));
} }
GST_LOG_OBJECT (qtmux, "writing %d buffers, total_size %d", GST_LOG_OBJECT (qtmux, "writing %d buffers, total_size %d",
@ -2046,7 +2065,7 @@ gst_qt_mux_get_asc_buffer_ts (GstQTMux * qtmux, GstQTPad * pad, GstBuffer * buf)
buf = pad->buf_entries[pad->buf_head]; buf = pad->buf_entries[pad->buf_head];
pad->buf_entries[pad->buf_head++] = NULL; pad->buf_entries[pad->buf_head++] = NULL;
pad->buf_head %= wrap; pad->buf_head %= wrap;
buf = gst_buffer_make_metadata_writable (buf); buf = gst_buffer_make_writable (buf);
/* track original ts (= pts ?) for later */ /* track original ts (= pts ?) for later */
GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_TIMESTAMP (buf); GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_TIMESTAMP (buf);
GST_BUFFER_TIMESTAMP (buf) = ts; GST_BUFFER_TIMESTAMP (buf) = ts;
@ -2224,7 +2243,7 @@ again:
buffer (= chunk)), but can also be fixed-packet-size codecs like ADPCM buffer (= chunk)), but can also be fixed-packet-size codecs like ADPCM
*/ */
sample_size = pad->sample_size; sample_size = pad->sample_size;
if (GST_BUFFER_SIZE (last_buf) % sample_size != 0) if (gst_buffer_get_size (last_buf) % sample_size != 0)
goto fragmented_sample; goto fragmented_sample;
/* note: qt raw audio storage warps it implicitly into a timewise /* note: qt raw audio storage warps it implicitly into a timewise
* perfect stream, discarding buffer times */ * perfect stream, discarding buffer times */
@ -2232,7 +2251,7 @@ again:
nsamples = gst_util_uint64_scale_round (GST_BUFFER_DURATION (last_buf), nsamples = gst_util_uint64_scale_round (GST_BUFFER_DURATION (last_buf),
atom_trak_get_timescale (pad->trak), GST_SECOND); atom_trak_get_timescale (pad->trak), GST_SECOND);
} else { } else {
nsamples = GST_BUFFER_SIZE (last_buf) / sample_size; nsamples = gst_buffer_get_size (last_buf) / sample_size;
} }
duration = GST_BUFFER_DURATION (last_buf) / nsamples; duration = GST_BUFFER_DURATION (last_buf) / nsamples;
@ -2241,7 +2260,7 @@ again:
pad->last_dts += duration * nsamples; pad->last_dts += duration * nsamples;
} else { } else {
nsamples = 1; nsamples = 1;
sample_size = GST_BUFFER_SIZE (last_buf); sample_size = gst_buffer_get_size (last_buf);
if (pad->have_dts) { if (pad->have_dts) {
gint64 scaled_dts; gint64 scaled_dts;
pad->last_dts = GST_BUFFER_OFFSET_END (last_buf); pad->last_dts = GST_BUFFER_OFFSET_END (last_buf);
@ -2473,7 +2492,7 @@ gst_qt_mux_collected (GstCollectPads * pads, gpointer user_data)
GST_LOG_OBJECT (qtmux, "selected pad %s with time %" GST_TIME_FORMAT, GST_LOG_OBJECT (qtmux, "selected pad %s with time %" GST_TIME_FORMAT,
GST_PAD_NAME (best_pad->collect.pad), GST_TIME_ARGS (best_time)); GST_PAD_NAME (best_pad->collect.pad), GST_TIME_ARGS (best_time));
buf = gst_collect_pads_pop (pads, &best_pad->collect); buf = gst_collect_pads_pop (pads, &best_pad->collect);
buf = gst_buffer_make_metadata_writable (buf); buf = gst_buffer_make_writable (buf);
GST_BUFFER_TIMESTAMP (buf) = best_time; GST_BUFFER_TIMESTAMP (buf) = best_time;
ret = gst_qt_mux_add_buffer (qtmux, best_pad, buf); ret = gst_qt_mux_add_buffer (qtmux, best_pad, buf);
} else { } else {
@ -2528,7 +2547,6 @@ gst_qt_mux_audio_sink_set_caps (GstPad * pad, GstCaps * caps)
AtomInfo *ext_atom = NULL; AtomInfo *ext_atom = NULL;
gint constant_size = 0; gint constant_size = 0;
const gchar *stream_format; const gchar *stream_format;
GstCaps *current_caps = NULL;
/* find stream data */ /* find stream data */
qtpad = (GstQTPad *) gst_pad_get_element_private (pad); qtpad = (GstQTPad *) gst_pad_get_element_private (pad);
@ -2540,15 +2558,19 @@ gst_qt_mux_audio_sink_set_caps (GstPad * pad, GstCaps * caps)
* the old caps are a subset of the new one (this means upstream * the old caps are a subset of the new one (this means upstream
* added more info to the caps, as both should be 'fixed' caps) */ * added more info to the caps, as both should be 'fixed' caps) */
if (qtpad->fourcc) { if (qtpad->fourcc) {
g_object_get (pad, "caps", &current_caps, NULL); GstCaps *current_caps;
current_caps = gst_pad_get_current_caps (pad);
g_assert (caps != NULL); g_assert (caps != NULL);
if (!gst_qtmux_caps_is_subset_full (qtmux, current_caps, caps)) { if (!gst_qtmux_caps_is_subset_full (qtmux, current_caps, caps)) {
gst_caps_unref (current_caps);
goto refuse_renegotiation; goto refuse_renegotiation;
} }
GST_DEBUG_OBJECT (qtmux, GST_DEBUG_OBJECT (qtmux,
"pad %s accepted renegotiation to %" GST_PTR_FORMAT " from %" "pad %s accepted renegotiation to %" GST_PTR_FORMAT " from %"
GST_PTR_FORMAT, GST_PAD_NAME (pad), caps, GST_PAD_CAPS (pad)); GST_PTR_FORMAT, GST_PAD_NAME (pad), caps, current_caps);
gst_caps_unref (current_caps);
} }
GST_DEBUG_OBJECT (qtmux, "%s:%s, caps=%" GST_PTR_FORMAT, GST_DEBUG_OBJECT (qtmux, "%s:%s, caps=%" GST_PTR_FORMAT,
@ -2625,11 +2647,12 @@ gst_qt_mux_audio_sink_set_caps (GstPad * pad, GstCaps * caps)
"assuming 'raw'"); "assuming 'raw'");
} }
if (!codec_data || GST_BUFFER_SIZE (codec_data) < 2) if (!codec_data || gst_buffer_get_size ((GstBuffer *) codec_data) < 2)
GST_WARNING_OBJECT (qtmux, "no (valid) codec_data for AAC audio"); GST_WARNING_OBJECT (qtmux, "no (valid) codec_data for AAC audio");
else { else {
guint8 profile = GST_READ_UINT8 (GST_BUFFER_DATA (codec_data)); guint8 profile;
gst_buffer_extract ((GstBuffer *) codec_data, 0, &profile, 1);
/* warn if not Low Complexity profile */ /* warn if not Low Complexity profile */
profile >>= 3; profile >>= 3;
if (profile != 2) if (profile != 2)
@ -2756,19 +2779,25 @@ gst_qt_mux_audio_sink_set_caps (GstPad * pad, GstCaps * caps)
} else if (strcmp (mimetype, "audio/x-alac") == 0) { } else if (strcmp (mimetype, "audio/x-alac") == 0) {
GstBuffer *codec_config; GstBuffer *codec_config;
gint len; gint len;
guint8 *data;
gsize size;
entry.fourcc = FOURCC_alac; entry.fourcc = FOURCC_alac;
data = gst_buffer_map ((GstBuffer *) codec_data, &size, NULL, GST_MAP_READ);
/* let's check if codec data already comes with 'alac' atom prefix */ /* let's check if codec data already comes with 'alac' atom prefix */
if (!codec_data || (len = GST_BUFFER_SIZE (codec_data)) < 28) { if (!codec_data || (len = size) < 28) {
GST_DEBUG_OBJECT (qtmux, "broken caps, codec data missing"); GST_DEBUG_OBJECT (qtmux, "broken caps, codec data missing");
gst_buffer_unmap ((GstBuffer *) codec_data, data, size);
goto refuse_caps; goto refuse_caps;
} }
if (GST_READ_UINT32_LE (GST_BUFFER_DATA (codec_data) + 4) == FOURCC_alac) { if (GST_READ_UINT32_LE (data + 4) == FOURCC_alac) {
len -= 8; len -= 8;
codec_config = gst_buffer_create_sub ((GstBuffer *) codec_data, 8, len); codec_config =
gst_buffer_copy_region ((GstBuffer *) codec_data, 0, 8, len);
} else { } else {
codec_config = gst_buffer_ref ((GstBuffer *) codec_data); codec_config = gst_buffer_ref ((GstBuffer *) codec_data);
} }
gst_buffer_unmap ((GstBuffer *) codec_data, data, size);
if (len != 28) { if (len != 28) {
/* does not look good, but perhaps some trailing unneeded stuff */ /* does not look good, but perhaps some trailing unneeded stuff */
GST_WARNING_OBJECT (qtmux, "unexpected codec-data size, possibly broken"); GST_WARNING_OBJECT (qtmux, "unexpected codec-data size, possibly broken");
@ -2778,9 +2807,10 @@ gst_qt_mux_audio_sink_set_caps (GstPad * pad, GstCaps * caps)
else else
ext_atom = build_codec_data_extension (FOURCC_alac, codec_config); ext_atom = build_codec_data_extension (FOURCC_alac, codec_config);
/* set some more info */ /* set some more info */
data = gst_buffer_map (codec_config, &size, NULL, GST_MAP_READ);
entry.bytes_per_sample = 2; entry.bytes_per_sample = 2;
entry.samples_per_packet = entry.samples_per_packet = GST_READ_UINT32_BE (data + 4);
GST_READ_UINT32_BE (GST_BUFFER_DATA (codec_config) + 4); gst_buffer_unmap (codec_config, data, size);
gst_buffer_unref (codec_config); gst_buffer_unref (codec_config);
} }
@ -2850,7 +2880,6 @@ gst_qt_mux_video_sink_set_caps (GstPad * pad, GstCaps * caps)
GList *ext_atom_list = NULL; GList *ext_atom_list = NULL;
gboolean sync = FALSE; gboolean sync = FALSE;
int par_num, par_den; int par_num, par_den;
GstCaps *current_caps = NULL;
/* find stream data */ /* find stream data */
qtpad = (GstQTPad *) gst_pad_get_element_private (pad); qtpad = (GstQTPad *) gst_pad_get_element_private (pad);
@ -2862,15 +2891,19 @@ gst_qt_mux_video_sink_set_caps (GstPad * pad, GstCaps * caps)
* the old caps are a subset of the new one (this means upstream * the old caps are a subset of the new one (this means upstream
* added more info to the caps, as both should be 'fixed' caps) */ * added more info to the caps, as both should be 'fixed' caps) */
if (qtpad->fourcc) { if (qtpad->fourcc) {
g_object_get (pad, "caps", &current_caps, NULL); GstCaps *current_caps;
current_caps = gst_pad_get_current_caps (pad);
g_assert (caps != NULL); g_assert (caps != NULL);
if (!gst_qtmux_caps_is_subset_full (qtmux, current_caps, caps)) { if (!gst_qtmux_caps_is_subset_full (qtmux, current_caps, caps)) {
gst_caps_unref (current_caps);
goto refuse_renegotiation; goto refuse_renegotiation;
} }
GST_DEBUG_OBJECT (qtmux, GST_DEBUG_OBJECT (qtmux,
"pad %s accepted renegotiation to %" GST_PTR_FORMAT " from %" "pad %s accepted renegotiation to %" GST_PTR_FORMAT " from %"
GST_PTR_FORMAT, GST_PAD_NAME (pad), caps, GST_PAD_CAPS (pad)); GST_PTR_FORMAT, GST_PAD_NAME (pad), caps, current_caps);
gst_caps_unref (current_caps);
} }
GST_DEBUG_OBJECT (qtmux, "%s:%s, caps=%" GST_PTR_FORMAT, GST_DEBUG_OBJECT (qtmux, "%s:%s, caps=%" GST_PTR_FORMAT,
@ -2925,24 +2958,27 @@ gst_qt_mux_video_sink_set_caps (GstPad * pad, GstCaps * caps)
sync = TRUE; sync = TRUE;
/* now map onto a fourcc, and some extra properties */ /* now map onto a fourcc, and some extra properties */
if (strcmp (mimetype, "video/x-raw-rgb") == 0) { if (strcmp (mimetype, "video/x-raw") == 0) {
gint bpp; const gchar *format;
GstVideoFormat fmt;
entry.fourcc = FOURCC_raw_; format = gst_structure_get_string (structure, "format");
gst_structure_get_int (structure, "bpp", &bpp); fmt = gst_video_format_from_string (format);
entry.depth = bpp;
sync = FALSE;
} else if (strcmp (mimetype, "video/x-raw-yuv") == 0) {
guint32 format = 0;
sync = FALSE; switch (fmt) {
gst_structure_get_fourcc (structure, "format", &format); case GST_VIDEO_FORMAT_UYVY:
switch (format) {
case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
if (depth == -1) if (depth == -1)
depth = 24; depth = 24;
entry.fourcc = FOURCC_2vuy; entry.fourcc = FOURCC_2vuy;
entry.depth = depth; entry.depth = depth;
sync = FALSE;
break;
default:
if (gst_video_format_is_rgb (fmt)) {
entry.fourcc = FOURCC_raw_;
entry.depth = gst_video_format_get_pixel_stride (fmt, 0) * 8;
sync = FALSE;
}
break; break;
} }
} else if (strcmp (mimetype, "video/x-h263") == 0) { } else if (strcmp (mimetype, "video/x-h263") == 0) {
@ -3155,8 +3191,8 @@ refuse_caps:
refuse_renegotiation: refuse_renegotiation:
{ {
GST_WARNING_OBJECT (qtmux, GST_WARNING_OBJECT (qtmux,
"pad %s refused renegotiation to %" GST_PTR_FORMAT " from %" "pad %s refused renegotiation to %" GST_PTR_FORMAT, GST_PAD_NAME (pad),
GST_PTR_FORMAT, GST_PAD_NAME (pad), caps, GST_PAD_CAPS (pad)); caps);
gst_object_unref (qtmux); gst_object_unref (qtmux);
return FALSE; return FALSE;
} }
@ -3170,7 +3206,23 @@ gst_qt_mux_sink_event (GstPad * pad, GstEvent * event)
guint32 avg_bitrate = 0, max_bitrate = 0; guint32 avg_bitrate = 0, max_bitrate = 0;
qtmux = GST_QT_MUX_CAST (gst_pad_get_parent (pad)); qtmux = GST_QT_MUX_CAST (gst_pad_get_parent (pad));
switch (GST_EVENT_TYPE (event)) { switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_CAPS:
{
GstCaps *caps;
GstQTPad *collect_pad;
gst_event_parse_caps (event, &caps);
/* find stream data */
collect_pad = (GstQTPad *) gst_pad_get_element_private (pad);
g_assert (collect_pad);
g_assert (collect_pad->set_caps);
collect_pad->set_caps (pad, caps);
break;
}
case GST_EVENT_TAG:{ case GST_EVENT_TAG:{
GstTagList *list; GstTagList *list;
GstTagSetter *setter = GST_TAG_SETTER (qtmux); GstTagSetter *setter = GST_TAG_SETTER (qtmux);
@ -3232,7 +3284,7 @@ gst_qt_mux_release_pad (GstElement * element, GstPad * pad)
static GstPad * static GstPad *
gst_qt_mux_request_new_pad (GstElement * element, gst_qt_mux_request_new_pad (GstElement * element,
GstPadTemplate * templ, const gchar * req_name) GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps)
{ {
GstElementClass *klass = GST_ELEMENT_GET_CLASS (element); GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
GstQTMux *qtmux = GST_QT_MUX_CAST (element); GstQTMux *qtmux = GST_QT_MUX_CAST (element);
@ -3273,11 +3325,9 @@ gst_qt_mux_request_new_pad (GstElement * element,
/* set up pad functions */ /* set up pad functions */
if (audio) if (audio)
gst_pad_set_setcaps_function (newpad, collect_pad->set_caps = GST_DEBUG_FUNCPTR (gst_qt_mux_audio_sink_set_caps);
GST_DEBUG_FUNCPTR (gst_qt_mux_audio_sink_set_caps));
else else
gst_pad_set_setcaps_function (newpad, collect_pad->set_caps = GST_DEBUG_FUNCPTR (gst_qt_mux_video_sink_set_caps);
GST_DEBUG_FUNCPTR (gst_qt_mux_video_sink_set_caps));
/* FIXME: hacked way to override/extend the event function of /* FIXME: hacked way to override/extend the event function of
* GstCollectPads; because it sets its own event function giving the * GstCollectPads; because it sets its own event function giving the

View file

@ -125,6 +125,7 @@ struct _GstQTPad
/* if nothing is set, it won't be called */ /* if nothing is set, it won't be called */
GstQTPadPrepareBufferFunc prepare_buf_func; GstQTPadPrepareBufferFunc prepare_buf_func;
gboolean (*set_caps) (GstPad * pad, GstCaps * caps);
}; };
typedef enum _GstQTMuxState typedef enum _GstQTMuxState

View file

@ -153,10 +153,8 @@ GstQTMuxFormatProp gst_qt_mux_format_list[] = {
"GstQTMux", "GstQTMux",
GST_STATIC_CAPS ("video/quicktime, variant = (string) apple; " GST_STATIC_CAPS ("video/quicktime, variant = (string) apple; "
"video/quicktime"), "video/quicktime"),
GST_STATIC_CAPS ("video/x-raw-rgb, " GST_STATIC_CAPS ("video/x-raw, "
COMMON_VIDEO_CAPS "; " "format = (string) { RGB, UYVY }, "
"video/x-raw-yuv, "
"format = (fourcc) UYVY, "
COMMON_VIDEO_CAPS "; " COMMON_VIDEO_CAPS "; "
MPEG4V_CAPS "; " MPEG4V_CAPS "; "
H263_CAPS "; " H263_CAPS "; "
@ -361,12 +359,18 @@ gst_qt_mux_map_format_to_header (GstQTMuxFormat format, GstBuffer ** _prefix,
break; break;
} }
case GST_QT_MUX_FORMAT_MJ2: case GST_QT_MUX_FORMAT_MJ2:
{
guint8 *bdata;
major = FOURCC_mjp2; major = FOURCC_mjp2;
comp = mjp2_brands; comp = mjp2_brands;
version = 0; version = 0;
prefix = gst_buffer_new_and_alloc (sizeof (mjp2_prefix)); prefix = gst_buffer_new_and_alloc (sizeof (mjp2_prefix));
memcpy (GST_BUFFER_DATA (prefix), mjp2_prefix, GST_BUFFER_SIZE (prefix)); bdata = gst_buffer_map (prefix, NULL, NULL, GST_MAP_WRITE);
memcpy (bdata, mjp2_prefix, sizeof (mjp2_prefix));
gst_buffer_unmap (prefix, bdata, -1);
break; break;
}
default: default:
g_assert_not_reached (); g_assert_not_reached ();
break; break;

View file

@ -91,8 +91,8 @@ GST_STATIC_PAD_TEMPLATE ("sink",
"encoding-name = (string) { \"X-QT\", \"X-QUICKTIME\" }") "encoding-name = (string) { \"X-QT\", \"X-QUICKTIME\" }")
); );
GST_BOILERPLATE (GstRtpXQTDepay, gst_rtp_xqt_depay, GstBaseRTPDepayload, #define gst_rtp_xqt_depay_parent_class parent_class
GST_TYPE_BASE_RTP_DEPAYLOAD); G_DEFINE_TYPE (GstRtpXQTDepay, gst_rtp_xqt_depay, GST_TYPE_BASE_RTP_DEPAYLOAD);
static void gst_rtp_xqt_depay_finalize (GObject * object); static void gst_rtp_xqt_depay_finalize (GObject * object);
@ -104,21 +104,6 @@ static GstBuffer *gst_rtp_xqt_depay_process (GstBaseRTPDepayload * depayload,
static GstStateChangeReturn gst_rtp_xqt_depay_change_state (GstElement * static GstStateChangeReturn gst_rtp_xqt_depay_change_state (GstElement *
element, GstStateChange transition); element, GstStateChange transition);
static void
gst_rtp_xqt_depay_base_init (gpointer klass)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&gst_rtp_xqt_depay_src_template));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&gst_rtp_xqt_depay_sink_template));
gst_element_class_set_details_simple (element_class, "RTP packet depayloader",
"Codec/Depayloader/Network",
"Extracts Quicktime audio/video from RTP packets",
"Wim Taymans <wim@fluendo.com>");
}
static void static void
gst_rtp_xqt_depay_class_init (GstRtpXQTDepayClass * klass) gst_rtp_xqt_depay_class_init (GstRtpXQTDepayClass * klass)
@ -142,11 +127,20 @@ gst_rtp_xqt_depay_class_init (GstRtpXQTDepayClass * klass)
GST_DEBUG_CATEGORY_INIT (rtpxqtdepay_debug, "rtpxqtdepay", 0, GST_DEBUG_CATEGORY_INIT (rtpxqtdepay_debug, "rtpxqtdepay", 0,
"QT Media RTP Depayloader"); "QT Media RTP Depayloader");
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&gst_rtp_xqt_depay_src_template));
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&gst_rtp_xqt_depay_sink_template));
gst_element_class_set_details_simple (gstelement_class,
"RTP packet depayloader", "Codec/Depayloader/Network",
"Extracts Quicktime audio/video from RTP packets",
"Wim Taymans <wim@fluendo.com>");
} }
static void static void
gst_rtp_xqt_depay_init (GstRtpXQTDepay * rtpxqtdepay, gst_rtp_xqt_depay_init (GstRtpXQTDepay * rtpxqtdepay)
GstRtpXQTDepayClass * klass)
{ {
rtpxqtdepay->adapter = gst_adapter_new (); rtpxqtdepay->adapter = gst_adapter_new ();
} }
@ -201,6 +195,7 @@ gst_rtp_quicktime_parse_sd (GstRtpXQTDepay * rtpxqtdepay, guint8 * data,
GstBuffer *buf; GstBuffer *buf;
gint size; gint size;
GstCaps *caps; GstCaps *caps;
guint8 *bdata;
GST_DEBUG_OBJECT (rtpxqtdepay, "found avcC codec_data in sd, %u", GST_DEBUG_OBJECT (rtpxqtdepay, "found avcC codec_data in sd, %u",
chlen); chlen);
@ -212,7 +207,9 @@ gst_rtp_quicktime_parse_sd (GstRtpXQTDepay * rtpxqtdepay, guint8 * data,
size = len - 8; size = len - 8;
buf = gst_buffer_new_and_alloc (size); buf = gst_buffer_new_and_alloc (size);
memcpy (GST_BUFFER_DATA (buf), data + 8, size); bdata = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
memcpy (bdata, data + 8, size);
gst_buffer_unmap (buf, bdata, -1);
caps = gst_caps_new_simple ("video/x-h264", caps = gst_caps_new_simple ("video/x-h264",
"codec_data", GST_TYPE_BUFFER, buf, NULL); "codec_data", GST_TYPE_BUFFER, buf, NULL);
gst_buffer_unref (buf); gst_buffer_unref (buf);
@ -255,11 +252,14 @@ static GstBuffer *
gst_rtp_xqt_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) gst_rtp_xqt_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
{ {
GstRtpXQTDepay *rtpxqtdepay; GstRtpXQTDepay *rtpxqtdepay;
GstBuffer *outbuf; GstBuffer *outbuf = NULL;
gboolean m; gboolean m;
GstRTPBuffer rtp;
rtpxqtdepay = GST_RTP_XQT_DEPAY (depayload); rtpxqtdepay = GST_RTP_XQT_DEPAY (depayload);
gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);
if (!gst_rtp_buffer_validate (buf)) if (!gst_rtp_buffer_validate (buf))
goto bad_packet; goto bad_packet;
@ -270,7 +270,7 @@ gst_rtp_xqt_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
GST_DEBUG_OBJECT (rtpxqtdepay, "we need resync"); GST_DEBUG_OBJECT (rtpxqtdepay, "we need resync");
} }
m = gst_rtp_buffer_get_marker (buf); m = gst_rtp_buffer_get_marker (&rtp);
GST_LOG_OBJECT (rtpxqtdepay, "marker: %d", m); GST_LOG_OBJECT (rtpxqtdepay, "marker: %d", m);
{ {
@ -279,9 +279,11 @@ gst_rtp_xqt_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
guint8 *payload; guint8 *payload;
guint8 ver, pck; guint8 ver, pck;
gboolean s, q, l, d; gboolean s, q, l, d;
guint8 *bdata;
gsize bsize;
payload_len = gst_rtp_buffer_get_payload_len (buf); payload_len = gst_rtp_buffer_get_payload_len (&rtp);
payload = gst_rtp_buffer_get_payload (buf); payload = gst_rtp_buffer_get_payload (&rtp);
/* 1 2 3 /* 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
@ -545,8 +547,11 @@ gst_rtp_xqt_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
{ {
/* multiple samples per packet. */ /* multiple samples per packet. */
outbuf = gst_buffer_new_and_alloc (payload_len); outbuf = gst_buffer_new_and_alloc (payload_len);
memcpy (GST_BUFFER_DATA (outbuf), payload, payload_len); bdata = gst_buffer_map (outbuf, &bsize, NULL, GST_MAP_WRITE);
return outbuf; memcpy (bdata, payload, payload_len);
gst_buffer_unmap (outbuf, bdata, bsize);
goto done;
} }
case 2: case 2:
{ {
@ -586,7 +591,9 @@ gst_rtp_xqt_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
slen = payload_len; slen = payload_len;
outbuf = gst_buffer_new_and_alloc (slen); outbuf = gst_buffer_new_and_alloc (slen);
memcpy (GST_BUFFER_DATA (outbuf), payload, slen); bdata = gst_buffer_map (outbuf, &bsize, NULL, GST_MAP_WRITE);
memcpy (bdata, payload, slen);
gst_buffer_unmap (outbuf, bdata, bsize);
if (!s) if (!s)
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT); GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
@ -604,7 +611,9 @@ gst_rtp_xqt_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
{ {
/* one sample per packet, use adapter to combine based on marker bit. */ /* one sample per packet, use adapter to combine based on marker bit. */
outbuf = gst_buffer_new_and_alloc (payload_len); outbuf = gst_buffer_new_and_alloc (payload_len);
memcpy (GST_BUFFER_DATA (outbuf), payload, payload_len); bdata = gst_buffer_map (outbuf, &bsize, NULL, GST_MAP_WRITE);
memcpy (bdata, payload, payload_len);
gst_buffer_unmap (outbuf, bdata, bsize);
gst_adapter_push (rtpxqtdepay->adapter, outbuf); gst_adapter_push (rtpxqtdepay->adapter, outbuf);
@ -617,48 +626,49 @@ gst_rtp_xqt_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
GST_DEBUG_OBJECT (rtpxqtdepay, GST_DEBUG_OBJECT (rtpxqtdepay,
"gst_rtp_xqt_depay_chain: pushing buffer of size %u", avail); "gst_rtp_xqt_depay_chain: pushing buffer of size %u", avail);
return outbuf; goto done;
} }
} }
} }
done: done:
return NULL; gst_rtp_buffer_unmap (&rtp);
return outbuf;
bad_packet: bad_packet:
{ {
GST_ELEMENT_WARNING (rtpxqtdepay, STREAM, DECODE, GST_ELEMENT_WARNING (rtpxqtdepay, STREAM, DECODE,
("Packet did not validate."), (NULL)); ("Packet did not validate."), (NULL));
return NULL; goto done;
} }
need_resync: need_resync:
{ {
GST_DEBUG_OBJECT (rtpxqtdepay, "waiting for marker"); GST_DEBUG_OBJECT (rtpxqtdepay, "waiting for marker");
return NULL; goto done;
} }
wrong_version: wrong_version:
{ {
GST_ELEMENT_WARNING (rtpxqtdepay, STREAM, DECODE, GST_ELEMENT_WARNING (rtpxqtdepay, STREAM, DECODE,
("Unknown payload version."), (NULL)); ("Unknown payload version."), (NULL));
return NULL; goto done;
} }
pck_reserved: pck_reserved:
{ {
GST_ELEMENT_WARNING (rtpxqtdepay, STREAM, DECODE, GST_ELEMENT_WARNING (rtpxqtdepay, STREAM, DECODE,
("PCK reserved 0."), (NULL)); ("PCK reserved 0."), (NULL));
return NULL; goto done;
} }
wrong_length: wrong_length:
{ {
GST_ELEMENT_WARNING (rtpxqtdepay, STREAM, DECODE, GST_ELEMENT_WARNING (rtpxqtdepay, STREAM, DECODE,
("Wrong payload length."), (NULL)); ("Wrong payload length."), (NULL));
return NULL; goto done;
} }
unknown_format: unknown_format:
{ {
GST_ELEMENT_WARNING (rtpxqtdepay, STREAM, DECODE, GST_ELEMENT_WARNING (rtpxqtdepay, STREAM, DECODE,
("Unknown payload format."), (NULL)); ("Unknown payload format."), (NULL));
return NULL; goto done;
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -100,7 +100,6 @@ struct _GstQTDemux {
/* configured playback region */ /* configured playback region */
GstSegment segment; GstSegment segment;
gboolean segment_running;
GstEvent *pending_newsegment; GstEvent *pending_newsegment;
/* gst index support */ /* gst index support */