Use avcodec_decode_audio4

This commit is contained in:
Alexander Kojevnikov 2013-02-10 20:40:29 -08:00
parent 69d400e34c
commit b1b102044e
3 changed files with 50 additions and 44 deletions

View File

@ -32,7 +32,7 @@ AC_MSG_RESULT([$os])
AC_CHECK_LIB(m, log10) AC_CHECK_LIB(m, log10)
PKG_CHECK_MODULES(FFMPEG, [libavformat >= 52.111 libavcodec >= 52.123 libavutil]) PKG_CHECK_MODULES(FFMPEG, [libavformat >= 54.2 libavcodec >= 53.25 libavutil >= 51.18])
AM_OPTIONS_WXCONFIG AM_OPTIONS_WXCONFIG
reqwx=2.8.0 reqwx=2.8.0

View File

@ -1,6 +1,6 @@
/* spek-audio.cc /* spek-audio.cc
* *
* Copyright (C) 2010-2012 Alexander Kojevnikov <alexander@kojevnikov.com> * Copyright (C) 2010-2013 Alexander Kojevnikov <alexander@kojevnikov.com>
* *
* Spek is free software: you can redistribute it and/or modify * Spek is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -35,8 +35,10 @@ struct spek_audio_context
AVStream *stream; AVStream *stream;
AVCodec *codec; AVCodec *codec;
int buffer_size; int buffer_size;
AVPacket *packet; AVPacket packet;
int offset; int offset;
int is_planar;
AVFrame *frame;
struct spek_audio_properties properties; struct spek_audio_properties properties;
}; };
@ -44,7 +46,6 @@ struct spek_audio_context
void spek_audio_init() void spek_audio_init()
{ {
// TODO: register only audio decoders.
av_register_all(); av_register_all();
} }
@ -114,31 +115,29 @@ struct spek_audio_context * spek_audio_open(const char *path)
cx->properties.error = SPEK_AUDIO_CANNOT_OPEN_DECODER; cx->properties.error = SPEK_AUDIO_CANNOT_OPEN_DECODER;
return cx; return cx;
} }
cx->is_planar = av_sample_fmt_is_planar(cx->codec_context->sample_fmt);
cx->properties.width = 8 * av_get_bytes_per_sample(cx->codec_context->sample_fmt);
switch (cx->codec_context->sample_fmt) { switch (cx->codec_context->sample_fmt) {
case AV_SAMPLE_FMT_S16: case AV_SAMPLE_FMT_S16:
cx->properties.width = 16; case AV_SAMPLE_FMT_S16P:
cx->properties.fp = false;
break;
case AV_SAMPLE_FMT_S32: case AV_SAMPLE_FMT_S32:
cx->properties.width = 32; case AV_SAMPLE_FMT_S32P:
cx->properties.fp = false; cx->properties.fp = false;
break; break;
case AV_SAMPLE_FMT_FLT: case AV_SAMPLE_FMT_FLT:
cx->properties.width = 32; case AV_SAMPLE_FMT_FLTP:
cx->properties.fp = true;
break;
case AV_SAMPLE_FMT_DBL: case AV_SAMPLE_FMT_DBL:
cx->properties.width = 64; case AV_SAMPLE_FMT_DBLP:
cx->properties.fp = true; cx->properties.fp = true;
break; break;
default: default:
cx->properties.error = SPEK_AUDIO_BAD_SAMPLE_FORMAT; cx->properties.error = SPEK_AUDIO_BAD_SAMPLE_FORMAT;
return cx; return cx;
} }
cx->buffer_size = (AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2; cx->buffer_size = 0;
cx->properties.buffer = (uint8_t*)av_malloc(cx->buffer_size); cx->properties.buffer = NULL;
cx->packet = (AVPacket*)av_mallocz(sizeof(AVPacket)); av_init_packet(&cx->packet);
av_init_packet(cx->packet); cx->frame = avcodec_alloc_frame();
cx->offset = 0; cx->offset = 0;
return cx; return cx;
} }
@ -160,38 +159,45 @@ int spek_audio_read(struct spek_audio_context *cx) {
} }
for (;;) { for (;;) {
while (cx->packet->size > 0) { while (cx->packet.size > 0) {
int buffer_size = cx->buffer_size; avcodec_get_frame_defaults(cx->frame);
int len = avcodec_decode_audio3( int got_frame = 0;
cx->codec_context, (int16_t *)cx->properties.buffer, &buffer_size, cx->packet); int len = avcodec_decode_audio4(cx->codec_context, cx->frame, &got_frame, &cx->packet);
if (len < 0) { if (len < 0) {
// Error, skip the frame. // Error, skip the frame.
cx->packet->size = 0;
break; break;
} }
cx->packet->data += len; cx->packet.data += len;
cx->packet->size -= len; cx->packet.size -= len;
cx->offset += len; cx->offset += len;
if (buffer_size <= 0) { if (!got_frame) {
// No data yet, get more frames. // No data yet, get more frames.
continue; continue;
} }
// We have data, return it and come back for more later. // We have data, return it and come back for more later.
int buffer_size =
cx->frame->nb_samples * cx->properties.channels *
(cx->properties.width / 8);
if (buffer_size > cx->buffer_size) {
cx->properties.buffer = (uint8_t*)av_realloc(cx->properties.buffer, buffer_size);
cx->buffer_size = buffer_size;
}
memcpy(cx->properties.buffer, cx->frame->data[0], buffer_size);
return buffer_size; return buffer_size;
} }
if (cx->packet->data) { if (cx->packet.data) {
cx->packet->data -= cx->offset; cx->packet.data -= cx->offset;
cx->packet->size += cx->offset; cx->packet.size += cx->offset;
cx->offset = 0; cx->offset = 0;
av_free_packet (cx->packet); av_free_packet (&cx->packet);
} }
int res = 0; int res = 0;
while ((res = av_read_frame(cx->format_context, cx->packet)) >= 0) { while ((res = av_read_frame(cx->format_context, &cx->packet)) >= 0) {
if (cx->packet->stream_index == cx->audio_stream) { if (cx->packet.stream_index == cx->audio_stream) {
break; break;
} }
av_free_packet(cx->packet); av_free_packet(&cx->packet);
} }
if (res < 0) { if (res < 0) {
// End of file or error. // End of file or error.
@ -205,23 +211,23 @@ void spek_audio_close(struct spek_audio_context *cx)
if (cx->properties.codec_name != NULL) { if (cx->properties.codec_name != NULL) {
free(cx->properties.codec_name); free(cx->properties.codec_name);
} }
if (cx->frame != NULL) {
avcodec_free_frame(&cx->frame);
}
if (cx->packet.data) {
cx->packet.data -= cx->offset;
cx->packet.size += cx->offset;
cx->offset = 0;
av_free_packet(&cx->packet);
}
if (cx->properties.buffer) { if (cx->properties.buffer) {
av_free(cx->properties.buffer); av_free(cx->properties.buffer);
} }
if (cx->packet) {
if (cx->packet->data) {
cx->packet->data -= cx->offset;
cx->packet->size += cx->offset;
cx->offset = 0;
av_free_packet(cx->packet);
}
av_free(cx->packet);
}
if (cx->codec_context != NULL) { if (cx->codec_context != NULL) {
avcodec_close(cx->codec_context); avcodec_close(cx->codec_context);
} }
if (cx->format_context != NULL) { if (cx->format_context != NULL) {
av_close_input_file(cx->format_context); avformat_close_input(&cx->format_context);
} }
free(cx); free(cx);
} }

View File

@ -1,6 +1,6 @@
/* spek-audio.h /* spek-audio.h
* *
* Copyright (C) 2010-2012 Alexander Kojevnikov <alexander@kojevnikov.com> * Copyright (C) 2010-2013 Alexander Kojevnikov <alexander@kojevnikov.com>
* *
* Spek is free software: you can redistribute it and/or modify * Spek is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -19,8 +19,8 @@
#ifndef SPEK_AUDIO_H_ #ifndef SPEK_AUDIO_H_
#define SPEK_AUDIO_H_ #define SPEK_AUDIO_H_
#include <stdbool.h> #include <tr1/cstdint>
#include <stdint.h> #include <string>
struct spek_audio_context; struct spek_audio_context;