aboutsummaryrefslogtreecommitdiff
path: root/src/decoder/libav_decoder_plugin.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/decoder/libav_decoder_plugin.c')
-rw-r--r--src/decoder/libav_decoder_plugin.c93
1 files changed, 22 insertions, 71 deletions
diff --git a/src/decoder/libav_decoder_plugin.c b/src/decoder/libav_decoder_plugin.c
index 88dd4a8f..05b9b2fb 100644
--- a/src/decoder/libav_decoder_plugin.c
+++ b/src/decoder/libav_decoder_plugin.c
@@ -41,6 +41,7 @@
#include <libavutil/log.h>
#include <libavutil/mathematics.h>
#include <libavutil/dict.h>
+#include <libavutil/opt.h>
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "libav"
@@ -159,40 +160,6 @@ static int64_t time_to_libav(double t, const AVRational time_base)
return av_rescale_q((int64_t)(t * 1024), (AVRational){1, 1024}, time_base);
}
-/**
- * Copy PCM data from a AVFrame to an interleaved buffer.
- */
-static int copy_interleave_frame(const AVCodecContext *codec_context,
- const AVFrame *frame,
- uint8_t *buffer, size_t buffer_size)
-{
- int plane_size;
- const int data_size =
- av_samples_get_buffer_size(&plane_size,
- codec_context->channels,
- frame->nb_samples,
- codec_context->sample_fmt, 1);
- uint16_t *dst = (uint16_t*)buffer;
-
- if (buffer_size < (size_t)data_size)
- /* buffer is too small - shouldn't happen */
- return AVERROR(EINVAL);
-
- if (av_sample_fmt_is_planar(codec_context->sample_fmt) &&
- codec_context->channels > 1) {
- for (int i = 0; i < frame->nb_samples; i++) {
- for (int j = 0; j < codec_context->channels; j++)
- dst[i * codec_context->channels + j] = ((uint16_t*)frame->extended_data[j])[i];
- }
- } else {
- memcpy(buffer, frame->extended_data[0], data_size);
- }
-
- return data_size;
-}
-
-#define AVCODEC_MAX_AUDIO_FRAME_SIZE 50000
-
static enum decoder_command libav_send_packet(struct decoder *decoder,
struct input_stream *is,
const AVPacket *packet,
@@ -200,9 +167,6 @@ static enum decoder_command libav_send_packet(struct decoder *decoder,
const AVRational *time_base)
{
AVPacket packet2 = *packet;
- uint8_t aligned_buffer[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2 + 16];
- const size_t buffer_size = sizeof(aligned_buffer);
-
enum decoder_command cmd = DECODE_COMMAND_NONE;
if (packet->pts != (int64_t)AV_NOPTS_VALUE)
@@ -210,37 +174,31 @@ static enum decoder_command libav_send_packet(struct decoder *decoder,
while (packet2.size > 0 &&
cmd == DECODE_COMMAND_NONE) {
- int audio_size = buffer_size;
- AVFrame frame;
+ AVFrame *frame = av_frame_alloc();
int got_frame = 0;
- int len = avcodec_decode_audio4(codec_context,
- &frame, &got_frame,
- &packet2);
- if (len >= 0 && got_frame) {
- audio_size = copy_interleave_frame(codec_context,
- &frame,
- aligned_buffer,
- buffer_size);
- if (audio_size < 0)
- len = audio_size;
- } else if (len >= 0)
- len = -1;
-
- if (len < 0) {
- /* if error, we skip the frame */
+ int ret;
+
+ if (!frame) {
+ g_warning("Error allocating a frame for decoding.\n");
+ break;
+ }
+
+ ret = avcodec_decode_audio4(codec_context, frame, &got_frame, &packet2);
+ if (ret < 0) {
g_message("decoding failed, frame skipped\n");
break;
}
- packet2.data += len;
- packet2.size -= len;
+ packet2.data += ret;
+ packet2.size -= ret;
- if (audio_size <= 0)
+ if (!got_frame) {
+ if (!ret)
+ break;
continue;
+ }
- cmd = decoder_data(decoder, is,
- aligned_buffer, audio_size,
- codec_context->bit_rate / 1000);
+ cmd = decoder_data(decoder, is, frame, codec_context->bit_rate / 1000);
}
return cmd;
}
@@ -248,17 +206,9 @@ static enum decoder_command libav_send_packet(struct decoder *decoder,
static enum sample_format libav_sample_format(const AVCodecContext *codec_context)
{
switch (codec_context->sample_fmt) {
- case AV_SAMPLE_FMT_S16:
- case AV_SAMPLE_FMT_S16P:
- return SAMPLE_FORMAT_S16;
-
- case AV_SAMPLE_FMT_S32:
- return SAMPLE_FORMAT_S32;
-
- default:
- g_warning("Unsupported libavcodec SampleFormat value: %d",
- codec_context->sample_fmt);
- return SAMPLE_FORMAT_UNDEFINED;
+ case AV_SAMPLE_FMT_S16: return SAMPLE_FORMAT_S16;
+ case AV_SAMPLE_FMT_S32: return SAMPLE_FORMAT_S32;
+ default: return SAMPLE_FORMAT_UNDEFINED;
}
}
@@ -298,6 +248,7 @@ static void libav_decode(struct decoder *decoder, struct input_stream *input)
values into AVCodecContext.channels - a change that will be
reverted later by avcodec_decode_audio3() */
+ av_opt_set_int(dec, "refcounted_frames", 1, 0);
ret = avcodec_open2(dec, codec, NULL);
if (ret < 0) {
g_warning("Could not open codec\n");