mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-02 08:42:32 +00:00
atdec: Implement draining properly
This commit is contained in:
parent
53ab9c6613
commit
fa8a7d7659
2 changed files with 90 additions and 56 deletions
|
@ -159,6 +159,7 @@ gst_atdec_destroy_queue (GstATDec * atdec, gboolean drain)
|
||||||
AudioQueueDispose (atdec->queue, true);
|
AudioQueueDispose (atdec->queue, true);
|
||||||
atdec->queue = NULL;
|
atdec->queue = NULL;
|
||||||
atdec->output_position = 0;
|
atdec->output_position = 0;
|
||||||
|
atdec->input_position = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -181,6 +182,7 @@ gst_atdec_start (GstAudioDecoder * decoder)
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (atdec, "start");
|
GST_DEBUG_OBJECT (atdec, "start");
|
||||||
atdec->output_position = 0;
|
atdec->output_position = 0;
|
||||||
|
atdec->input_position = 0;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -406,47 +408,21 @@ gst_atdec_buffer_emptied (void *user_data, AudioQueueRef queue,
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_atdec_handle_frame (GstAudioDecoder * decoder, GstBuffer * buffer)
|
gst_atdec_offline_render (GstATDec * atdec, GstAudioInfo * audio_info)
|
||||||
{
|
{
|
||||||
OSStatus status;
|
OSStatus status;
|
||||||
AudioTimeStamp timestamp = { 0 };
|
AudioTimeStamp timestamp = { 0 };
|
||||||
AudioStreamPacketDescription packet;
|
AudioQueueBufferRef output_buffer;
|
||||||
AudioQueueBufferRef input_buffer, output_buffer;
|
|
||||||
GstBuffer *out;
|
|
||||||
GstMapInfo info;
|
|
||||||
GstAudioInfo *audio_info;
|
|
||||||
int size, out_frames;
|
|
||||||
GstFlowReturn flow_ret = GST_FLOW_OK;
|
GstFlowReturn flow_ret = GST_FLOW_OK;
|
||||||
GstATDec *atdec = GST_ATDEC (decoder);
|
GstBuffer *out;
|
||||||
|
guint out_frames;
|
||||||
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;
|
|
||||||
|
|
||||||
/* figure out how many frames we need to pull out of the queue */
|
/* figure out how many frames we need to pull out of the queue */
|
||||||
size = atdec->spf * audio_info->bpf;
|
out_frames = atdec->input_position - atdec->output_position;
|
||||||
AudioQueueAllocateBuffer (atdec->queue, size, &output_buffer);
|
if (out_frames > atdec->spf)
|
||||||
|
out_frames = atdec->spf;
|
||||||
|
status = AudioQueueAllocateBuffer (atdec->queue, out_frames * audio_info->bpf,
|
||||||
|
&output_buffer);
|
||||||
if (status)
|
if (status)
|
||||||
goto allocate_output_failed;
|
goto allocate_output_failed;
|
||||||
|
|
||||||
|
@ -467,36 +443,22 @@ gst_atdec_handle_frame (GstAudioDecoder * decoder, GstBuffer * buffer)
|
||||||
output_buffer->mAudioDataByteSize / audio_info->bpf;
|
output_buffer->mAudioDataByteSize / audio_info->bpf;
|
||||||
|
|
||||||
out =
|
out =
|
||||||
gst_audio_decoder_allocate_output_buffer (decoder,
|
gst_audio_decoder_allocate_output_buffer (GST_AUDIO_DECODER (atdec),
|
||||||
output_buffer->mAudioDataByteSize);
|
output_buffer->mAudioDataByteSize);
|
||||||
|
|
||||||
gst_buffer_map (out, &info, GST_MAP_WRITE);
|
gst_buffer_fill (out, 0, output_buffer->mAudioData,
|
||||||
memcpy (info.data, output_buffer->mAudioData,
|
|
||||||
output_buffer->mAudioDataByteSize);
|
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);
|
AudioQueueFreeBuffer (atdec->queue, output_buffer);
|
||||||
|
|
||||||
return flow_ret;
|
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:
|
allocate_output_failed:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_ERROR (atdec, STREAM, DECODE, (NULL),
|
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
|
static void
|
||||||
gst_atdec_flush (GstAudioDecoder * decoder, gboolean hard)
|
gst_atdec_flush (GstAudioDecoder * decoder, gboolean hard)
|
||||||
{
|
{
|
||||||
|
@ -534,4 +567,5 @@ gst_atdec_flush (GstAudioDecoder * decoder, gboolean hard)
|
||||||
|
|
||||||
AudioQueueReset (atdec->queue);
|
AudioQueueReset (atdec->queue);
|
||||||
atdec->output_position = 0;
|
atdec->output_position = 0;
|
||||||
|
atdec->input_position = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ struct _GstATDec
|
||||||
GstAudioDecoder decoder;
|
GstAudioDecoder decoder;
|
||||||
AudioQueueRef queue;
|
AudioQueueRef queue;
|
||||||
gint spf;
|
gint spf;
|
||||||
guint64 output_position;
|
guint64 input_position, output_position;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstATDecClass
|
struct _GstATDecClass
|
||||||
|
|
Loading…
Reference in a new issue