summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian@centricular.com>2014-03-11 14:47:04 +0100
committerSebastian Dröge <sebastian@centricular.com>2014-03-11 15:34:46 +0100
commit620da62311f56f22121f0737a87158740b7fa116 (patch)
tree2fc36597748e9c20a26108e873ff42d56701c6ef
parent37b99b347c7c47045e197f5e5a4dba85326d6cb6 (diff)
downloadgstreamer-plugins-bad-620da62311f56f22121f0737a87158740b7fa116.tar.gz
atdec: Implement draining properly
-rw-r--r--sys/applemedia/atdec.c144
-rw-r--r--sys/applemedia/atdec.h2
2 files changed, 90 insertions, 56 deletions
diff --git a/sys/applemedia/atdec.c b/sys/applemedia/atdec.c
index 242137ee1..b1638d371 100644
--- a/sys/applemedia/atdec.c
+++ b/sys/applemedia/atdec.c
@@ -159,6 +159,7 @@ gst_atdec_destroy_queue (GstATDec * atdec, gboolean drain)
AudioQueueDispose (atdec->queue, true);
atdec->queue = NULL;
atdec->output_position = 0;
+ atdec->input_position = 0;
}
void
@@ -181,6 +182,7 @@ gst_atdec_start (GstAudioDecoder * decoder)
GST_DEBUG_OBJECT (atdec, "start");
atdec->output_position = 0;
+ atdec->input_position = 0;
return TRUE;
}
@@ -406,47 +408,21 @@ gst_atdec_buffer_emptied (void *user_data, AudioQueueRef queue,
}
static GstFlowReturn
-gst_atdec_handle_frame (GstAudioDecoder * decoder, GstBuffer * buffer)
+gst_atdec_offline_render (GstATDec * atdec, GstAudioInfo * audio_info)
{
OSStatus status;
AudioTimeStamp timestamp = { 0 };
- AudioStreamPacketDescription packet;
- AudioQueueBufferRef input_buffer, output_buffer;
- GstBuffer *out;
- GstMapInfo info;
- GstAudioInfo *audio_info;
- int size, out_frames;
+ AudioQueueBufferRef output_buffer;
GstFlowReturn flow_ret = GST_FLOW_OK;
- GstATDec *atdec = GST_ATDEC (decoder);
-
- if (buffer == NULL)
- return GST_FLOW_OK;
-
- audio_info = gst_audio_decoder_get_audio_info (decoder);
-
- /* copy the input buffer into an AudioQueueBuffer */
- size = gst_buffer_get_size (buffer);
- status = AudioQueueAllocateBuffer (atdec->queue, size, &input_buffer);
- if (status)
- goto allocate_input_failed;
- gst_buffer_extract (buffer, 0, input_buffer->mAudioData, size);
- input_buffer->mAudioDataByteSize = size;
-
- /* assume framed input */
- packet.mStartOffset = 0;
- packet.mVariableFramesInPacket = 1;
- packet.mDataByteSize = size;
-
- /* enqueue the buffer. It will get free'd once the gst_atdec_buffer_emptied
- * callback is called
- */
- status = AudioQueueEnqueueBuffer (atdec->queue, input_buffer, 1, &packet);
- if (status)
- goto enqueue_buffer_failed;
+ GstBuffer *out;
+ guint out_frames;
/* figure out how many frames we need to pull out of the queue */
- size = atdec->spf * audio_info->bpf;
- AudioQueueAllocateBuffer (atdec->queue, size, &output_buffer);
+ out_frames = atdec->input_position - atdec->output_position;
+ if (out_frames > atdec->spf)
+ out_frames = atdec->spf;
+ status = AudioQueueAllocateBuffer (atdec->queue, out_frames * audio_info->bpf,
+ &output_buffer);
if (status)
goto allocate_output_failed;
@@ -467,36 +443,22 @@ gst_atdec_handle_frame (GstAudioDecoder * decoder, GstBuffer * buffer)
output_buffer->mAudioDataByteSize / audio_info->bpf;
out =
- gst_audio_decoder_allocate_output_buffer (decoder,
+ gst_audio_decoder_allocate_output_buffer (GST_AUDIO_DECODER (atdec),
output_buffer->mAudioDataByteSize);
- gst_buffer_map (out, &info, GST_MAP_WRITE);
- memcpy (info.data, output_buffer->mAudioData,
+ gst_buffer_fill (out, 0, output_buffer->mAudioData,
output_buffer->mAudioDataByteSize);
- gst_buffer_unmap (out, &info);
- flow_ret = gst_audio_decoder_finish_frame (decoder, out, 1);
+ flow_ret =
+ gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (atdec), out, 1);
+ } else {
+ flow_ret = GST_FLOW_CUSTOM_SUCCESS;
}
AudioQueueFreeBuffer (atdec->queue, output_buffer);
return flow_ret;
-allocate_input_failed:
- {
- GST_ELEMENT_ERROR (atdec, STREAM, DECODE, (NULL),
- ("AudioQueueAllocateBuffer returned error: %d", (gint) status));
- return GST_FLOW_ERROR;
- }
-
-enqueue_buffer_failed:
- {
- GST_AUDIO_DECODER_ERROR (atdec, 1, STREAM, DECODE, (NULL),
- ("AudioQueueEnqueueBuffer returned error: %d", (gint) status),
- flow_ret);
- return flow_ret;
- }
-
allocate_output_failed:
{
GST_ELEMENT_ERROR (atdec, STREAM, DECODE, (NULL),
@@ -527,6 +489,77 @@ invalid_buffer_size:
}
}
+static GstFlowReturn
+gst_atdec_handle_frame (GstAudioDecoder * decoder, GstBuffer * buffer)
+{
+ OSStatus status;
+ AudioStreamPacketDescription packet;
+ AudioQueueBufferRef input_buffer;
+ GstAudioInfo *audio_info;
+ int size;
+ GstFlowReturn flow_ret = GST_FLOW_OK;
+ GstATDec *atdec = GST_ATDEC (decoder);
+
+ audio_info = gst_audio_decoder_get_audio_info (decoder);
+
+ if (buffer == NULL) {
+ AudioQueueFlush (atdec->queue);
+
+ while (atdec->input_position > atdec->output_position
+ && flow_ret == GST_FLOW_OK) {
+ flow_ret = gst_atdec_offline_render (atdec, audio_info);
+ }
+
+ if (flow_ret == GST_FLOW_CUSTOM_SUCCESS)
+ flow_ret = GST_FLOW_OK;
+
+ return flow_ret;
+ }
+
+ /* copy the input buffer into an AudioQueueBuffer */
+ size = gst_buffer_get_size (buffer);
+ status = AudioQueueAllocateBuffer (atdec->queue, size, &input_buffer);
+ if (status)
+ goto allocate_input_failed;
+ gst_buffer_extract (buffer, 0, input_buffer->mAudioData, size);
+ input_buffer->mAudioDataByteSize = size;
+
+ /* assume framed input */
+ packet.mStartOffset = 0;
+ packet.mVariableFramesInPacket = 1;
+ packet.mDataByteSize = size;
+
+ /* enqueue the buffer. It will get free'd once the gst_atdec_buffer_emptied
+ * callback is called
+ */
+ status = AudioQueueEnqueueBuffer (atdec->queue, input_buffer, 1, &packet);
+ if (status)
+ goto enqueue_buffer_failed;
+
+ atdec->input_position += atdec->spf;
+
+ flow_ret = gst_atdec_offline_render (atdec, audio_info);
+ if (flow_ret == GST_FLOW_CUSTOM_SUCCESS)
+ flow_ret = GST_FLOW_OK;
+
+ return flow_ret;
+
+allocate_input_failed:
+ {
+ GST_ELEMENT_ERROR (atdec, STREAM, DECODE, (NULL),
+ ("AudioQueueAllocateBuffer returned error: %d", (gint) status));
+ return GST_FLOW_ERROR;
+ }
+
+enqueue_buffer_failed:
+ {
+ GST_AUDIO_DECODER_ERROR (atdec, 1, STREAM, DECODE, (NULL),
+ ("AudioQueueEnqueueBuffer returned error: %d", (gint) status),
+ flow_ret);
+ return flow_ret;
+ }
+}
+
static void
gst_atdec_flush (GstAudioDecoder * decoder, gboolean hard)
{
@@ -534,4 +567,5 @@ gst_atdec_flush (GstAudioDecoder * decoder, gboolean hard)
AudioQueueReset (atdec->queue);
atdec->output_position = 0;
+ atdec->input_position = 0;
}
diff --git a/sys/applemedia/atdec.h b/sys/applemedia/atdec.h
index ef8829419..7f8310c3a 100644
--- a/sys/applemedia/atdec.h
+++ b/sys/applemedia/atdec.h
@@ -39,7 +39,7 @@ struct _GstATDec
GstAudioDecoder decoder;
AudioQueueRef queue;
gint spf;
- guint64 output_position;
+ guint64 input_position, output_position;
};
struct _GstATDecClass