summaryrefslogtreecommitdiffstats
path: root/sys/qtwrapper
diff options
context:
space:
mode:
Diffstat (limited to 'sys/qtwrapper')
-rw-r--r--sys/qtwrapper/audiodecoders.c623
-rw-r--r--sys/qtwrapper/codecmapping.h10
-rw-r--r--sys/qtwrapper/imagedescription.c18
-rw-r--r--sys/qtwrapper/imagedescription.h1
-rw-r--r--sys/qtwrapper/qtutils.c67
-rw-r--r--sys/qtwrapper/qtutils.h7
-rw-r--r--sys/qtwrapper/qtwrapper.c16
-rw-r--r--sys/qtwrapper/qtwrapper.h6
-rw-r--r--sys/qtwrapper/videodecoders.c70
9 files changed, 507 insertions, 311 deletions
diff --git a/sys/qtwrapper/audiodecoders.c b/sys/qtwrapper/audiodecoders.c
index 2efd5ae8..ed5c69ce 100644
--- a/sys/qtwrapper/audiodecoders.c
+++ b/sys/qtwrapper/audiodecoders.c
@@ -1,7 +1,8 @@
/*
* GStreamer QuickTime audio decoder codecs wrapper
* Copyright <2006, 2007> Fluendo <gstreamer@fluendo.com>
- * Copyright <2006, 2007> Pioneers of the Inevitable <songbird@songbirdnest.com>
+ * Copyright <2006, 2007, 2008> Pioneers of the Inevitable
+ * <songbird@songbirdnest.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -46,14 +47,19 @@
#include "config.h"
#endif
-#include <QuickTime/Movies.h>
-#include <AudioToolbox/AudioToolbox.h>
+#include <string.h>
-#include <gst/base/gstadapter.h>
+#include <gst/gst.h>
#include "qtwrapper.h"
#include "codecmapping.h"
#include "qtutils.h"
+#ifdef G_OS_WIN32
+#include <QuickTimeComponents.h>
+#else
+#include <Quicktime/QuickTimeComponents.h>
+#endif
+
#define QTWRAPPER_ADEC_PARAMS_QDATA g_quark_from_static_string("qtwrapper-adec-params")
static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
@@ -63,7 +69,8 @@ static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
"endianness = (int) {" G_STRINGIFY (G_BYTE_ORDER) " }, "
"signed = (boolean) { TRUE }, "
"width = (int) 32, "
- "depth = (int) 32, " "rate = (int) 44100, " "channels = (int) 2")
+ "depth = (int) 32, " "rate = (int) [1, MAX], "
+ "channels = (int) [1, MAX]")
);
typedef struct _QTWrapperAudioDecoder QTWrapperAudioDecoder;
@@ -77,12 +84,14 @@ struct _QTWrapperAudioDecoder
GstPad *srcpad;
/* FIXME : all following should be protected by a mutex */
- AudioConverterRef aconv;
+ ComponentInstance adec; /* The Audio Decoder component */
AudioStreamBasicDescription indesc, outdesc;
guint samplerate;
guint channels;
+
AudioBufferList *bufferlist;
+ AudioStreamPacketDescription aspd[1];
/* first time received after NEWSEGMENT */
GstClockTime initial_time;
@@ -91,13 +100,8 @@ struct _QTWrapperAudioDecoder
/* TRUE just after receiving a NEWSEGMENT */
gboolean gotnewsegment;
- /* temporary output data */
- gpointer tmpdata;
-
- /* buffer previously used by the decoder */
- gpointer prevdata;
-
- GstAdapter *adapter;
+ /* Data for StdAudio callbacks */
+ GstBuffer *input_buffer;
};
struct _QTWrapperAudioDecoderClass
@@ -126,52 +130,6 @@ static gboolean qtwrapper_audio_decoder_sink_event (GstPad * pad,
GstEvent * event);
static void
-qtwrapper_audio_decoder_base_init (QTWrapperAudioDecoderClass * klass)
-{
- GstElementDetails details;
- GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
- gchar *name = NULL;
- gchar *info = NULL;
- ComponentDescription desc;
- QTWrapperAudioDecoderParams *params;
-
- params = (QTWrapperAudioDecoderParams *)
- g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass),
- QTWRAPPER_ADEC_PARAMS_QDATA);
- g_assert (params);
-
- get_name_info_from_component (params->component, &desc, &name, &info);
-
- /* Fill in details */
- details.longname = g_strdup_printf ("QTWrapper Audio Decoder : %s", name);
- details.klass = "Codec/Decoder/Audio";
- details.description = info;
- details.author = "Fluendo <gstreamer@fluendo.com>, "
- "Pioneers of the Inevitable <songbird@songbirdnest.com>";
- gst_element_class_set_details (element_class, &details);
-
- g_free (details.longname);
- g_free (name);
- g_free (info);
-
- /* Add pad templates */
- klass->sinktempl = gst_pad_template_new ("sink", GST_PAD_SINK,
- GST_PAD_ALWAYS, params->sinkcaps);
- gst_element_class_add_pad_template (element_class, klass->sinktempl);
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&src_templ));
-
- /* Store class-global values */
- klass->componentSubType = desc.componentSubType;
-}
-
-static void
-qtwrapper_audio_decoder_class_init (QTWrapperAudioDecoderClass * klass)
-{
- /* FIXME : don't we need some vmethod implementations here ?? */
-}
-
-static void
qtwrapper_audio_decoder_init (QTWrapperAudioDecoder * qtwrapper)
{
QTWrapperAudioDecoderClass *oclass;
@@ -191,8 +149,6 @@ qtwrapper_audio_decoder_init (QTWrapperAudioDecoder * qtwrapper)
/* Source pad */
qtwrapper->srcpad = gst_pad_new_from_static_template (&src_templ, "src");
gst_element_add_pad (GST_ELEMENT (qtwrapper), qtwrapper->srcpad);
-
- qtwrapper->adapter = gst_adapter_new ();
}
static void
@@ -206,17 +162,17 @@ clear_AudioStreamBasicDescription (AudioStreamBasicDescription * desc)
desc->mBytesPerFrame = 0;
desc->mChannelsPerFrame = 0;
desc->mBitsPerChannel = 0;
-
+ desc->mReserved = 0;
}
static void
fill_indesc_mp3 (QTWrapperAudioDecoder * qtwrapper, guint32 fourcc, gint rate,
gint channels)
{
- GST_LOG ("...");
+ GST_INFO_OBJECT (qtwrapper, "Filling input description for MP3 data");
clear_AudioStreamBasicDescription (&qtwrapper->indesc);
/* only the samplerate is needed apparently */
- qtwrapper->indesc.mSampleRate = rate;
+ qtwrapper->indesc.mSampleRate = (double) rate;
qtwrapper->indesc.mFormatID = kAudioFormatMPEGLayer3;
qtwrapper->indesc.mChannelsPerFrame = channels;
}
@@ -226,10 +182,10 @@ fill_indesc_aac (QTWrapperAudioDecoder * qtwrapper, guint32 fourcc, gint rate,
gint channels)
{
clear_AudioStreamBasicDescription (&qtwrapper->indesc);
- qtwrapper->indesc.mSampleRate = rate;
+ qtwrapper->indesc.mSampleRate = (double) rate;
qtwrapper->indesc.mFormatID = kAudioFormatMPEG4AAC;
- /* aac always has 1024 bytes per packet */
- qtwrapper->indesc.mBytesPerPacket = 1024;
+ /* aac always has 1024 frames per packet */
+ qtwrapper->indesc.mFramesPerPacket = 1024;
qtwrapper->indesc.mChannelsPerFrame = channels;
}
@@ -257,7 +213,7 @@ fill_indesc_generic (QTWrapperAudioDecoder * qtwrapper, guint32 fourcc,
static gpointer
make_samr_magic_cookie (GstBuffer * codec_data, gsize * len)
{
- gpointer res;
+ guint8 *res;
*len = 48;
res = g_malloc0 (0x30);
@@ -288,21 +244,107 @@ make_samr_magic_cookie (GstBuffer * codec_data, gsize * len)
return res;
}
+static int
+write_len (guint8 * buf, int val)
+{
+ /* This is some sort of variable-length coding, but the quicktime
+ * file(s) I have here all just use a 4-byte version, so we'll do that.
+ * Return the number of bytes written;
+ */
+ buf[0] = ((val >> 21) & 0x7f) | 0x80;
+ buf[1] = ((val >> 14) & 0x7f) | 0x80;
+ buf[2] = ((val >> 7) & 0x7f) | 0x80;
+ buf[3] = ((val >> 0) & 0x7f);
+
+ return 4;
+}
+
+/* The AAC decoder requires the entire mpeg4 audio elementary stream
+ * descriptor, which is the body (except the 4-byte version field) of
+ * the quicktime 'esds' atom. However, qtdemux only passes through the
+ * (two byte, normally) payload, so we need to reconstruct the ESD */
+
+/* TODO: Get the AAC spec, and verify this implementation */
+static gpointer
+make_aac_magic_cookie (GstBuffer * codec_data, gsize * len)
+{
+ guint8 *cookie;
+ int offset = 0;
+ int decoder_specific_len = GST_BUFFER_SIZE (codec_data);
+ int config_len = 13 + 5 + decoder_specific_len;
+ int es_len = 3 + 5 + config_len + 5 + 1;
+ int total_len = es_len + 5;
+
+ cookie = g_malloc0 (total_len);
+ *len = total_len;
+
+ /* Structured something like this:
+ * [ES Descriptor
+ * [Config Descriptor
+ * [Specific Descriptor]]
+ * [Unknown]]
+ */
+
+ QT_WRITE_UINT8 (cookie + offset, 0x03);
+ offset += 1; /* ES Descriptor tag */
+ offset += write_len (cookie + offset, es_len);
+ QT_WRITE_UINT16 (cookie + offset, 0);
+ offset += 2; /* Track ID */
+ QT_WRITE_UINT8 (cookie + offset, 0);
+ offset += 1; /* Flags */
+
+ QT_WRITE_UINT8 (cookie + offset, 0x04);
+ offset += 1; /* Config Descriptor tag */
+ offset += write_len (cookie + offset, config_len);
+
+ /* TODO: Fix these up */
+ QT_WRITE_UINT8 (cookie + offset, 0x40);
+ offset += 1; /* object_type_id */
+ QT_WRITE_UINT8 (cookie + offset, 0x15);
+ offset += 1; /* stream_type */
+ QT_WRITE_UINT24 (cookie + offset, 0x1800);
+ offset += 3; /* buffer_size_db */
+ QT_WRITE_UINT32 (cookie + offset, 128000);
+ offset += 4; /* max_bitrate */
+ QT_WRITE_UINT32 (cookie + offset, 128000);
+ offset += 4; /* avg_bitrate */
+
+ QT_WRITE_UINT8 (cookie + offset, 0x05);
+ offset += 1; /* Specific Descriptor tag */
+ offset += write_len (cookie + offset, decoder_specific_len);
+ memcpy (cookie + offset, GST_BUFFER_DATA (codec_data), decoder_specific_len);
+ offset += decoder_specific_len;
+
+ /* TODO: What is this? 'SL descriptor' apparently, but what does that mean? */
+ QT_WRITE_UINT8 (cookie + offset, 0x06);
+ offset += 1; /* SL Descriptor tag */
+ offset += write_len (cookie + offset, 1);
+ QT_WRITE_UINT8 (cookie + offset, 2);
+ offset += 1;
+
+ return cookie;
+}
+
+
static gboolean
open_decoder (QTWrapperAudioDecoder * qtwrapper, GstCaps * caps,
GstCaps ** othercaps)
{
gboolean ret = FALSE;
QTWrapperAudioDecoderClass *oclass;
+
+ /* TODO: these will be used as the output rate/channels for formats that
+ * don't supply these in the caps. This isn't very nice!
+ */
gint channels = 2;
gint rate = 44100;
- gint depth = 32;
- OSErr oserr;
+
OSStatus status;
GstStructure *s;
gchar *tmp;
const GValue *value;
GstBuffer *codec_data = NULL;
+ gboolean have_esds = FALSE;
tmp = gst_caps_to_string (caps);
GST_LOG_OBJECT (qtwrapper, "caps: %s", tmp);
@@ -313,17 +355,15 @@ open_decoder (QTWrapperAudioDecoder * qtwrapper, GstCaps * caps,
gst_structure_get_int (s, "rate", &rate);
gst_structure_get_int (s, "channels", &channels);
- /* depth isn't compulsory */
- if (!(gst_structure_get_int (s, "depth", &depth)))
- gst_structure_get_int (s, "samplesize", &depth);
-
/* get codec_data */
if ((value = gst_structure_get_value (s, "codec_data"))) {
codec_data = GST_BUFFER_CAST (gst_value_get_mini_object (value));
}
- /* If the quicktime demuxer gives us a full esds atom, use that instead of the codec_data */
+ /* If the quicktime demuxer gives us a full esds atom, use that instead of
+ * the codec_data */
if ((value = gst_structure_get_value (s, "quicktime_esds"))) {
+ have_esds = TRUE;
codec_data = GST_BUFFER_CAST (gst_value_get_mini_object (value));
}
#if DEBUG_DUMP
@@ -333,9 +373,11 @@ open_decoder (QTWrapperAudioDecoder * qtwrapper, GstCaps * caps,
#endif
- GST_LOG ("rate:%d, channels:%d, depth:%d", rate, channels, depth);
+ GST_INFO_OBJECT (qtwrapper, "rate:%d, channels:%d", rate, channels);
oclass = (QTWrapperAudioDecoderClass *) (G_OBJECT_GET_CLASS (qtwrapper));
+ GST_INFO_OBJECT (qtwrapper, "componentSubType is %" GST_FOURCC_FORMAT,
+ QT_FOURCC_ARGS (oclass->componentSubType));
/* Setup the input format description, some format require special handling */
switch (oclass->componentSubType) {
@@ -355,64 +397,148 @@ open_decoder (QTWrapperAudioDecoder * qtwrapper, GstCaps * caps,
}
#if DEBUG_DUMP
- gst_util_dump_mem (&qtwrapper->indesc, sizeof (AudioStreamBasicDescription));
+ gst_util_dump_mem ((gpointer) & qtwrapper->indesc,
+ sizeof (AudioStreamBasicDescription));
#endif
- /* we're forcing output to stereo 44.1kHz */
- rate = 44100;
- channels = 2;
-
qtwrapper->samplerate = rate;
qtwrapper->channels = channels;
- /* Setup the output format description */
- qtwrapper->outdesc.mSampleRate = rate;
- qtwrapper->outdesc.mFormatID = kAudioFormatLinearPCM;
- qtwrapper->outdesc.mFormatFlags = kAudioFormatFlagIsFloat;
-#if G_BYTE_ORDER == G_BIG_ENDIAN
- qtwrapper->outdesc.mFormatFlags |= kAudioFormatFlagIsBigEndian;
-#endif
- qtwrapper->outdesc.mBytesPerPacket = channels * 4; /* ?? */
- qtwrapper->outdesc.mFramesPerPacket = 1;
- qtwrapper->outdesc.mBytesPerFrame = channels * 4; /* channels * bytes-per-samples */
- qtwrapper->outdesc.mChannelsPerFrame = channels;
- qtwrapper->outdesc.mBitsPerChannel = 32;
-
- /* Create an AudioConverter */
- status = AudioConverterNew (&qtwrapper->indesc,
- &qtwrapper->outdesc, &qtwrapper->aconv);
- if (status != noErr) {
+ /* Create an instance of SCAudio */
+ status = OpenADefaultComponent (StandardCompressionType,
+ StandardCompressionSubTypeAudio, &qtwrapper->adec);
+ if (status) {
GST_WARNING_OBJECT (qtwrapper,
- "Error when calling AudioConverterNew() : %" GST_FOURCC_FORMAT,
- QT_FOURCC_ARGS (status));
+ "Error instantiating SCAudio component: %ld", status);
goto beach;
}
+ /* This is necessary to make setting the InputBasicDescription succeed;
+ without it SCAudio only accepts PCM as input. Presumably a bug in
+ QuickTime. Thanks to Arek for figuring this one out!
+ */
+ {
+ QTAtomContainer audiosettings = NULL;
+
+ SCGetSettingsAsAtomContainer (qtwrapper->adec, &audiosettings);
+ SCSetSettingsFromAtomContainer (qtwrapper->adec, audiosettings);
+
+ /* TODO: Figure out if disposing of the QTAtomContainer is needed here */
+ }
+
+ /* Set the input description info on the SCAudio instance */
+ status = QTSetComponentProperty (qtwrapper->adec, kQTPropertyClass_SCAudio,
+ kQTSCAudioPropertyID_InputBasicDescription,
+ sizeof (qtwrapper->indesc), &qtwrapper->indesc);
+ if (status) {
+ GST_WARNING_OBJECT (qtwrapper,
+ "Error setting input description on SCAudio: %ld", status);
+ goto beach;
+ }
+
+ /* TODO: we can select a channel layout here, figure out if we want to */
+
/* if we have codec_data, give it to the converter ! */
if (codec_data) {
gsize len;
gpointer magiccookie;
- if (oclass->componentSubType == QT_MAKE_FOURCC_LE ('s', 'a', 'm', 'r')) {
- magiccookie = make_samr_magic_cookie (codec_data, &len);
- } else {
- len = GST_BUFFER_SIZE (codec_data);
- magiccookie = GST_BUFFER_DATA (codec_data);
+ switch (oclass->componentSubType) {
+ /* Some decoders want the 'magic cookie' in a different format from how
+ * gstreamer represents it. So, convert...
+ */
+ case QT_MAKE_FOURCC_LE ('s', 'a', 'm', 'r'):
+ magiccookie = make_samr_magic_cookie (codec_data, &len);
+ break;
+ case QT_MAKE_FOURCC_LE ('m', 'p', '4', 'a'):
+ if (!have_esds) {
+ magiccookie = make_aac_magic_cookie (codec_data, &len);
+ break;
+ }
+ /* Else: fallthrough */
+ default:
+ len = GST_BUFFER_SIZE (codec_data);
+ magiccookie = GST_BUFFER_DATA (codec_data);
+ break;
}
+
GST_LOG_OBJECT (qtwrapper, "Setting magic cookie %p of size %"
G_GSIZE_FORMAT, magiccookie, len);
- oserr = AudioConverterSetProperty (qtwrapper->aconv,
- kAudioConverterDecompressionMagicCookie, len, magiccookie);
- if (oserr != noErr) {
- GST_WARNING_OBJECT (qtwrapper, "Error setting extra codec data !");
+
+#if DEBUG_DUMP
+ gst_util_dump_mem (magiccookie, len);
+#endif
+
+ status = QTSetComponentProperty (qtwrapper->adec, kQTPropertyClass_SCAudio,
+ kQTSCAudioPropertyID_InputMagicCookie, len, magiccookie);
+ if (status) {
+ GST_WARNING_OBJECT (qtwrapper, "Error setting extra codec data: %ld",
+ status);
+ goto beach;
+ }
+ }
+
+ /* Set output to be interleaved raw PCM */
+ {
+ OSType outputFormat = kAudioFormatLinearPCM;
+ SCAudioFormatFlagsRestrictions restrictions = { 0 };
+
+ /* Set the mask in order to set this flag to zero */
+ restrictions.formatFlagsMask =
+ kAudioFormatFlagIsFloat | kAudioFormatFlagIsBigEndian;
+ restrictions.formatFlagsValues = kAudioFormatFlagIsFloat;
+
+ status = QTSetComponentProperty (qtwrapper->adec, kQTPropertyClass_SCAudio,
+ kQTSCAudioPropertyID_ClientRestrictedLPCMFlags,
+ sizeof (restrictions), &restrictions);
+ if (status) {
+ GST_WARNING_OBJECT (qtwrapper, "Error setting PCM to interleaved: %ld",
+ status);
+ goto beach;
+ }
+
+ status = QTSetComponentProperty (qtwrapper->adec, kQTPropertyClass_SCAudio,
+ kQTSCAudioPropertyID_ClientRestrictedCompressionFormatList,
+ sizeof (outputFormat), &outputFormat);
+ if (status) {
+ GST_WARNING_OBJECT (qtwrapper, "Error setting output to PCM: %ld",
+ status);
goto beach;
}
}
- /* Create output bufferlist */
- qtwrapper->bufferlist = AllocateAudioBufferList (channels,
- rate * channels * 4 / 20);
+ status = QTGetComponentProperty (qtwrapper->adec, kQTPropertyClass_SCAudio,
+ kQTSCAudioPropertyID_BasicDescription,
+ sizeof (qtwrapper->outdesc), &qtwrapper->outdesc, NULL);
+
+ if (status) {
+ GST_WARNING_OBJECT (qtwrapper,
+ "Failed to get output audio description: %ld", status);
+ ret = FALSE;
+ goto beach;
+ }
+ if (qtwrapper->outdesc.mFormatID != kAudioFormatLinearPCM ||
+ (qtwrapper->outdesc.mFormatFlags & kAudioFormatFlagIsFloat) !=
+ kAudioFormatFlagIsFloat) {
+ GST_WARNING_OBJECT (qtwrapper, "Output is not floating point PCM");
+ ret = FALSE;
+ goto beach;
+ }
+
+ qtwrapper->samplerate = (int) qtwrapper->outdesc.mSampleRate;
+ qtwrapper->channels = qtwrapper->outdesc.mChannelsPerFrame;
+ GST_DEBUG_OBJECT (qtwrapper, "Output is %d Hz, %d channels",
+ qtwrapper->samplerate, qtwrapper->channels);
+
+ /* Create output bufferlist, big enough for 50ms of audio */
+ GST_DEBUG_OBJECT (qtwrapper, "Allocating bufferlist for %d channels",
+ channels);
+ qtwrapper->bufferlist =
+ AllocateAudioBufferList (channels,
+ qtwrapper->samplerate * qtwrapper->channels * 4 / 20);
+
+ /* TODO: Figure out how the output format is determined, can we pick this? */
/* Create output caps */
*othercaps = gst_caps_new_simple ("audio/x-raw-float",
"endianness", G_TYPE_INT, G_BYTE_ORDER,
@@ -453,15 +579,12 @@ beach:
}
static OSStatus
-process_buffer_cb (AudioConverterRef inAudioConverter,
+process_buffer_cb (ComponentInstance inAudioConverter,
UInt32 * ioNumberDataPackets,
AudioBufferList * ioData,
AudioStreamPacketDescription ** outDataPacketDescription,
QTWrapperAudioDecoder * qtwrapper)
{
- gint len;
- AudioStreamPacketDescription aspd[200];
-
GST_LOG_OBJECT (qtwrapper,
"ioNumberDataPackets:%lu, iodata:%p, outDataPacketDescription:%p",
*ioNumberDataPackets, ioData, outDataPacketDescription);
@@ -474,48 +597,33 @@ process_buffer_cb (AudioConverterRef inAudioConverter,
ioData->mBuffers[0].mData = NULL;
ioData->mBuffers[0].mDataByteSize = 0;
- if (qtwrapper->prevdata)
- g_free (qtwrapper->prevdata);
- len = gst_adapter_available (qtwrapper->adapter);
+ *ioNumberDataPackets = 1;
- if (len) {
- ioData->mBuffers[0].mData = gst_adapter_take (qtwrapper->adapter, len);
- qtwrapper->prevdata = ioData->mBuffers[0].mData;
+ if (qtwrapper->input_buffer && GST_BUFFER_SIZE (qtwrapper->input_buffer)) {
+ ioData->mBuffers[0].mData = GST_BUFFER_DATA (qtwrapper->input_buffer);
+ ioData->mBuffers[0].mDataByteSize =
+ GST_BUFFER_SIZE (qtwrapper->input_buffer);
/* if we have a valid outDataPacketDescription, we need to fill it */
if (outDataPacketDescription) {
- /* mStartOffset : the number of bytes from the start of the buffer to the
- * beginning of the packet. */
- aspd[0].mStartOffset = 0;
- aspd[1].mStartOffset = 0;
- /* mVariableFramesInPacket : the number of samples frames of data in the
- * packet. For formats with a constant number of frames per packet, this
- * field is set to 0. */
- aspd[0].mVariableFramesInPacket = 0;
- aspd[1].mVariableFramesInPacket = 0;
- /* mDataByteSize : The number of bytes in the packet. */
- aspd[0].mDataByteSize = len;
- aspd[1].mDataByteSize = 0;
- GST_LOG ("ASPD: mStartOffset:%lld, mVariableFramesInPacket:%u, "
- "mDataByteSize:%u", aspd[0].mStartOffset,
- (guint32) aspd[0].mVariableFramesInPacket,
- (guint32) aspd[0].mDataByteSize);
- *outDataPacketDescription = (AudioStreamPacketDescription *) & aspd;
+ qtwrapper->aspd[0].mStartOffset = 0;
+ qtwrapper->aspd[0].mVariableFramesInPacket = 0;
+ qtwrapper->aspd[0].mDataByteSize =
+ GST_BUFFER_SIZE (qtwrapper->input_buffer);
+ *outDataPacketDescription = qtwrapper->aspd;
}
- } else {
- qtwrapper->prevdata = NULL;
- }
+ GST_LOG_OBJECT (qtwrapper, "returning %d bytes at %p",
+ GST_BUFFER_SIZE (qtwrapper->input_buffer), ioData->mBuffers[0].mData);
- ioData->mBuffers[0].mDataByteSize = len;
+ qtwrapper->input_buffer = 0;
+ return noErr;
+ }
- GST_LOG_OBJECT (qtwrapper, "returning %d bytes at %p",
- len, ioData->mBuffers[0].mData);
+ GST_LOG_OBJECT (qtwrapper, "No remaining input data, returning 42 for hack");
- if (!len)
- return 42;
- return noErr;
+ return 42;
}
static GstFlowReturn
@@ -523,9 +631,19 @@ qtwrapper_audio_decoder_chain (GstPad * pad, GstBuffer * buf)
{
GstFlowReturn ret = GST_FLOW_OK;
QTWrapperAudioDecoder *qtwrapper;
+ GstBuffer *outbuf;
+ OSStatus status;
+ guint32 outsamples;
+ guint32 savedbytes;
+ guint32 realbytes;
qtwrapper = (QTWrapperAudioDecoder *) gst_pad_get_parent (pad);
+ if (!qtwrapper->adec) {
+ GST_WARNING_OBJECT (qtwrapper, "QTWrapper not initialised");
+ goto beach;
+ }
+
GST_LOG_OBJECT (qtwrapper,
"buffer:%p , timestamp:%" GST_TIME_FORMAT " ,size:%d", buf,
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), GST_BUFFER_SIZE (buf));
@@ -536,9 +654,9 @@ qtwrapper_audio_decoder_chain (GstPad * pad, GstBuffer * buf)
if (qtwrapper->gotnewsegment) {
- GST_DEBUG_OBJECT (qtwrapper, "AudioConverterReset()");
+ GST_DEBUG_OBJECT (qtwrapper, "SCAudioReset()");
- AudioConverterReset (qtwrapper->aconv);
+ SCAudioReset (qtwrapper->adec);
/* some formats can give us a better initial time using the buffer
* timestamp. */
@@ -548,84 +666,78 @@ qtwrapper_audio_decoder_chain (GstPad * pad, GstBuffer * buf)
qtwrapper->gotnewsegment = FALSE;
}
- /* stack in adapter */
- gst_adapter_push (qtwrapper->adapter, buf);
-
- /* do we have enough to decode at least one frame ? */
- while (gst_adapter_available (qtwrapper->adapter)) {
- GstBuffer *outbuf;
- OSStatus status;
- guint32 outsamples = qtwrapper->bufferlist->mBuffers[0].mDataByteSize / 8;
- guint32 savedbytes = qtwrapper->bufferlist->mBuffers[0].mDataByteSize;
- guint32 realbytes;
-
-
- GST_LOG_OBJECT (qtwrapper, "Calling FillBuffer(outsamples:%d , outdata:%p)",
- outsamples, qtwrapper->bufferlist->mBuffers[0].mData);
-
- /* Ask AudioConverter to give us data ! */
- status = AudioConverterFillComplexBuffer (qtwrapper->aconv,
- (AudioConverterComplexInputDataProc) process_buffer_cb,
- qtwrapper, (UInt32 *) & outsamples, qtwrapper->bufferlist, NULL);
-
- if ((status != noErr) && (status != 42)) {
- if (status < 0)
- GST_WARNING_OBJECT (qtwrapper,
- "Error in AudioConverterFillComplexBuffer() : %d", (gint32) status);
- else
- GST_WARNING_OBJECT (qtwrapper,
- "Error in AudioConverterFillComplexBuffer() : %" GST_FOURCC_FORMAT,
- QT_FOURCC_ARGS (status));
- ret = GST_FLOW_ERROR;
- goto beach;
- }
+ outsamples = qtwrapper->bufferlist->mBuffers[0].mDataByteSize / 8;
+ savedbytes = qtwrapper->bufferlist->mBuffers[0].mDataByteSize;
+
+ qtwrapper->input_buffer = buf;
+
+ GST_LOG_OBJECT (qtwrapper, "Calling FillBuffer(outsamples:%d , outdata:%p)",
+ outsamples, qtwrapper->bufferlist->mBuffers[0].mData);
+
+ /* Ask SCAudio to give us data ! */
+ status = SCAudioFillBuffer (qtwrapper->adec,
+ (SCAudioInputDataProc) process_buffer_cb,
+ qtwrapper, (UInt32 *) & outsamples, qtwrapper->bufferlist, NULL);
+
+ /* TODO: What's this '42' crap?? It does seem to be needed, though. */
+ if ((status != noErr) && (status != 42)) {
+ if (status < 0)
+ GST_WARNING_OBJECT (qtwrapper,
+ "Error in SCAudioFillBuffer() : %d", (gint32) status);
+ else
+ GST_WARNING_OBJECT (qtwrapper,
+ "Error in SCAudioFillBuffer() : %" GST_FOURCC_FORMAT,
+ QT_FOURCC_ARGS (status));
+ ret = GST_FLOW_ERROR;
+ goto beach;
+ }
- realbytes = qtwrapper->bufferlist->mBuffers[0].mDataByteSize;
+ realbytes = qtwrapper->bufferlist->mBuffers[0].mDataByteSize;
- GST_LOG_OBJECT (qtwrapper, "We now have %d samples [%d bytes]",
- outsamples, realbytes);
+ GST_LOG_OBJECT (qtwrapper, "We now have %d samples [%d bytes]",
+ outsamples, realbytes);
- qtwrapper->bufferlist->mBuffers[0].mDataByteSize = savedbytes;
+ qtwrapper->bufferlist->mBuffers[0].mDataByteSize = savedbytes;
- if (!outsamples)
- break;
+ if (!outsamples)
+ goto beach;
- /* 4. Create buffer and copy data in it */
- ret = gst_pad_alloc_buffer (qtwrapper->srcpad, qtwrapper->cur_offset,
- realbytes, GST_PAD_CAPS (qtwrapper->srcpad), &outbuf);
- if (ret != GST_FLOW_OK)
- goto beach;
+ /* 4. Create buffer and copy data in it */
+ ret = gst_pad_alloc_buffer (qtwrapper->srcpad, qtwrapper->cur_offset,
+ realbytes, GST_PAD_CAPS (qtwrapper->srcpad), &outbuf);
+ if (ret != GST_FLOW_OK)
+ goto beach;
- /* copy data from bufferlist to output buffer */
- g_memmove (GST_BUFFER_DATA (outbuf),
- qtwrapper->bufferlist->mBuffers[0].mData, realbytes);
+ /* copy data from bufferlist to output buffer */
+ g_memmove (GST_BUFFER_DATA (outbuf),
+ qtwrapper->bufferlist->mBuffers[0].mData, realbytes);
- /* 5. calculate timestamp and duration */
- GST_BUFFER_TIMESTAMP (outbuf) =
- qtwrapper->initial_time + gst_util_uint64_scale_int (GST_SECOND,
- qtwrapper->cur_offset, qtwrapper->samplerate);
- GST_BUFFER_SIZE (outbuf) = realbytes;
- GST_BUFFER_DURATION (outbuf) =
- gst_util_uint64_scale_int (GST_SECOND,
- realbytes / (qtwrapper->channels * 4), qtwrapper->samplerate);
+ /* 5. calculate timestamp and duration */
+ GST_BUFFER_TIMESTAMP (outbuf) =
+ qtwrapper->initial_time + gst_util_uint64_scale_int (GST_SECOND,
+ (gint) qtwrapper->cur_offset, qtwrapper->samplerate);
+ GST_BUFFER_SIZE (outbuf) = realbytes;
+ GST_BUFFER_DURATION (outbuf) =
+ gst_util_uint64_scale_int (GST_SECOND,
+ realbytes / (qtwrapper->channels * 4), qtwrapper->samplerate);
- GST_LOG_OBJECT (qtwrapper,
- "timestamp:%" GST_TIME_FORMAT ", duration:%" GST_TIME_FORMAT
- "offset:%lld, offset_end:%lld",
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
- GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)),
- GST_BUFFER_OFFSET (outbuf), GST_BUFFER_OFFSET_END (outbuf));
+ GST_LOG_OBJECT (qtwrapper,
+ "timestamp:%" GST_TIME_FORMAT ", duration:%" GST_TIME_FORMAT
+ "offset:%lld, offset_end:%lld",
+ GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
+ GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)),
+ GST_BUFFER_OFFSET (outbuf), GST_BUFFER_OFFSET_END (outbuf));
- qtwrapper->cur_offset += outsamples;
+ qtwrapper->cur_offset += outsamples;
- /* 6. push buffer downstream */
+ /* 6. push buffer downstream */
- ret = gst_pad_push (qtwrapper->srcpad, outbuf);
- if (ret != GST_FLOW_OK)
- goto beach;
- }
+ ret = gst_pad_push (qtwrapper->srcpad, outbuf);
+ if (ret != GST_FLOW_OK)
+ goto beach;
beach:
+ gst_buffer_unref (buf);
gst_object_unref (qtwrapper);
return ret;
}
@@ -641,6 +753,7 @@ qtwrapper_audio_decoder_sink_event (GstPad * pad, GstEvent * event)
GST_LOG_OBJECT (qtwrapper, "event:%s", GST_EVENT_TYPE_NAME (event));
switch (GST_EVENT_TYPE (event)) {
+ /* TODO: Flush events should reset the decoder component */
case GST_EVENT_NEWSEGMENT:{
gint64 start, stop, position;
gboolean update;
@@ -671,14 +784,11 @@ qtwrapper_audio_decoder_sink_event (GstPad * pad, GstEvent * event)
qtwrapper->initial_time = start;
qtwrapper->cur_offset = 0;
- gst_adapter_clear (qtwrapper->adapter);
-
GST_LOG ("initial_time is now %" GST_TIME_FORMAT, GST_TIME_ARGS (start));
- if (qtwrapper->aconv)
+ if (qtwrapper->adec)
qtwrapper->gotnewsegment = TRUE;
- /* FIXME : reset adapter */
break;
}
default:
@@ -691,15 +801,67 @@ qtwrapper_audio_decoder_sink_event (GstPad * pad, GstEvent * event)
return TRUE;
}
+static void
+qtwrapper_audio_decoder_base_init (QTWrapperAudioDecoderClass * klass)
+{
+ GstElementDetails details;
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ gchar *name = NULL;
+ gchar *info = NULL;
+ ComponentDescription desc;
+ QTWrapperAudioDecoderParams *params;
+
+ params = (QTWrapperAudioDecoderParams *)
+ g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass),
+ QTWRAPPER_ADEC_PARAMS_QDATA);
+ g_assert (params);
+
+ get_name_info_from_component (params->component, &desc, &name, &info);
+
+ /* Fill in details */
+ details.longname = g_strdup_printf ("QTWrapper SCAudio Audio Decoder : %s",
+ GST_STR_NULL (name));
+ details.klass = "Codec/Decoder/Audio";
+ details.description =
+ g_strdup_printf ("QTWrapper SCAudio wrapper for decoder: %s",
+ GST_STR_NULL (info));
+ details.author =
+ "Fluendo <gstreamer@fluendo.com>, "
+ "Pioneers of the Inevitable <songbird@songbirdnest.com>";
+ gst_element_class_set_details (element_class, &details);
+
+ g_free (details.longname);
+ g_free (details.description);
+ g_free (name);
+ g_free (info);
+
+ /* Add pad templates */
+ klass->sinktempl = gst_pad_template_new ("sink", GST_PAD_SINK,
+ GST_PAD_ALWAYS, params->sinkcaps);
+ gst_element_class_add_pad_template (element_class, klass->sinktempl);
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&src_templ));
+
+ /* Store class-global values */
+ klass->componentSubType = desc.componentSubType;
+}
+
+static void
+qtwrapper_audio_decoder_class_init (QTWrapperAudioDecoderClass * klass)
+{
+ /* FIXME : don't we need some vmethod implementations here ?? */
+}
+
gboolean
qtwrapper_audio_decoders_register (GstPlugin * plugin)
{
gboolean res = TRUE;
- OSErr result;
Component componentID = NULL;
+
ComponentDescription desc = {
- 'sdec', 0, 0, 0, 0
+ kSoundDecompressor, 0, 0, 0, 0
};
+
GTypeInfo typeinfo = {
sizeof (QTWrapperAudioDecoderClass),
(GBaseInitFunc) qtwrapper_audio_decoder_base_init,
@@ -712,18 +874,12 @@ qtwrapper_audio_decoders_register (GstPlugin * plugin)
(GInstanceInitFunc) qtwrapper_audio_decoder_init,
};
- /* Initialize quicktime environment */
- result = EnterMovies ();
- if (result != noErr) {
- GST_ERROR ("Error initializing QuickTime environment");
- res = FALSE;
- goto beach;
- }
-
- /* Find all ImageDecoders ! */
+ /* Find all SoundDecompressors ! */
+ fprintf (stderr, "There are %ld decompressors available\n",
+ CountComponents (&desc));
GST_DEBUG ("There are %ld decompressors available", CountComponents (&desc));
- /* loop over ImageDecoders */
+ /* loop over SoundDecompressors */
do {
componentID = FindNextComponent (componentID, &desc);
@@ -741,8 +897,8 @@ qtwrapper_audio_decoders_register (GstPlugin * plugin)
&info)))
goto next;
- GST_LOG (" name:%s", name);
- GST_LOG (" info:%s", info);
+ GST_LOG (" name:%s", GST_STR_NULL (name));
+ GST_LOG (" info:%s", GST_STR_NULL (info));
GST_LOG (" type:%" GST_FOURCC_FORMAT,
QT_FOURCC_ARGS (thisdesc.componentType));
@@ -794,6 +950,5 @@ qtwrapper_audio_decoders_register (GstPlugin * plugin)
} while (componentID && res);
-beach:
return res;
}
diff --git a/sys/qtwrapper/codecmapping.h b/sys/qtwrapper/codecmapping.h
index 78600b69..946906f4 100644
--- a/sys/qtwrapper/codecmapping.h
+++ b/sys/qtwrapper/codecmapping.h
@@ -42,9 +42,15 @@
* Boston, MA 02111-1307, USA.
*/
-#include <QuickTime/Movies.h>
-#include <QuickTime/ImageCodec.h>
#include <gst/gst.h>
+#include "qtwrapper.h"
+
+#ifdef G_OS_WIN32
+#include <ImageCodec.h>
+#else
+#include <Quicktime/ImageCodec.h>
+#endif
+
/*
* fourcc_to_caps:
diff --git a/sys/qtwrapper/imagedescription.c b/sys/qtwrapper/imagedescription.c
index 7cdf3990..eb52ebfa 100644
--- a/sys/qtwrapper/imagedescription.c
+++ b/sys/qtwrapper/imagedescription.c
@@ -42,16 +42,18 @@
* Boston, MA 02111-1307, USA.
*/
+#include <string.h>
+
#include "imagedescription.h"
static ImageDescription *
image_description_for_avc1 (GstBuffer * buf)
{
ImageDescription *desc = NULL;
- gpointer pos;
+ guint8 *pos;
desc = g_malloc0 (sizeof (ImageDescription) + GST_BUFFER_SIZE (buf) + 8);
- pos = (gpointer) ((gulong) desc + (gulong) sizeof (ImageDescription));
+ pos = (guint8 *) desc + sizeof (ImageDescription);
desc->idSize = sizeof (ImageDescription) + GST_BUFFER_SIZE (buf) + 8;
/* write size in Big-Endian */
@@ -74,7 +76,7 @@ image_description_for_mp4v (GstBuffer * buf)
{
ImageDescription *desc = NULL;
guint32 offset = sizeof (ImageDescription);
- gpointer location;
+ guint8 *location;
GST_LOG ("buf %p , size:%d", buf, GST_BUFFER_SIZE (buf));
@@ -88,7 +90,7 @@ image_description_for_mp4v (GstBuffer * buf)
desc = g_malloc0 (offset + 37 + GST_BUFFER_SIZE (buf));
desc->idSize = offset + 37 + GST_BUFFER_SIZE (buf);
- location = (gpointer) ((gulong) desc + (gulong) offset);
+ location = (guint8 *) desc + offset;
/* Fill in ESDS */
/* size */
@@ -137,8 +139,9 @@ static ImageDescription *
image_description_from_stsd_buffer (GstBuffer * buf)
{
ImageDescription *desc = NULL;
- gpointer content;
- guint size, imds;
+ guint8 *content;
+ guint size;
+ gint imds;
GST_LOG ("buffer %p, size:%u", buf, GST_BUFFER_SIZE (buf));
@@ -171,8 +174,7 @@ image_description_from_stsd_buffer (GstBuffer * buf)
if (desc->idSize > imds) {
GST_LOG ("Copying %d bytes from %p to %p",
size - imds, content + imds, desc + imds);
- memcpy ((gpointer) ((gulong) desc + imds),
- (gpointer) ((gulong) content + imds), size - imds);
+ memcpy ((guint8 *) desc + imds, (guint8 *) content + imds, size - imds);
}
#if DEBUG_DUMP
GST_LOG ("outgoing data in machine-endian");
diff --git a/sys/qtwrapper/imagedescription.h b/sys/qtwrapper/imagedescription.h
index fe5ed9a8..bf1fb436 100644
--- a/sys/qtwrapper/imagedescription.h
+++ b/sys/qtwrapper/imagedescription.h
@@ -46,7 +46,6 @@
#include "config.h"
#endif
-#include <QuickTime/Movies.h>
#include "qtwrapper.h"
#include "qtutils.h"
diff --git a/sys/qtwrapper/qtutils.c b/sys/qtwrapper/qtutils.c
index 441a87d2..b698dc85 100644
--- a/sys/qtwrapper/qtutils.c
+++ b/sys/qtwrapper/qtutils.c
@@ -42,31 +42,39 @@
* Boston, MA 02111-1307, USA.
*/
+#include <string.h>
+
#include "qtutils.h"
gboolean
get_name_info_from_component (Component componentID,
ComponentDescription * desc, gchar ** name, gchar ** info)
{
- gchar *tmp1 = NULL;
- gchar *tmp2 = NULL;
+ Handle nameHandle = NewHandle (200);
+ Handle infoHandle = NewHandle (200);
gchar *tmpname;
gchar *tmpinfo;
OSErr result;
+ gboolean ret = TRUE;
- result = GetComponentInfo (componentID, desc, &tmp1, &tmp2, NULL);
- if (result != noErr)
- return FALSE;
-
+ result = GetComponentInfo (componentID, desc, nameHandle, infoHandle, NULL);
+ if (result != noErr) {
+ ret = FALSE;
+ goto done;
+ }
#if DEBUG_DUMP
GST_LOG ("ComponentDescription dump");
gst_util_dump_mem ((const guchar *) desc, sizeof (ComponentDescription));
+ gst_util_dump_mem ((gpointer) * nameHandle, 200);
+ gst_util_dump_mem ((gpointer) * infoHandle, 200);
+ GST_LOG ("0x%x 0x%x", **((guint8 **) nameHandle), **((guint8 **) infoHandle));
#endif
- if (tmp1 && name) {
+ if (*nameHandle && name) {
gsize read, written;
- tmpname = g_strndup (tmp1 + 1, (guint8) * tmp1);
+ tmpname = g_strndup ((*(char **) nameHandle) + 1,
+ **((guint8 **) nameHandle));
*name = g_convert_with_fallback (tmpname, -1, "ASCII", "MAC",
" ", &read, &written, NULL);
if (!*name)
@@ -75,14 +83,20 @@ get_name_info_from_component (Component componentID,
g_free (tmpname);
}
- if (tmp2 && info) {
- tmpinfo = g_strndup (tmp2 + 1, (guint8) * tmp2);
- *info = g_convert_with_fallback (tmpinfo, -1, "ASCII", "MAC",
- " ", NULL, NULL, NULL);
+ if (*infoHandle && info) {
+ tmpinfo =
+ g_strndup ((*(char **) infoHandle) + 1, **((guint8 **) infoHandle));
+ *info =
+ g_convert_with_fallback (tmpinfo, -1, "ASCII", "MAC", " ", NULL, NULL,
+ NULL);
g_free (tmpinfo);
}
- return TRUE;
+done:
+ DisposeHandle (nameHandle);
+ DisposeHandle (infoHandle);
+
+ return ret;
}
/*
@@ -296,7 +310,7 @@ beach:
}
void
-dump_avcc_atom (gpointer atom)
+dump_avcc_atom (guint8 * atom)
{
/* first 8 bytes : length + atom */
GST_LOG ("version:0x%x", QT_UINT8 (atom + 8));
@@ -331,14 +345,14 @@ dump_image_description (ImageDescription * desc)
GST_LOG ("clutID:%d", desc->clutID);
if (desc->idSize > sizeof (ImageDescription)) {
- gpointer extradata =
- (gpointer) (gulong) desc + (gulong) sizeof (ImageDescription);
+ guint8 *extradata = (guint8 *) desc + sizeof (ImageDescription);
guint32 type = QT_READ_UINT32 (extradata + 4);
GST_LOG ("Extra Data size:%lu",
(gulong) desc->idSize - (gulong) sizeof (ImageDescription));
#if DEBUG_DUMP
- gst_util_dump_mem ((gulong) desc + (gulong) sizeof (ImageDescription),
+ gst_util_dump_mem ((gpointer) (gulong) desc +
+ (gulong) sizeof (ImageDescription),
(gulong) desc->idSize - (gulong) sizeof (ImageDescription));
#endif
GST_LOG ("Extra Data Type : %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (type));
@@ -455,23 +469,18 @@ AudioBufferList *
AllocateAudioBufferList (UInt32 numChannels, UInt32 size)
{
AudioBufferList *list;
- UInt32 i;
- list =
- (AudioBufferList *) calloc (1,
- sizeof (AudioBufferList) + sizeof (AudioBuffer));
+ list = (AudioBufferList *) calloc (1, sizeof (AudioBufferList));
if (list == NULL)
return NULL;
list->mNumberBuffers = 1;
- for (i = 0; i < 1; ++i) {
- list->mBuffers[i].mNumberChannels = numChannels;
- list->mBuffers[i].mDataByteSize = size;
- list->mBuffers[i].mData = malloc (size);
- if (list->mBuffers[i].mData == NULL) {
- DestroyAudioBufferList (list);
- return NULL;
- }
+ list->mBuffers[0].mNumberChannels = numChannels;
+ list->mBuffers[0].mDataByteSize = size;
+ list->mBuffers[0].mData = malloc (size);
+ if (list->mBuffers[0].mData == NULL) {
+ DestroyAudioBufferList (list);
+ return NULL;
}
return list;
}
diff --git a/sys/qtwrapper/qtutils.h b/sys/qtwrapper/qtutils.h
index cb550c85..a8b68aff 100644
--- a/sys/qtwrapper/qtutils.h
+++ b/sys/qtwrapper/qtutils.h
@@ -42,8 +42,11 @@
* Boston, MA 02111-1307, USA.
*/
-#include <QuickTime/Movies.h>
-#include <QuickTime/ImageCodec.h>
+#ifdef G_OS_WIN32
+#include <ImageCodec.h>
+#else
+#include <Quicktime/ImageCodec.h>
+#endif
#include <gst/gst.h>
#include "qtwrapper.h"
diff --git a/sys/qtwrapper/qtwrapper.c b/sys/qtwrapper/qtwrapper.c
index ca4793e5..27e5c163 100644
--- a/sys/qtwrapper/qtwrapper.c
+++ b/sys/qtwrapper/qtwrapper.c
@@ -47,6 +47,7 @@
#endif
#include "qtwrapper.h"
+#include <stdio.h>
GST_DEBUG_CATEGORY (qtwrapper_debug);
@@ -54,11 +55,26 @@ static gboolean
plugin_init (GstPlugin * plugin)
{
gboolean res;
+ OSErr status;
GST_DEBUG_CATEGORY_INIT (qtwrapper_debug, "qtwrapper",
0, "QuickTime codecs wrappers");
+ /* Initialize quicktime environment */
+#ifdef G_OS_WIN32
+ /* Only required on win32 */
+ InitializeQTML (0);
+#endif
+
+ status = EnterMovies ();
+ if (status) {
+ GST_ERROR ("Error initializing QuickTime environment: %d", status);
+ return FALSE;
+ }
+
+ GST_INFO ("Registering video decoders");
res = qtwrapper_video_decoders_register (plugin);
+ GST_INFO ("Registering audio decoders");
res &= qtwrapper_audio_decoders_register (plugin);
return res;
diff --git a/sys/qtwrapper/qtwrapper.h b/sys/qtwrapper/qtwrapper.h
index bba744ba..09081cee 100644
--- a/sys/qtwrapper/qtwrapper.h
+++ b/sys/qtwrapper/qtwrapper.h
@@ -46,6 +46,12 @@
#define __GST_QTWRAPPER_H__
#include <gst/gst.h>
+#ifdef G_OS_WIN32
+#include <Movies.h>
+#include <QTML.h>
+#else
+#include <Quicktime/Movies.h>
+#endif
/* Set following to 1 if you want to have extra debug in form of
* memory dumps */
diff --git a/sys/qtwrapper/videodecoders.c b/sys/qtwrapper/videodecoders.c
index d0b54454..a9c1c884 100644
--- a/sys/qtwrapper/videodecoders.c
+++ b/sys/qtwrapper/videodecoders.c
@@ -46,7 +46,7 @@
#include "config.h"
#endif
-#include <QuickTime/Movies.h>
+#include <string.h>
#include "qtwrapper.h"
#include "codecmapping.h"
@@ -153,14 +153,19 @@ qtwrapper_video_decoder_base_init (QTWrapperVideoDecoderClass * klass)
get_name_info_from_component (params->component, &desc, &name, &info);
/* Fill in details */
- details.longname = g_strdup_printf ("QTWrapper Video Decoder : %s", name);
+ details.longname =
+ g_strdup_printf ("QTWrapper Video Decoder : %s", GST_STR_NULL (name));
details.klass = "Codec/Decoder/Video";
- details.description = info;
- details.author = "Fluendo <gstreamer@fluendo.com>, "
+ details.description =
+ g_strdup_printf ("QTWrapper SCAudio wrapper for decoder: %s",
+ GST_STR_NULL (info));
+ details.author =
+ "Fluendo <gstreamer@fluendo.com>, "
"Pioneers of the Inevitable <songbird@songbirdnest.com>";
gst_element_class_set_details (element_class, &details);
g_free (details.longname);
+ g_free (details.description);
g_free (name);
g_free (info);
@@ -375,7 +380,7 @@ open_decoder (QTWrapperVideoDecoder * qtwrapper, GstCaps * caps,
const GValue *par = NULL;
const GValue *rate = NULL;
const GValue *cdata = NULL;
- OSErr oserr;
+ OSStatus status;
gboolean res = FALSE;
guint32 outformat;
@@ -452,7 +457,7 @@ open_decoder (QTWrapperVideoDecoder * qtwrapper, GstCaps * caps,
cbrecord.decompressionTrackingRefCon = qtwrapper;
/* 6. create decompressionsession */
- oserr = ICMDecompressionSessionCreate (NULL,
+ status = ICMDecompressionSessionCreate (NULL,
qtwrapper->idesc,
sessionoptions, pixelBufferAttributes, &cbrecord, &qtwrapper->decsession);
@@ -460,9 +465,9 @@ open_decoder (QTWrapperVideoDecoder * qtwrapper, GstCaps * caps,
qtwrapper->width = width;
qtwrapper->height = height;
- if (oserr != noErr) {
+ if (status) {
GST_DEBUG_OBJECT (qtwrapper,
- "Error when Calling ICMDecompressionSessionCreate : %d", oserr);
+ "Error when Calling ICMDecompressionSessionCreate : %ld", status);
goto beach;
}
#if G_BYTE_ORDER == G_BIG_ENDIAN
@@ -555,12 +560,13 @@ decompressCb (void *decompressionTrackingRefCon,
if ((decompressionTrackingFlags & kICMDecompressionTracking_EmittingFrame)
&& pixelBuffer) {
- gpointer addr;
+ guint8 *addr;
GstBuffer *outbuf;
- gsize size;
+ size_t size;
+ GstClockTime outtime;
size = CVPixelBufferGetDataSize (pixelBuffer);
- GstClockTime outtime = gst_util_uint64_scale (displayTime, GST_SECOND, 600);
+ outtime = gst_util_uint64_scale (displayTime, GST_SECOND, 600);
GST_LOG ("Got a buffer ready outtime : %" GST_TIME_FORMAT,
GST_TIME_ARGS (outtime));
@@ -580,7 +586,7 @@ decompressCb (void *decompressionTrackingRefCon,
/* allocate buffer */
qtwrapper->lastret =
gst_pad_alloc_buffer (qtwrapper->srcpad, GST_BUFFER_OFFSET_NONE,
- qtwrapper->outsize, GST_PAD_CAPS (qtwrapper->srcpad), &outbuf);
+ (gint) qtwrapper->outsize, GST_PAD_CAPS (qtwrapper->srcpad), &outbuf);
if (G_UNLIKELY (qtwrapper->lastret != GST_FLOW_OK)) {
GST_LOG ("gst_pad_alloc_buffer() returned %s",
gst_flow_get_name (qtwrapper->lastret));
@@ -593,7 +599,8 @@ decompressCb (void *decompressionTrackingRefCon,
if (G_UNLIKELY ((qtwrapper->width * 2) !=
CVPixelBufferGetBytesPerRow (pixelBuffer))) {
guint i;
- gulong stride, realpixels;
+ gulong realpixels;
+ size_t stride;
stride = CVPixelBufferGetBytesPerRow (pixelBuffer);
realpixels = qtwrapper->width * 2;
@@ -604,7 +611,7 @@ decompressCb (void *decompressionTrackingRefCon,
addr + stride * i, realpixels);
} else
- g_memmove (GST_BUFFER_DATA (outbuf), addr, qtwrapper->outsize);
+ g_memmove (GST_BUFFER_DATA (outbuf), addr, (int) qtwrapper->outsize);
/* Release CVPixelBuffer */
CVPixelBufferUnlockBaseAddress (pixelBuffer, 0);
@@ -614,7 +621,7 @@ decompressCb (void *decompressionTrackingRefCon,
gst_buffer_set_caps (outbuf, GST_PAD_CAPS (qtwrapper->srcpad));
GST_BUFFER_TIMESTAMP (outbuf) = qtwrapper->last_ts;
GST_BUFFER_DURATION (outbuf) = qtwrapper->last_duration;
- GST_BUFFER_SIZE (outbuf) = qtwrapper->outsize;
+ GST_BUFFER_SIZE (outbuf) = (int) qtwrapper->outsize;
/* See if we push buffer downstream */
if (G_LIKELY (!qtwrapper->framebuffering)) {
@@ -670,7 +677,7 @@ qtwrapper_video_decoder_chain (GstPad * pad, GstBuffer * buf)
QTWrapperVideoDecoder *qtwrapper;
GstFlowReturn ret = GST_FLOW_OK;
ICMFrameTimeRecord frameTime = { {0} };
- OSErr oserr;
+ OSStatus status;
guint64 intime;
qtwrapper = (QTWrapperVideoDecoder *) gst_pad_get_parent (pad);
@@ -684,28 +691,28 @@ qtwrapper_video_decoder_chain (GstPad * pad, GstBuffer * buf)
frameTime.recordSize = sizeof (ICMFrameTimeRecord);
/* *(TimeValue64 *)&frameTime.value = intime; */
- frameTime.value.lo = intime;
- frameTime.value.hi = 0;
+ frameTime.value.lo = (guint32) (intime & 0xffffffff);
+ frameTime.value.hi = (guint32) (intime >> 32);
frameTime.base = 0;
frameTime.scale = 600;
frameTime.rate = fixed1;
frameTime.duration = 1;
frameTime.flags = icmFrameTimeDecodeImmediately;
/* frameTime.flags = icmFrameTimeIsNonScheduledDisplayTime; */
- frameTime.frameNumber = ++qtwrapper->frameNumber;
+ frameTime.frameNumber = (long) (++qtwrapper->frameNumber);
MAC_LOCK (qtwrapper);
qtwrapper->last_ts = GST_BUFFER_TIMESTAMP (buf);
qtwrapper->last_duration = GST_BUFFER_DURATION (buf);
- oserr = ICMDecompressionSessionDecodeFrame (qtwrapper->decsession,
+ status = ICMDecompressionSessionDecodeFrame (qtwrapper->decsession,
GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf), NULL, &frameTime, buf);
MAC_UNLOCK (qtwrapper);
- if (oserr != noErr) {
- GST_WARNING_OBJECT (qtwrapper, "Error when Calling DecodeFrame() : %d",
- oserr);
+ if (status) {
+ GST_WARNING_OBJECT (qtwrapper, "Error when Calling DecodeFrame() : %ld",
+ status);
ret = GST_FLOW_ERROR;
goto beach;
}
@@ -763,7 +770,6 @@ gboolean
qtwrapper_video_decoders_register (GstPlugin * plugin)
{
gboolean res = TRUE;
- OSErr result;
Component componentID = NULL;
ComponentDescription desc = {
'imdc', 0, 0, 0, 0
@@ -780,14 +786,6 @@ qtwrapper_video_decoders_register (GstPlugin * plugin)
(GInstanceInitFunc) qtwrapper_video_decoder_init,
};
- /* Initialize quicktime environment */
- result = EnterMovies ();
- if (result != noErr) {
- GST_ERROR ("Error initializing QuickTime environment");
- res = FALSE;
- goto beach;
- }
-
/* Find all ImageDecoders ! */
GST_DEBUG ("There are %ld decompressors available", CountComponents (&desc));
@@ -814,8 +812,8 @@ qtwrapper_video_decoders_register (GstPlugin * plugin)
goto next;
}
- GST_LOG (" name:%s", name);
- GST_LOG (" info:%s", info);
+ GST_LOG (" name:%s", GST_STR_NULL (name));
+ GST_LOG (" info:%s", GST_STR_NULL (info));
GST_LOG (" type:%" GST_FOURCC_FORMAT,
QT_FOURCC_ARGS (thisdesc.componentType));
@@ -843,6 +841,7 @@ qtwrapper_video_decoders_register (GstPlugin * plugin)
params->component = componentID;
params->sinkcaps = gst_caps_ref (caps);
+ GST_INFO ("Registering g_type for type_name: %s", type_name);
type = g_type_register_static (GST_TYPE_ELEMENT, type_name, &typeinfo, 0);
/* Store params in type qdata */
g_type_set_qdata (type, QTWRAPPER_VDEC_PARAMS_QDATA, (gpointer) params);
@@ -854,6 +853,8 @@ qtwrapper_video_decoders_register (GstPlugin * plugin)
g_free (params);
res = FALSE;
goto next;
+ } else {
+ GST_LOG ("Reigstered video plugin %s", type_name);
}
next:
@@ -869,6 +870,5 @@ qtwrapper_video_decoders_register (GstPlugin * plugin)
} while (componentID && res);
-beach:
return res;
}