mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
isomp4: port to 0.11
This commit is contained in:
parent
65bb271a95
commit
f886681367
10 changed files with 514 additions and 424 deletions
|
@ -6,6 +6,7 @@ libgstisomp4_la_LIBADD = \
|
|||
$(GST_PLUGINS_BASE_LIBS) \
|
||||
-lgstriff-@GST_MAJORMINOR@ \
|
||||
-lgstaudio-@GST_MAJORMINOR@ \
|
||||
-lgstvideo-@GST_MAJORMINOR@ \
|
||||
-lgstrtp-@GST_MAJORMINOR@ \
|
||||
-lgsttag-@GST_MAJORMINOR@ \
|
||||
-lgstpbutils-@GST_MAJORMINOR@ \
|
||||
|
|
|
@ -206,9 +206,10 @@ static AtomData *
|
|||
atom_data_new_from_gst_buffer (guint32 fourcc, const GstBuffer * buf)
|
||||
{
|
||||
AtomData *data = atom_data_new (fourcc);
|
||||
gsize size = gst_buffer_get_size ((GstBuffer *) buf);
|
||||
|
||||
atom_data_alloc_mem (data, GST_BUFFER_SIZE (buf));
|
||||
g_memmove (data->data, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
|
||||
atom_data_alloc_mem (data, size);
|
||||
gst_buffer_extract ((GstBuffer *) buf, 0, data->data, size);
|
||||
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
|
||||
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)
|
||||
return;
|
||||
|
||||
buf = gst_buffer_new ();
|
||||
GST_BUFFER_SIZE (buf) = len - 8;
|
||||
GST_BUFFER_DATA (buf) = data + 8;
|
||||
|
||||
buf = _gst_buffer_new_wrapped (data + 8, len - 8, NULL);
|
||||
data_atom = atom_data_new_from_gst_buffer (fourcc, buf);
|
||||
gst_buffer_unref (buf);
|
||||
|
||||
|
@ -2864,12 +2875,12 @@ atom_moov_add_3gp_tag (AtomMOOV * moov, guint32 fourcc, guint8 * data,
|
|||
guint8 *bdata;
|
||||
|
||||
/* need full atom */
|
||||
buf = gst_buffer_new_and_alloc (size + 4);
|
||||
bdata = GST_BUFFER_DATA (buf);
|
||||
bdata = g_malloc (size + 4);
|
||||
/* full atom: version and flags */
|
||||
GST_WRITE_UINT32_BE (bdata, 0);
|
||||
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);
|
||||
gst_buffer_unref (buf);
|
||||
|
||||
|
@ -3188,13 +3199,12 @@ build_pasp_extension (AtomTRAK * trak, gint par_width, gint par_height)
|
|||
GstBuffer *buf;
|
||||
guint8 *data;
|
||||
|
||||
buf = gst_buffer_new_and_alloc (8);
|
||||
data = GST_BUFFER_DATA (buf);
|
||||
|
||||
data = g_malloc (8);
|
||||
/* ihdr = image header box */
|
||||
GST_WRITE_UINT32_BE (data, par_width);
|
||||
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);
|
||||
gst_buffer_unref (buf);
|
||||
|
||||
|
@ -3942,13 +3952,13 @@ build_esds_extension (AtomTRAK * trak, guint8 object_type, guint8 stream_type,
|
|||
/* optional DecoderSpecificInfo */
|
||||
if (codec_data) {
|
||||
DecoderSpecificInfoDescriptor *desc;
|
||||
gsize size;
|
||||
|
||||
esds->es.dec_conf_desc.dec_specific_info = desc =
|
||||
desc_dec_specific_info_new ();
|
||||
desc_dec_specific_info_alloc_data (desc, GST_BUFFER_SIZE (codec_data));
|
||||
|
||||
memcpy (desc->data, GST_BUFFER_DATA (codec_data),
|
||||
GST_BUFFER_SIZE (codec_data));
|
||||
size = gst_buffer_get_size ((GstBuffer *) codec_data);
|
||||
desc_dec_specific_info_alloc_data (desc, size);
|
||||
gst_buffer_extract ((GstBuffer *) codec_data, 0, desc->data, size);
|
||||
}
|
||||
|
||||
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;
|
||||
GstBuffer *buf;
|
||||
guint8 *data;
|
||||
|
||||
if (buffer_size_db == 0 && avg_bitrate == 0 && max_bitrate == 0)
|
||||
return 0;
|
||||
|
||||
buf = gst_buffer_new_and_alloc (12);
|
||||
|
||||
GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf), buffer_size_db);
|
||||
GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + 4, max_bitrate);
|
||||
GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + 8, avg_bitrate);
|
||||
data = g_malloc (12);
|
||||
GST_WRITE_UINT32_BE (data, buffer_size_db);
|
||||
GST_WRITE_UINT32_BE (data + 4, max_bitrate);
|
||||
GST_WRITE_UINT32_BE (data + 8, avg_bitrate);
|
||||
|
||||
buf = _gst_buffer_new_wrapped (data, 12, g_free);
|
||||
atom_data =
|
||||
atom_data_new_from_gst_buffer (GST_MAKE_FOURCC ('b', 't', 'r', 't'), buf);
|
||||
gst_buffer_unref (buf);
|
||||
|
@ -4022,6 +4033,7 @@ build_mov_aac_extension (AtomTRAK * trak, const GstBuffer * codec_data,
|
|||
{
|
||||
AtomInfo *esds, *mp4a;
|
||||
GstBuffer *buf;
|
||||
guint32 tmp = 0;
|
||||
|
||||
/* Add ESDS atom to WAVE */
|
||||
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:
|
||||
* not really in spec, but makes offset based players happy */
|
||||
buf = gst_buffer_new_and_alloc (4);
|
||||
*((guint32 *) GST_BUFFER_DATA (buf)) = 0;
|
||||
buf = _gst_buffer_new_wrapped (&tmp, 4, NULL);
|
||||
mp4a = build_codec_data_extension (FOURCC_mp4a, buf);
|
||||
gst_buffer_unref (buf);
|
||||
|
||||
|
@ -4052,14 +4063,13 @@ build_fiel_extension (gint fields)
|
|||
{
|
||||
AtomData *atom_data;
|
||||
GstBuffer *buf;
|
||||
guint8 f = fields;
|
||||
|
||||
if (fields == 1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf = gst_buffer_new_and_alloc (1);
|
||||
GST_BUFFER_DATA (buf)[0] = (guint8) fields;
|
||||
|
||||
buf = _gst_buffer_new_wrapped (&f, 1, NULL);
|
||||
atom_data =
|
||||
atom_data_new_from_gst_buffer (GST_MAKE_FOURCC ('f', 'i', 'e', 'l'), 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;
|
||||
}
|
||||
|
||||
buf = gst_buffer_new_and_alloc (idhr_size + colr_size + cmap_size +
|
||||
cdef_size);
|
||||
gst_byte_writer_init_with_buffer (&writer, buf, FALSE);
|
||||
gst_byte_writer_init_with_size (&writer,
|
||||
idhr_size + colr_size + cmap_size + cdef_size, TRUE);
|
||||
|
||||
/* ihdr = image header box */
|
||||
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);
|
||||
buf = gst_byte_writer_reset_and_get_buffer (&writer);
|
||||
|
||||
atom_data = atom_data_new_from_gst_buffer (FOURCC_jp2h, buf);
|
||||
gst_buffer_unref (buf);
|
||||
|
@ -4245,10 +4255,6 @@ build_amr_extension (void)
|
|||
GstBuffer *buf;
|
||||
AtomInfo *res;
|
||||
|
||||
buf = gst_buffer_new ();
|
||||
GST_BUFFER_DATA (buf) = ext;
|
||||
GST_BUFFER_SIZE (buf) = sizeof (ext);
|
||||
|
||||
/* vendor */
|
||||
GST_WRITE_UINT32_LE (ext, 0);
|
||||
/* decoder version */
|
||||
|
@ -4260,6 +4266,7 @@ build_amr_extension (void)
|
|||
/* frames per sample */
|
||||
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);
|
||||
gst_buffer_unref (buf);
|
||||
return res;
|
||||
|
@ -4272,10 +4279,6 @@ build_h263_extension (void)
|
|||
GstBuffer *buf;
|
||||
AtomInfo *res;
|
||||
|
||||
buf = gst_buffer_new ();
|
||||
GST_BUFFER_DATA (buf) = ext;
|
||||
GST_BUFFER_SIZE (buf) = sizeof (ext);
|
||||
|
||||
/* vendor */
|
||||
GST_WRITE_UINT32_LE (ext, 0);
|
||||
/* decoder version */
|
||||
|
@ -4285,6 +4288,7 @@ build_h263_extension (void)
|
|||
GST_WRITE_UINT8 (ext + 5, 10);
|
||||
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);
|
||||
gst_buffer_unref (buf);
|
||||
return res;
|
||||
|
@ -4300,8 +4304,8 @@ build_gama_atom (gdouble gamma)
|
|||
/* convert to uint32 from fixed point */
|
||||
gamma_fp = (guint32) 65536 *gamma;
|
||||
|
||||
buf = gst_buffer_new_and_alloc (4);
|
||||
GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf), gamma_fp);
|
||||
gamma_fp = GUINT32_TO_BE (gamma_fp);
|
||||
buf = _gst_buffer_new_wrapped (&gamma_fp, 4, NULL);
|
||||
res = build_codec_data_extension (FOURCC_gama, buf);
|
||||
gst_buffer_unref (buf);
|
||||
return res;
|
||||
|
@ -4312,14 +4316,17 @@ build_SMI_atom (const GstBuffer * seqh)
|
|||
{
|
||||
AtomInfo *res;
|
||||
GstBuffer *buf;
|
||||
gsize size;
|
||||
guint8 *data;
|
||||
|
||||
/* 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_BE (GST_BUFFER_DATA (buf) + 4, GST_BUFFER_SIZE (seqh));
|
||||
memcpy (GST_BUFFER_DATA (buf) + 8, GST_BUFFER_DATA (seqh),
|
||||
GST_BUFFER_SIZE (seqh));
|
||||
GST_WRITE_UINT32_LE (data, FOURCC_SEQH);
|
||||
GST_WRITE_UINT32_BE (data + 4, size + 8);
|
||||
gst_buffer_extract ((GstBuffer *) seqh, 0, data + 8, size);
|
||||
buf = _gst_buffer_new_wrapped (data, size + 8, g_free);
|
||||
res = build_codec_data_extension (FOURCC_SMI_, buf);
|
||||
gst_buffer_unref (buf);
|
||||
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. */
|
||||
fourcc = MS_WAVE_FOURCC (0x11);
|
||||
|
||||
buf = gst_buffer_new_and_alloc (ima_adpcm_atom_size);
|
||||
data = GST_BUFFER_DATA (buf);
|
||||
data = g_malloc (ima_adpcm_atom_size);
|
||||
|
||||
/* 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. */
|
||||
|
@ -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 + 18, samplesperblock);
|
||||
|
||||
buf = _gst_buffer_new_wrapped (data, ima_adpcm_atom_size, g_free);
|
||||
atom_data = atom_data_new_from_gst_buffer (fourcc, buf);
|
||||
gst_buffer_unref (buf);
|
||||
|
||||
|
@ -4402,6 +4409,7 @@ AtomInfo *
|
|||
build_uuid_xmp_atom (GstBuffer * xmp_data)
|
||||
{
|
||||
AtomUUID *uuid;
|
||||
gsize size;
|
||||
static guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
|
||||
0x97, 0xA9, 0x42, 0xE8,
|
||||
0x9C, 0x71, 0x99, 0x94,
|
||||
|
@ -4414,9 +4422,10 @@ build_uuid_xmp_atom (GstBuffer * xmp_data)
|
|||
uuid = atom_uuid_new ();
|
||||
memcpy (uuid->uuid, xmp_uuid, 16);
|
||||
|
||||
uuid->data = g_malloc (GST_BUFFER_SIZE (xmp_data));
|
||||
uuid->datalen = GST_BUFFER_SIZE (xmp_data);
|
||||
memcpy (uuid->data, GST_BUFFER_DATA (xmp_data), GST_BUFFER_SIZE (xmp_data));
|
||||
size = gst_buffer_get_size (xmp_data);
|
||||
uuid->data = g_malloc (size);
|
||||
uuid->datalen = size;
|
||||
gst_buffer_extract (xmp_data, 0, uuid->data, size);
|
||||
|
||||
return build_atom_info_wrapper ((Atom *) uuid, atom_uuid_copy_data,
|
||||
atom_uuid_free);
|
||||
|
|
|
@ -108,10 +108,15 @@ atoms_recov_write_ftyp_info (FILE * f, AtomFTYP * ftyp, GstBuffer * prefix)
|
|||
guint64 size = 0;
|
||||
|
||||
if (prefix) {
|
||||
if (fwrite (GST_BUFFER_DATA (prefix), 1, GST_BUFFER_SIZE (prefix), f) !=
|
||||
GST_BUFFER_SIZE (prefix)) {
|
||||
guint8 *bdata;
|
||||
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;
|
||||
}
|
||||
gst_buffer_unmap (prefix, bdata, bsize);
|
||||
}
|
||||
if (!atom_ftyp_copy_data (ftyp, &data, &size, &offset)) {
|
||||
return FALSE;
|
||||
|
|
|
@ -89,8 +89,8 @@ enum
|
|||
PROP_FAST_START_MODE
|
||||
};
|
||||
|
||||
GST_BOILERPLATE (GstQTMoovRecover, gst_qt_moov_recover, GstPipeline,
|
||||
GST_TYPE_PIPELINE);
|
||||
#define gst_qt_moov_recover_parent_class parent_class
|
||||
G_DEFINE_TYPE (GstQTMoovRecover, gst_qt_moov_recover, GST_TYPE_PIPELINE);
|
||||
|
||||
/* property functions */
|
||||
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_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
|
||||
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,
|
||||
"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
|
||||
gst_qt_moov_recover_init (GstQTMoovRecover * qtmr,
|
||||
GstQTMoovRecoverClass * qtmr_klass)
|
||||
gst_qt_moov_recover_init (GstQTMoovRecover * qtmr)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -117,6 +117,7 @@
|
|||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/base/gstcollectpads.h>
|
||||
#include <gst/video/video.h>
|
||||
#include <gst/tag/xmpwriter.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
@ -220,7 +221,7 @@ static void gst_qt_mux_get_property (GObject * object,
|
|||
|
||||
/* pad functions */
|
||||
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);
|
||||
|
||||
/* event */
|
||||
|
@ -515,20 +516,23 @@ gst_qt_mux_prepare_jpc_buffer (GstQTPad * qtpad, GstBuffer * buf,
|
|||
GstQTMux * qtmux)
|
||||
{
|
||||
GstBuffer *newbuf;
|
||||
guint8 *data;
|
||||
gsize size;
|
||||
|
||||
GST_LOG_OBJECT (qtmux, "Preparing jpc buffer");
|
||||
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
newbuf = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (buf) + 8);
|
||||
gst_buffer_copy_metadata (newbuf, buf, GST_BUFFER_COPY_ALL);
|
||||
size = gst_buffer_get_size (buf);
|
||||
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));
|
||||
GST_WRITE_UINT32_LE (GST_BUFFER_DATA (newbuf) + 4, FOURCC_jp2c);
|
||||
data = gst_buffer_map (newbuf, &size, NULL, GST_MAP_WRITE);
|
||||
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_SIZE (buf));
|
||||
gst_buffer_unmap (buf, data, size);
|
||||
gst_buffer_unref (buf);
|
||||
|
||||
return newbuf;
|
||||
|
@ -635,6 +639,8 @@ gst_qt_mux_add_mp4_cover (GstQTMux * qtmux, const GstTagList * list,
|
|||
GstCaps *caps;
|
||||
GstStructure *structure;
|
||||
gint flags = 0;
|
||||
guint8 *data;
|
||||
gsize size;
|
||||
|
||||
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)
|
||||
goto done;
|
||||
|
||||
caps = gst_buffer_get_caps (buf);
|
||||
/* FIXME-0.11 caps metadata ? */
|
||||
/* caps = gst_buffer_get_caps (buf); */
|
||||
caps = NULL;
|
||||
if (!caps) {
|
||||
GST_WARNING_OBJECT (qtmux, "preview image without caps");
|
||||
goto done;
|
||||
|
@ -665,10 +673,11 @@ gst_qt_mux_add_mp4_cover (GstQTMux * qtmux, const GstTagList * list,
|
|||
goto done;
|
||||
}
|
||||
|
||||
data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
|
||||
GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT
|
||||
" -> image size %d", GST_FOURCC_ARGS (fourcc), GST_BUFFER_SIZE (buf));
|
||||
atom_moov_add_tag (qtmux->moov, fourcc, flags, GST_BUFFER_DATA (buf),
|
||||
GST_BUFFER_SIZE (buf));
|
||||
" -> image size %d", GST_FOURCC_ARGS (fourcc), size);
|
||||
atom_moov_add_tag (qtmux->moov, fourcc, flags, data, size);
|
||||
gst_buffer_unmap (buf, data, size);
|
||||
done:
|
||||
g_value_unset (&value);
|
||||
}
|
||||
|
@ -1095,14 +1104,18 @@ gst_qt_mux_add_metadata_tags (GstQTMux * qtmux, const GstTagList * list)
|
|||
GstCaps *caps = NULL;
|
||||
|
||||
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;
|
||||
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_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);
|
||||
if (s && (style = gst_structure_get_string (s, "style"))) {
|
||||
/* 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 &&
|
||||
qtmux_klass->format == GST_QT_MUX_FORMAT_3GP)) {
|
||||
GST_DEBUG_OBJECT (qtmux, "Adding private tag");
|
||||
atom_moov_add_blob_tag (qtmux->moov, GST_BUFFER_DATA (buf),
|
||||
GST_BUFFER_SIZE (buf));
|
||||
atom_moov_add_blob_tag (qtmux->moov, data, size);
|
||||
}
|
||||
}
|
||||
gst_buffer_unmap (buf, data, size);
|
||||
gst_caps_unref (caps);
|
||||
}
|
||||
}
|
||||
|
@ -1162,8 +1175,8 @@ _gst_buffer_new_take_data (guint8 * data, guint size)
|
|||
GstBuffer *buf;
|
||||
|
||||
buf = gst_buffer_new ();
|
||||
GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data;
|
||||
GST_BUFFER_SIZE (buf) = size;
|
||||
gst_buffer_take_memory (buf, -1,
|
||||
gst_memory_new_wrapped (0, data, g_free, size, 0, size));
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
@ -1173,21 +1186,21 @@ gst_qt_mux_send_buffer (GstQTMux * qtmux, GstBuffer * buf, guint64 * offset,
|
|||
gboolean mind_fast)
|
||||
{
|
||||
GstFlowReturn res;
|
||||
guint8 *data;
|
||||
guint size;
|
||||
gsize size;
|
||||
|
||||
g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
|
||||
|
||||
data = GST_BUFFER_DATA (buf);
|
||||
size = GST_BUFFER_SIZE (buf);
|
||||
|
||||
size = gst_buffer_get_size (buf);
|
||||
GST_LOG_OBJECT (qtmux, "sending buffer size %d", size);
|
||||
|
||||
if (mind_fast && qtmux->fast_start_file) {
|
||||
gint ret;
|
||||
guint8 *data;
|
||||
|
||||
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);
|
||||
gst_buffer_unmap (buf, data, size);
|
||||
gst_buffer_unref (buf);
|
||||
if (ret != size)
|
||||
goto write_error;
|
||||
|
@ -1195,9 +1208,6 @@ gst_qt_mux_send_buffer (GstQTMux * qtmux, GstBuffer * buf, guint64 * offset,
|
|||
res = GST_FLOW_OK;
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1248,16 +1258,19 @@ gst_qt_mux_send_buffered_data (GstQTMux * qtmux, guint64 * offset)
|
|||
* (somehow optimize copy?) */
|
||||
GST_DEBUG_OBJECT (qtmux, "Sending buffered data");
|
||||
while (ret == GST_FLOW_OK) {
|
||||
gint r;
|
||||
const int bufsize = 4096;
|
||||
guint8 *data;
|
||||
gsize size;
|
||||
|
||||
buf = gst_buffer_new_and_alloc (bufsize);
|
||||
r = fread (GST_BUFFER_DATA (buf), sizeof (guint8), bufsize,
|
||||
qtmux->fast_start_file);
|
||||
if (r == 0)
|
||||
gst_buffer_map (buf, &size, NULL, GST_MAP_WRITE);
|
||||
size = fread (data, sizeof (guint8), bufsize, qtmux->fast_start_file);
|
||||
if (size == 0) {
|
||||
gst_buffer_unmap (buf, data, -1);
|
||||
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);
|
||||
buf = NULL;
|
||||
}
|
||||
|
@ -1354,9 +1367,11 @@ static GstFlowReturn
|
|||
gst_qt_mux_update_mdat_size (GstQTMux * qtmux, guint64 mdat_pos,
|
||||
guint64 mdat_size, guint64 * offset)
|
||||
{
|
||||
GstEvent *event;
|
||||
GstBuffer *buf;
|
||||
gboolean large_file;
|
||||
GstSegment segment;
|
||||
guint8 *data;
|
||||
gsize size;
|
||||
|
||||
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;
|
||||
|
||||
/* seek and rewrite the header */
|
||||
event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
|
||||
mdat_pos, GST_CLOCK_TIME_NONE, 0);
|
||||
gst_pad_push_event (qtmux->srcpad, event);
|
||||
gst_segment_init (&segment, GST_FORMAT_BYTES);
|
||||
segment.start = mdat_pos;
|
||||
gst_pad_push_event (qtmux->srcpad, gst_event_new_segment (&segment));
|
||||
|
||||
if (large_file) {
|
||||
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 {
|
||||
guint8 *data;
|
||||
|
||||
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_LE (data + 4, FOURCC_free);
|
||||
GST_WRITE_UINT32_BE (data + 8, mdat_size + 8);
|
||||
GST_WRITE_UINT32_LE (data + 12, FOURCC_mdat);
|
||||
}
|
||||
gst_buffer_unmap (buf, data, size);
|
||||
|
||||
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;
|
||||
GValue array = { 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);
|
||||
|
||||
g_value_init (&array, GST_TYPE_ARRAY);
|
||||
|
@ -1589,6 +1607,7 @@ gst_qt_mux_start_file (GstQTMux * qtmux)
|
|||
{
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
GstCaps *caps;
|
||||
GstSegment segment;
|
||||
|
||||
GST_DEBUG_OBJECT (qtmux, "starting file");
|
||||
|
||||
|
@ -1600,8 +1619,8 @@ gst_qt_mux_start_file (GstQTMux * qtmux)
|
|||
gst_caps_unref (caps);
|
||||
|
||||
/* let downstream know we think in BYTES and expect to do seeking later on */
|
||||
gst_pad_push_event (qtmux->srcpad,
|
||||
gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0));
|
||||
gst_segment_init (&segment, GST_FORMAT_BYTES);
|
||||
gst_pad_push_event (qtmux->srcpad, gst_event_new_segment (&segment));
|
||||
|
||||
/* initialize our moov recovery file */
|
||||
GST_OBJECT_LOCK (qtmux);
|
||||
|
@ -1760,7 +1779,7 @@ gst_qt_mux_stop_file (GstQTMux * qtmux)
|
|||
}
|
||||
|
||||
if (qtmux->fragment_sequence) {
|
||||
GstEvent *event;
|
||||
GstSegment segment;
|
||||
|
||||
if (qtmux->mfra) {
|
||||
guint8 *data = NULL;
|
||||
|
@ -1780,7 +1799,6 @@ gst_qt_mux_stop_file (GstQTMux * qtmux)
|
|||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
|
||||
timescale = qtmux->timescale;
|
||||
/* only mvex duration is updated,
|
||||
* 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_TIME_FORMAT, GST_TIME_ARGS (first_ts));
|
||||
/* seek and rewrite the header */
|
||||
event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
|
||||
qtmux->mdat_pos, GST_CLOCK_TIME_NONE, 0);
|
||||
gst_pad_push_event (qtmux->srcpad, event);
|
||||
gst_segment_init (&segment, GST_FORMAT_BYTES);
|
||||
segment.start = qtmux->mdat_pos;
|
||||
gst_pad_push_event (qtmux->srcpad, gst_event_new_segment (&segment));
|
||||
/* no need to seek back */
|
||||
return gst_qt_mux_send_moov (qtmux, NULL, FALSE);
|
||||
}
|
||||
|
@ -1948,14 +1966,15 @@ flush:
|
|||
pad->traf = NULL;
|
||||
atom_moof_copy_data (moof, &data, &size, &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);
|
||||
|
||||
/* and actual data */
|
||||
total_size = 0;
|
||||
for (i = 0; i < atom_array_get_len (&pad->fragment_buffers); i++) {
|
||||
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",
|
||||
|
@ -2046,7 +2065,7 @@ gst_qt_mux_get_asc_buffer_ts (GstQTMux * qtmux, GstQTPad * pad, GstBuffer * buf)
|
|||
buf = pad->buf_entries[pad->buf_head];
|
||||
pad->buf_entries[pad->buf_head++] = NULL;
|
||||
pad->buf_head %= wrap;
|
||||
buf = gst_buffer_make_metadata_writable (buf);
|
||||
buf = gst_buffer_make_writable (buf);
|
||||
/* track original ts (= pts ?) for later */
|
||||
GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_TIMESTAMP (buf);
|
||||
GST_BUFFER_TIMESTAMP (buf) = ts;
|
||||
|
@ -2224,7 +2243,7 @@ again:
|
|||
buffer (= chunk)), but can also be fixed-packet-size codecs like ADPCM
|
||||
*/
|
||||
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;
|
||||
/* note: qt raw audio storage warps it implicitly into a timewise
|
||||
* perfect stream, discarding buffer times */
|
||||
|
@ -2232,7 +2251,7 @@ again:
|
|||
nsamples = gst_util_uint64_scale_round (GST_BUFFER_DURATION (last_buf),
|
||||
atom_trak_get_timescale (pad->trak), GST_SECOND);
|
||||
} 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;
|
||||
|
||||
|
@ -2241,7 +2260,7 @@ again:
|
|||
pad->last_dts += duration * nsamples;
|
||||
} else {
|
||||
nsamples = 1;
|
||||
sample_size = GST_BUFFER_SIZE (last_buf);
|
||||
sample_size = gst_buffer_get_size (last_buf);
|
||||
if (pad->have_dts) {
|
||||
gint64 scaled_dts;
|
||||
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_PAD_NAME (best_pad->collect.pad), GST_TIME_ARGS (best_time));
|
||||
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;
|
||||
ret = gst_qt_mux_add_buffer (qtmux, best_pad, buf);
|
||||
} else {
|
||||
|
@ -2528,7 +2547,6 @@ gst_qt_mux_audio_sink_set_caps (GstPad * pad, GstCaps * caps)
|
|||
AtomInfo *ext_atom = NULL;
|
||||
gint constant_size = 0;
|
||||
const gchar *stream_format;
|
||||
GstCaps *current_caps = NULL;
|
||||
|
||||
/* find stream data */
|
||||
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
|
||||
* added more info to the caps, as both should be 'fixed' caps) */
|
||||
if (qtpad->fourcc) {
|
||||
g_object_get (pad, "caps", ¤t_caps, NULL);
|
||||
GstCaps *current_caps;
|
||||
|
||||
current_caps = gst_pad_get_current_caps (pad);
|
||||
g_assert (caps != NULL);
|
||||
|
||||
if (!gst_qtmux_caps_is_subset_full (qtmux, current_caps, caps)) {
|
||||
gst_caps_unref (current_caps);
|
||||
goto refuse_renegotiation;
|
||||
}
|
||||
GST_DEBUG_OBJECT (qtmux,
|
||||
"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,
|
||||
|
@ -2625,11 +2647,12 @@ gst_qt_mux_audio_sink_set_caps (GstPad * pad, GstCaps * caps)
|
|||
"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");
|
||||
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 */
|
||||
profile >>= 3;
|
||||
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) {
|
||||
GstBuffer *codec_config;
|
||||
gint len;
|
||||
guint8 *data;
|
||||
gsize size;
|
||||
|
||||
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 */
|
||||
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_buffer_unmap ((GstBuffer *) codec_data, data, size);
|
||||
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;
|
||||
codec_config = gst_buffer_create_sub ((GstBuffer *) codec_data, 8, len);
|
||||
codec_config =
|
||||
gst_buffer_copy_region ((GstBuffer *) codec_data, 0, 8, len);
|
||||
} else {
|
||||
codec_config = gst_buffer_ref ((GstBuffer *) codec_data);
|
||||
}
|
||||
gst_buffer_unmap ((GstBuffer *) codec_data, data, size);
|
||||
if (len != 28) {
|
||||
/* does not look good, but perhaps some trailing unneeded stuff */
|
||||
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
|
||||
ext_atom = build_codec_data_extension (FOURCC_alac, codec_config);
|
||||
/* set some more info */
|
||||
data = gst_buffer_map (codec_config, &size, NULL, GST_MAP_READ);
|
||||
entry.bytes_per_sample = 2;
|
||||
entry.samples_per_packet =
|
||||
GST_READ_UINT32_BE (GST_BUFFER_DATA (codec_config) + 4);
|
||||
entry.samples_per_packet = GST_READ_UINT32_BE (data + 4);
|
||||
gst_buffer_unmap (codec_config, data, size);
|
||||
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;
|
||||
gboolean sync = FALSE;
|
||||
int par_num, par_den;
|
||||
GstCaps *current_caps = NULL;
|
||||
|
||||
/* find stream data */
|
||||
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
|
||||
* added more info to the caps, as both should be 'fixed' caps) */
|
||||
if (qtpad->fourcc) {
|
||||
g_object_get (pad, "caps", ¤t_caps, NULL);
|
||||
GstCaps *current_caps;
|
||||
|
||||
current_caps = gst_pad_get_current_caps (pad);
|
||||
g_assert (caps != NULL);
|
||||
|
||||
if (!gst_qtmux_caps_is_subset_full (qtmux, current_caps, caps)) {
|
||||
gst_caps_unref (current_caps);
|
||||
goto refuse_renegotiation;
|
||||
}
|
||||
GST_DEBUG_OBJECT (qtmux,
|
||||
"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,
|
||||
|
@ -2925,24 +2958,27 @@ gst_qt_mux_video_sink_set_caps (GstPad * pad, GstCaps * caps)
|
|||
sync = TRUE;
|
||||
|
||||
/* now map onto a fourcc, and some extra properties */
|
||||
if (strcmp (mimetype, "video/x-raw-rgb") == 0) {
|
||||
gint bpp;
|
||||
if (strcmp (mimetype, "video/x-raw") == 0) {
|
||||
const gchar *format;
|
||||
GstVideoFormat fmt;
|
||||
|
||||
entry.fourcc = FOURCC_raw_;
|
||||
gst_structure_get_int (structure, "bpp", &bpp);
|
||||
entry.depth = bpp;
|
||||
sync = FALSE;
|
||||
} else if (strcmp (mimetype, "video/x-raw-yuv") == 0) {
|
||||
guint32 format = 0;
|
||||
format = gst_structure_get_string (structure, "format");
|
||||
fmt = gst_video_format_from_string (format);
|
||||
|
||||
sync = FALSE;
|
||||
gst_structure_get_fourcc (structure, "format", &format);
|
||||
switch (format) {
|
||||
case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
|
||||
switch (fmt) {
|
||||
case GST_VIDEO_FORMAT_UYVY:
|
||||
if (depth == -1)
|
||||
depth = 24;
|
||||
entry.fourcc = FOURCC_2vuy;
|
||||
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;
|
||||
}
|
||||
} else if (strcmp (mimetype, "video/x-h263") == 0) {
|
||||
|
@ -3155,8 +3191,8 @@ refuse_caps:
|
|||
refuse_renegotiation:
|
||||
{
|
||||
GST_WARNING_OBJECT (qtmux,
|
||||
"pad %s refused renegotiation to %" GST_PTR_FORMAT " from %"
|
||||
GST_PTR_FORMAT, GST_PAD_NAME (pad), caps, GST_PAD_CAPS (pad));
|
||||
"pad %s refused renegotiation to %" GST_PTR_FORMAT, GST_PAD_NAME (pad),
|
||||
caps);
|
||||
gst_object_unref (qtmux);
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -3170,7 +3206,23 @@ gst_qt_mux_sink_event (GstPad * pad, GstEvent * event)
|
|||
guint32 avg_bitrate = 0, max_bitrate = 0;
|
||||
|
||||
qtmux = GST_QT_MUX_CAST (gst_pad_get_parent (pad));
|
||||
|
||||
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:{
|
||||
GstTagList *list;
|
||||
GstTagSetter *setter = GST_TAG_SETTER (qtmux);
|
||||
|
@ -3232,7 +3284,7 @@ gst_qt_mux_release_pad (GstElement * element, GstPad * pad)
|
|||
|
||||
static GstPad *
|
||||
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);
|
||||
GstQTMux *qtmux = GST_QT_MUX_CAST (element);
|
||||
|
@ -3273,11 +3325,9 @@ gst_qt_mux_request_new_pad (GstElement * element,
|
|||
|
||||
/* set up pad functions */
|
||||
if (audio)
|
||||
gst_pad_set_setcaps_function (newpad,
|
||||
GST_DEBUG_FUNCPTR (gst_qt_mux_audio_sink_set_caps));
|
||||
collect_pad->set_caps = GST_DEBUG_FUNCPTR (gst_qt_mux_audio_sink_set_caps);
|
||||
else
|
||||
gst_pad_set_setcaps_function (newpad,
|
||||
GST_DEBUG_FUNCPTR (gst_qt_mux_video_sink_set_caps));
|
||||
collect_pad->set_caps = GST_DEBUG_FUNCPTR (gst_qt_mux_video_sink_set_caps);
|
||||
|
||||
/* FIXME: hacked way to override/extend the event function of
|
||||
* GstCollectPads; because it sets its own event function giving the
|
||||
|
|
|
@ -125,6 +125,7 @@ struct _GstQTPad
|
|||
|
||||
/* if nothing is set, it won't be called */
|
||||
GstQTPadPrepareBufferFunc prepare_buf_func;
|
||||
gboolean (*set_caps) (GstPad * pad, GstCaps * caps);
|
||||
};
|
||||
|
||||
typedef enum _GstQTMuxState
|
||||
|
|
|
@ -153,10 +153,8 @@ GstQTMuxFormatProp gst_qt_mux_format_list[] = {
|
|||
"GstQTMux",
|
||||
GST_STATIC_CAPS ("video/quicktime, variant = (string) apple; "
|
||||
"video/quicktime"),
|
||||
GST_STATIC_CAPS ("video/x-raw-rgb, "
|
||||
COMMON_VIDEO_CAPS "; "
|
||||
"video/x-raw-yuv, "
|
||||
"format = (fourcc) UYVY, "
|
||||
GST_STATIC_CAPS ("video/x-raw, "
|
||||
"format = (string) { RGB, UYVY }, "
|
||||
COMMON_VIDEO_CAPS "; "
|
||||
MPEG4V_CAPS "; "
|
||||
H263_CAPS "; "
|
||||
|
@ -361,12 +359,18 @@ gst_qt_mux_map_format_to_header (GstQTMuxFormat format, GstBuffer ** _prefix,
|
|||
break;
|
||||
}
|
||||
case GST_QT_MUX_FORMAT_MJ2:
|
||||
{
|
||||
guint8 *bdata;
|
||||
|
||||
major = FOURCC_mjp2;
|
||||
comp = mjp2_brands;
|
||||
version = 0;
|
||||
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;
|
||||
}
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
|
|
|
@ -91,8 +91,8 @@ GST_STATIC_PAD_TEMPLATE ("sink",
|
|||
"encoding-name = (string) { \"X-QT\", \"X-QUICKTIME\" }")
|
||||
);
|
||||
|
||||
GST_BOILERPLATE (GstRtpXQTDepay, gst_rtp_xqt_depay, GstBaseRTPDepayload,
|
||||
GST_TYPE_BASE_RTP_DEPAYLOAD);
|
||||
#define gst_rtp_xqt_depay_parent_class parent_class
|
||||
G_DEFINE_TYPE (GstRtpXQTDepay, gst_rtp_xqt_depay, GST_TYPE_BASE_RTP_DEPAYLOAD);
|
||||
|
||||
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 *
|
||||
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
|
||||
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,
|
||||
"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
|
||||
gst_rtp_xqt_depay_init (GstRtpXQTDepay * rtpxqtdepay,
|
||||
GstRtpXQTDepayClass * klass)
|
||||
gst_rtp_xqt_depay_init (GstRtpXQTDepay * rtpxqtdepay)
|
||||
{
|
||||
rtpxqtdepay->adapter = gst_adapter_new ();
|
||||
}
|
||||
|
@ -201,6 +195,7 @@ gst_rtp_quicktime_parse_sd (GstRtpXQTDepay * rtpxqtdepay, guint8 * data,
|
|||
GstBuffer *buf;
|
||||
gint size;
|
||||
GstCaps *caps;
|
||||
guint8 *bdata;
|
||||
|
||||
GST_DEBUG_OBJECT (rtpxqtdepay, "found avcC codec_data in sd, %u",
|
||||
chlen);
|
||||
|
@ -212,7 +207,9 @@ gst_rtp_quicktime_parse_sd (GstRtpXQTDepay * rtpxqtdepay, guint8 * data,
|
|||
size = len - 8;
|
||||
|
||||
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",
|
||||
"codec_data", GST_TYPE_BUFFER, buf, NULL);
|
||||
gst_buffer_unref (buf);
|
||||
|
@ -255,11 +252,14 @@ static GstBuffer *
|
|||
gst_rtp_xqt_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
||||
{
|
||||
GstRtpXQTDepay *rtpxqtdepay;
|
||||
GstBuffer *outbuf;
|
||||
GstBuffer *outbuf = NULL;
|
||||
gboolean m;
|
||||
GstRTPBuffer rtp;
|
||||
|
||||
rtpxqtdepay = GST_RTP_XQT_DEPAY (depayload);
|
||||
|
||||
gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);
|
||||
|
||||
if (!gst_rtp_buffer_validate (buf))
|
||||
goto bad_packet;
|
||||
|
||||
|
@ -270,7 +270,7 @@ gst_rtp_xqt_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
|||
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);
|
||||
|
||||
{
|
||||
|
@ -279,9 +279,11 @@ gst_rtp_xqt_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
|||
guint8 *payload;
|
||||
guint8 ver, pck;
|
||||
gboolean s, q, l, d;
|
||||
guint8 *bdata;
|
||||
gsize bsize;
|
||||
|
||||
payload_len = gst_rtp_buffer_get_payload_len (buf);
|
||||
payload = gst_rtp_buffer_get_payload (buf);
|
||||
payload_len = gst_rtp_buffer_get_payload_len (&rtp);
|
||||
payload = gst_rtp_buffer_get_payload (&rtp);
|
||||
|
||||
/* 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
|
||||
|
@ -545,8 +547,11 @@ gst_rtp_xqt_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
|||
{
|
||||
/* multiple samples per packet. */
|
||||
outbuf = gst_buffer_new_and_alloc (payload_len);
|
||||
memcpy (GST_BUFFER_DATA (outbuf), payload, payload_len);
|
||||
return outbuf;
|
||||
bdata = gst_buffer_map (outbuf, &bsize, NULL, GST_MAP_WRITE);
|
||||
memcpy (bdata, payload, payload_len);
|
||||
gst_buffer_unmap (outbuf, bdata, bsize);
|
||||
|
||||
goto done;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
|
@ -586,7 +591,9 @@ gst_rtp_xqt_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
|||
slen = payload_len;
|
||||
|
||||
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)
|
||||
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. */
|
||||
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);
|
||||
|
||||
|
@ -617,48 +626,49 @@ gst_rtp_xqt_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
|||
GST_DEBUG_OBJECT (rtpxqtdepay,
|
||||
"gst_rtp_xqt_depay_chain: pushing buffer of size %u", avail);
|
||||
|
||||
return outbuf;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
return NULL;
|
||||
gst_rtp_buffer_unmap (&rtp);
|
||||
return outbuf;
|
||||
|
||||
bad_packet:
|
||||
{
|
||||
GST_ELEMENT_WARNING (rtpxqtdepay, STREAM, DECODE,
|
||||
("Packet did not validate."), (NULL));
|
||||
return NULL;
|
||||
goto done;
|
||||
}
|
||||
need_resync:
|
||||
{
|
||||
GST_DEBUG_OBJECT (rtpxqtdepay, "waiting for marker");
|
||||
return NULL;
|
||||
goto done;
|
||||
}
|
||||
wrong_version:
|
||||
{
|
||||
GST_ELEMENT_WARNING (rtpxqtdepay, STREAM, DECODE,
|
||||
("Unknown payload version."), (NULL));
|
||||
return NULL;
|
||||
goto done;
|
||||
}
|
||||
pck_reserved:
|
||||
{
|
||||
GST_ELEMENT_WARNING (rtpxqtdepay, STREAM, DECODE,
|
||||
("PCK reserved 0."), (NULL));
|
||||
return NULL;
|
||||
goto done;
|
||||
}
|
||||
wrong_length:
|
||||
{
|
||||
GST_ELEMENT_WARNING (rtpxqtdepay, STREAM, DECODE,
|
||||
("Wrong payload length."), (NULL));
|
||||
return NULL;
|
||||
goto done;
|
||||
}
|
||||
unknown_format:
|
||||
{
|
||||
GST_ELEMENT_WARNING (rtpxqtdepay, STREAM, DECODE,
|
||||
("Unknown payload format."), (NULL));
|
||||
return NULL;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -100,7 +100,6 @@ struct _GstQTDemux {
|
|||
|
||||
/* configured playback region */
|
||||
GstSegment segment;
|
||||
gboolean segment_running;
|
||||
GstEvent *pending_newsegment;
|
||||
|
||||
/* gst index support */
|
||||
|
|
Loading…
Reference in a new issue