summaryrefslogtreecommitdiffstats
path: root/gst/qtmux/atoms.c
diff options
context:
space:
mode:
authorDave Robillard <dave@drobilla.net>2009-06-19 21:01:54 -0400
committerDave Robillard <dave@drobilla.net>2009-06-19 21:01:54 -0400
commit925e83ee60c5406b2e5f0f39b0da0f90370efc27 (patch)
treece01d298ed0c5d31853fa43aedc2af0779417816 /gst/qtmux/atoms.c
parent7f3bcd484b465d8216ac419754450adf07e9b0d2 (diff)
parentc70dbe94b5ff9a0993d852605d40c21020c59552 (diff)
downloadgst-plugins-bad-925e83ee60c5406b2e5f0f39b0da0f90370efc27.tar.gz
gst-plugins-bad-925e83ee60c5406b2e5f0f39b0da0f90370efc27.tar.bz2
gst-plugins-bad-925e83ee60c5406b2e5f0f39b0da0f90370efc27.zip
Merge branch 'master' of git://anongit.freedesktop.org/gstreamer/gst-plugins-bad into fdo
Diffstat (limited to 'gst/qtmux/atoms.c')
-rw-r--r--gst/qtmux/atoms.c186
1 files changed, 164 insertions, 22 deletions
diff --git a/gst/qtmux/atoms.c b/gst/qtmux/atoms.c
index 47db40ce..29859d00 100644
--- a/gst/qtmux/atoms.c
+++ b/gst/qtmux/atoms.c
@@ -1036,7 +1036,8 @@ atom_meta_free (AtomMETA * meta)
{
atom_full_clear (&meta->header);
atom_hdlr_clear (&meta->hdlr);
- atom_ilst_free (meta->ilst);
+ if (meta->ilst)
+ atom_ilst_free (meta->ilst);
meta->ilst = NULL;
g_free (meta);
}
@@ -1061,8 +1062,11 @@ static void
atom_udta_free (AtomUDTA * udta)
{
atom_clear (&udta->header);
- atom_meta_free (udta->meta);
+ if (udta->meta)
+ atom_meta_free (udta->meta);
udta->meta = NULL;
+ if (udta->entries)
+ atom_info_list_free (udta->entries);
g_free (udta);
}
@@ -1149,6 +1153,7 @@ atom_moov_init (AtomMOOV * moov, AtomsContext * context)
atom_mvhd_init (&(moov->mvhd));
moov->udta = NULL;
moov->traks = NULL;
+ moov->context = *context;
}
AtomMOOV *
@@ -1170,13 +1175,11 @@ atom_moov_free (AtomMOOV * moov)
walker = moov->traks;
while (walker) {
- GList *aux = walker;
-
+ atom_trak_free ((AtomTRAK *) walker->data);
walker = g_list_next (walker);
- moov->traks = g_list_remove_link (moov->traks, aux);
- atom_trak_free ((AtomTRAK *) aux->data);
- g_list_free (aux);
}
+ g_list_free (moov->traks);
+ moov->traks = NULL;
if (moov->udta) {
atom_udta_free (moov->udta);
@@ -1240,9 +1243,6 @@ atom_copy_data (Atom * atom, guint8 ** buffer, guint64 * size, guint64 * offset)
* would be a problem for size (re)write code, not to mention memory */
g_return_val_if_fail (atom->type == FOURCC_mdat, 0);
prop_copy_uint64 (atom->extended_size, buffer, size, offset);
- } else {
- /* just in case some trivially derived atom does not do so */
- atom_write_size (buffer, size, offset, original_offset);
}
return *offset - original_offset;
@@ -2163,6 +2163,10 @@ atom_udta_copy_data (AtomUDTA * udta, guint8 ** buffer, guint64 * size,
if (!atom_meta_copy_data (udta->meta, buffer, size, offset)) {
return 0;
}
+ } else if (udta->entries) {
+ /* extra atoms */
+ if (!atom_info_list_copy_data (udta->entries, buffer, size, offset))
+ return 0;
}
atom_write_size (buffer, size, offset, original_offset);
@@ -2238,6 +2242,10 @@ stsc_entry_new (guint32 first_chunk, guint32 samples, guint32 desc_index)
static void
atom_stsc_add_new_entry (AtomSTSC * stsc, guint32 first_chunk, guint32 nsamples)
{
+ if (stsc->entries &&
+ ((STSCEntry *) stsc->entries->data)->samples_per_chunk == nsamples)
+ return;
+
stsc->entries =
g_list_prepend (stsc->entries, stsc_entry_new (first_chunk, nsamples, 1));
stsc->n_entries++;
@@ -2517,16 +2525,18 @@ atom_moov_chunks_add_offset (AtomMOOV * moov, guint32 offset)
* Meta tags functions
*/
static void
-atom_moov_init_metatags (AtomMOOV * moov)
+atom_moov_init_metatags (AtomMOOV * moov, AtomsContext * context)
{
if (!moov->udta) {
moov->udta = atom_udta_new ();
}
- if (!moov->udta->meta) {
- moov->udta->meta = atom_meta_new ();
- }
- if (!moov->udta->meta->ilst) {
- moov->udta->meta->ilst = atom_ilst_new ();
+ if (context->flavor != ATOMS_TREE_FLAVOR_3GP) {
+ if (!moov->udta->meta) {
+ moov->udta->meta = atom_meta_new ();
+ }
+ if (!moov->udta->meta->ilst) {
+ moov->udta->meta->ilst = atom_ilst_new ();
+ }
}
}
@@ -2543,11 +2553,14 @@ atom_tag_data_alloc_data (AtomTagData * data, guint size)
static void
atom_moov_append_tag (AtomMOOV * moov, AtomInfo * tag)
{
- AtomILST *ilst;
+ GList **entries;
- atom_moov_init_metatags (moov);
- ilst = moov->udta->meta->ilst;
- ilst->entries = g_list_append (ilst->entries, tag);
+ atom_moov_init_metatags (moov, &moov->context);
+ if (moov->udta->meta)
+ entries = &moov->udta->meta->ilst->entries;
+ else
+ entries = &moov->udta->entries;
+ *entries = g_list_append (*entries, tag);
}
void
@@ -2621,6 +2634,87 @@ atom_moov_add_blob_tag (AtomMOOV * moov, guint8 * data, guint size)
atom_data_free));
}
+void
+atom_moov_add_3gp_tag (AtomMOOV * moov, guint32 fourcc, guint8 * data,
+ guint size)
+{
+ AtomData *data_atom;
+ GstBuffer *buf;
+ guint8 *bdata;
+
+ /* need full atom */
+ buf = gst_buffer_new_and_alloc (size + 4);
+ bdata = GST_BUFFER_DATA (buf);
+ /* full atom: version and flags */
+ GST_WRITE_UINT32_BE (bdata, 0);
+ memcpy (bdata + 4, data, size);
+
+ data_atom = atom_data_new_from_gst_buffer (fourcc, buf);
+ gst_buffer_unref (buf);
+
+ atom_moov_append_tag (moov,
+ build_atom_info_wrapper ((Atom *) data_atom, atom_data_copy_data,
+ atom_data_free));
+}
+
+guint16
+language_code (const char *lang)
+{
+ g_return_val_if_fail (lang != NULL, 0);
+ g_return_val_if_fail (strlen (lang) == 3, 0);
+
+ return (((lang[0] - 0x60) & 0x1F) << 10) + (((lang[1] - 0x60) & 0x1F) << 5) +
+ ((lang[2] - 0x60) & 0x1F);
+}
+
+void
+atom_moov_add_3gp_str_int_tag (AtomMOOV * moov, guint32 fourcc,
+ const gchar * value, gint16 ivalue)
+{
+ gint len = 0, size = 0;
+ guint8 *data;
+
+ if (value) {
+ len = strlen (value);
+ size = len + 3;
+ }
+
+ if (ivalue >= 0)
+ size += 2;
+
+ data = g_malloc (size + 3);
+ /* language tag and null-terminated UTF-8 string */
+ if (value) {
+ GST_WRITE_UINT16_BE (data, language_code (GST_QT_MUX_DEFAULT_TAG_LANGUAGE));
+ /* include 0 terminator */
+ memcpy (data + 2, value, len + 1);
+ }
+ /* 16-bit unsigned int if standalone, otherwise 8-bit */
+ if (ivalue >= 0) {
+ if (size == 2)
+ GST_WRITE_UINT16_BE (data + size - 2, ivalue);
+ else {
+ GST_WRITE_UINT8 (data + size - 2, ivalue & 0xFF);
+ size--;
+ }
+ }
+
+ atom_moov_add_3gp_tag (moov, fourcc, data, size);
+ g_free (data);
+}
+
+void
+atom_moov_add_3gp_str_tag (AtomMOOV * moov, guint32 fourcc, const gchar * value)
+{
+ atom_moov_add_3gp_str_int_tag (moov, fourcc, value, -1);
+}
+
+void
+atom_moov_add_3gp_uint_tag (AtomMOOV * moov, guint32 fourcc, guint16 value)
+{
+ atom_moov_add_3gp_str_int_tag (moov, fourcc, NULL, value);
+}
+
/*
* Functions for specifying media types
*/
@@ -2804,14 +2898,56 @@ atom_trak_set_audio_type (AtomTRAK * trak, AtomsContext * context,
atom_trak_set_constant_size_samples (trak, sample_size);
}
+AtomInfo *
+build_pasp_extension (AtomTRAK * trak, gint par_width, gint par_height)
+{
+ AtomData *atom_data;
+ GstBuffer *buf;
+ guint8 *data;
+
+ buf = gst_buffer_new_and_alloc (8);
+ data = GST_BUFFER_DATA (buf);
+
+ /* ihdr = image header box */
+ GST_WRITE_UINT32_BE (data, par_width);
+ GST_WRITE_UINT32_BE (data + 4, par_height);
+
+ atom_data = atom_data_new_from_gst_buffer (FOURCC_pasp, buf);
+ gst_buffer_unref (buf);
+
+ return build_atom_info_wrapper ((Atom *) atom_data, atom_data_copy_data,
+ atom_data_free);
+}
+
void
atom_trak_set_video_type (AtomTRAK * trak, AtomsContext * context,
VisualSampleEntry * entry, guint32 scale, AtomInfo * ext)
{
SampleTableEntryMP4V *ste;
+ gint dwidth, dheight;
+ gint par_n = 0, par_d = 0;
+
+ if ((entry->par_n != 1 || entry->par_d != 1) &&
+ (entry->par_n != entry->par_d)) {
+ par_n = entry->par_n;
+ par_d = entry->par_d;
+ }
+
+ dwidth = entry->width;
+ dheight = entry->height;
+ /* ISO file spec says track header w/h indicates track's visual presentation
+ * (so this together with pixels w/h implicitly defines PAR) */
+ if (par_n && (context->flavor != ATOMS_TREE_FLAVOR_MOV)) {
+ if (par_n > par_d) {
+ dwidth = entry->width * par_n / par_d;
+ dheight = entry->height;
+ } else {
+ dwidth = entry->width * par_n / par_d;
+ dheight = entry->height;
+ }
+ }
- atom_trak_set_video_commons (trak, context, scale, entry->width,
- entry->height);
+ atom_trak_set_video_commons (trak, context, scale, dwidth, dheight);
ste = atom_trak_add_video_entry (trak, context, entry->fourcc);
trak->is_video = TRUE;
@@ -2825,6 +2961,12 @@ atom_trak_set_video_type (AtomTRAK * trak, AtomsContext * context,
if (ext)
ste->extension_atoms = g_list_prepend (ste->extension_atoms, ext);
+
+ /* QT spec has a pasp extension atom in stsd that can hold PAR */
+ if (par_n && (context->flavor == ATOMS_TREE_FLAVOR_MOV)) {
+ ste->extension_atoms = g_list_append (ste->extension_atoms,
+ build_pasp_extension (trak, par_n, par_d));
+ }
}
/* some sample description construction helpers */