mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +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) \
|
$(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@ \
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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", ¤t_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", ¤t_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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
@ -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 */
|
||||||
|
|
Loading…
Reference in a new issue