summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian.droege@collabora.co.uk>2009-03-11 19:33:38 +0100
committerSebastian Dröge <sebastian.droege@collabora.co.uk>2009-03-21 10:19:47 +0100
commit60d0dc07bfe9fa1735f31231ed43d81f64643a3a (patch)
treee4532b913339fa617b6c7f1dabf7e897b1b19a40
parent0a5dc919fb8fd9f48307d5e9dd44d9a84a10e2d3 (diff)
downloadgst-plugins-bad-60d0dc07bfe9fa1735f31231ed43d81f64643a3a.tar.gz
gst-plugins-bad-60d0dc07bfe9fa1735f31231ed43d81f64643a3a.tar.bz2
gst-plugins-bad-60d0dc07bfe9fa1735f31231ed43d81f64643a3a.zip
mxfmux: Add support for muxing A-Law audio
-rw-r--r--gst/mxf/mxfalaw.c174
1 files changed, 174 insertions, 0 deletions
diff --git a/gst/mxf/mxfalaw.c b/gst/mxf/mxfalaw.c
index 074f1a48..db7456cb 100644
--- a/gst/mxf/mxfalaw.c
+++ b/gst/mxf/mxfalaw.c
@@ -29,6 +29,7 @@
#include <string.h>
#include "mxfalaw.h"
+#include "mxfwrite.h"
GST_DEBUG_CATEGORY_EXTERN (mxf_debug);
#define GST_CAT_DEFAULT mxf_debug
@@ -138,8 +139,181 @@ static const MXFEssenceElementHandler mxf_alaw_essence_element_handler = {
mxf_alaw_create_caps
};
+typedef struct
+{
+ guint64 error;
+ gint rate, channels;
+ MXFFraction edit_rate;
+} ALawMappingData;
+
+static GstFlowReturn
+mxf_alaw_write_func (GstBuffer * buffer, GstCaps * caps, gpointer mapping_data,
+ GstAdapter * adapter, GstBuffer ** outbuf, gboolean flush)
+{
+ ALawMappingData *md = mapping_data;
+ guint bytes;
+
+ if (buffer) {
+ guint64 speu =
+ gst_util_uint64_scale (md->rate, md->edit_rate.d, md->edit_rate.n);
+
+ md->error += (GST_SECOND * md->edit_rate.d * md->rate) % (md->edit_rate.n);
+ if (md->error >= md->edit_rate.n) {
+ md->error = 0;
+ speu += 1;
+ }
+
+ bytes = speu * md->channels;
+
+ gst_adapter_push (adapter, buffer);
+ if (gst_adapter_available (adapter) >= bytes) {
+ *outbuf = gst_adapter_take_buffer (adapter, bytes);
+ }
+ } else if (flush && (bytes = gst_adapter_available (adapter))) {
+ *outbuf = gst_adapter_take_buffer (adapter, bytes);
+ }
+
+ return GST_FLOW_OK;
+}
+
+static const guint8 alaw_essence_container_ul[] = {
+ 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x03,
+ 0x0d, 0x01, 0x03, 0x01, 0x02, 0x0a, 0x01, 0x00
+};
+
+static const MXFUL mxf_sound_essence_compression_alaw =
+ { {0x06, 0x0E, 0x2B, 0x34, 0x04, 0x01, 0x01, 0x03, 0x04, 0x02, 0x02, 0x02,
+ 0x03, 0x01, 0x01, 0x00}
+};
+
+static MXFMetadataFileDescriptor *
+mxf_alaw_get_descriptor (GstPadTemplate * tmpl, GstCaps * caps,
+ MXFEssenceElementWriteFunc * handler, gpointer * mapping_data)
+{
+ MXFMetadataGenericSoundEssenceDescriptor *ret;
+ GstStructure *s;
+ ALawMappingData *md;
+ gint rate, channels;
+
+ s = gst_caps_get_structure (caps, 0);
+ if (strcmp (gst_structure_get_name (s), "audio/x-alaw") != 0)
+ return NULL;
+
+ if (!gst_structure_get_int (s, "rate", &rate) ||
+ !gst_structure_get_int (s, "channels", &channels))
+ return NULL;
+
+ ret = (MXFMetadataGenericSoundEssenceDescriptor *)
+ gst_mini_object_new (MXF_TYPE_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR);
+
+ memcpy (&ret->parent.essence_container, &alaw_essence_container_ul, 16);
+ memcpy (&ret->sound_essence_compression, &mxf_sound_essence_compression_alaw,
+ 16);
+
+ mxf_metadata_generic_sound_essence_descriptor_from_caps (ret, caps);
+ *handler = mxf_alaw_write_func;
+
+ md = g_new0 (ALawMappingData, 1);
+ md->rate = rate;
+ md->channels = channels;
+ *mapping_data = md;
+
+ return (MXFMetadataFileDescriptor *) ret;
+}
+
+static void
+mxf_alaw_update_descriptor (MXFMetadataFileDescriptor * d, GstCaps * caps,
+ gpointer mapping_data, GstBuffer * buf)
+{
+ return;
+}
+
+static guint
+gst_greatest_common_divisor (guint a, guint b)
+{
+ while (b != 0) {
+ guint temp = a;
+
+ a = b;
+ b = temp % b;
+ }
+
+ return a;
+}
+
+static void
+mxf_alaw_get_edit_rate (MXFMetadataFileDescriptor * a, GstCaps * caps,
+ gpointer mapping_data, GstBuffer * buf, MXFMetadataSourcePackage * package,
+ MXFMetadataTimelineTrack * track, MXFFraction * edit_rate)
+{
+ guint i;
+ gdouble min = G_MAXDOUBLE;
+ MXFMetadataGenericSoundEssenceDescriptor *d =
+ MXF_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (a);
+ ALawMappingData *md = mapping_data;
+
+ for (i = 0; i < package->parent.n_tracks; i++) {
+ MXFMetadataTimelineTrack *tmp;
+
+ if (!MXF_IS_METADATA_TIMELINE_TRACK (package->parent.tracks[i]) ||
+ package->parent.tracks[i] == (MXFMetadataTrack *) track)
+ continue;
+
+ tmp = MXF_METADATA_TIMELINE_TRACK (package->parent.tracks[i]);
+ if (((gdouble) tmp->edit_rate.n) / ((gdouble) tmp->edit_rate.d) < min) {
+ min = ((gdouble) tmp->edit_rate.n) / ((gdouble) tmp->edit_rate.d);
+ memcpy (edit_rate, &tmp->edit_rate, sizeof (MXFFraction));
+ }
+ }
+
+ if (min == G_MAXDOUBLE) {
+ guint32 nu, de;
+ guint gcd;
+
+ /* 50ms edit units */
+ nu = d->audio_sampling_rate.n;
+ de = d->audio_sampling_rate.d * 20;
+ gcd = gst_greatest_common_divisor (nu, de);
+ nu /= gcd;
+ de /= gcd;
+
+ (*edit_rate).n = nu;
+ (*edit_rate).d = de;
+ }
+
+ memcpy (&md->edit_rate, edit_rate, sizeof (MXFFraction));
+}
+
+static guint32
+mxf_alaw_get_track_number_template (MXFMetadataFileDescriptor * a,
+ GstCaps * caps, gpointer mapping_data)
+{
+ return (0x16 << 24) | (0x08 << 8);
+}
+
+static MXFEssenceElementWriter mxf_alaw_essence_element_writer = {
+ mxf_alaw_get_descriptor,
+ mxf_alaw_update_descriptor,
+ mxf_alaw_get_edit_rate,
+ mxf_alaw_get_track_number_template,
+ NULL,
+ {{0,}}
+};
+
+#define ALAW_CAPS \
+ "audio/x-alaw, " \
+ "rate = (int) [ 8000, 192000 ], " \
+ "channels = (int) [ 1, 2 ]"
+
void
mxf_alaw_init (void)
{
mxf_essence_element_handler_register (&mxf_alaw_essence_element_handler);
+
+ mxf_alaw_essence_element_writer.pad_template =
+ gst_pad_template_new ("alaw_audio_sink_%u", GST_PAD_SINK, GST_PAD_REQUEST,
+ gst_caps_from_string (ALAW_CAPS));
+ memcpy (&mxf_alaw_essence_element_writer.data_definition,
+ mxf_metadata_track_identifier_get (MXF_METADATA_TRACK_SOUND_ESSENCE), 16);
+ mxf_essence_element_writer_register (&mxf_alaw_essence_element_writer);
}