Skip to content

Commit

Permalink
Update ffmpeg.c to work with newer versions of FFmpeg
Browse files Browse the repository at this point in the history
Since ffmpeg 2.0, the macro AVCODEC_MAX_AUDIO_FRAME_SIZE is deprecated
and removed. This commit simply defines the macro if it's not defined
previously, using the same value it used to be in old versions of
libavcodec.

Actually, as my branch has been using swr_convert, where caller specifies
the size of output buffer, even if the current size of 192000 proved to
be not enough in the future, we can simply let swr_convert deal with the
insufficient size by a small modification.

Currently the parameters to swr_convert() still assumes that the size of
192000 samples is always enough for the output buffer.

Signed-off-by: Gregory Petrosyan <gregory.petrosyan@gmail.com>
  • Loading branch information
stonekyx authored and flyingmutant committed Aug 12, 2013
1 parent 6b5d525 commit fb939e5
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 11 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -5,6 +5,7 @@
*.lo
*.so
tags
cscope.out
!.gitignore

# top-level ignores
Expand Down
3 changes: 3 additions & 0 deletions Makefile
Expand Up @@ -18,6 +18,9 @@ include scripts/lib.mk

CFLAGS += -D_FILE_OFFSET_BITS=64

FFMPEG_CFLAGS += $(shell pkg-config --cflags libswresample)
FFMPEG_LIBS += $(shell pkg-config --libs libswresample)

CMUS_LIBS = $(PTHREAD_LIBS) $(NCURSES_LIBS) $(ICONV_LIBS) $(DL_LIBS) $(DISCID_LIBS) $(CUE_LIBS) -lm $(COMPAT_LIBS)

input.o main.o ui_curses.o pulse.lo: .version
Expand Down
84 changes: 73 additions & 11 deletions ffmpeg.c
Expand Up @@ -30,10 +30,16 @@
#include <ffmpeg/avcodec.h>
#include <ffmpeg/avformat.h>
#include <ffmpeg/avio.h>
#include <ffmpeg/swresample.h>
#include <ffmpeg/opt.h>
#include <ffmpeg/audioconvert.h>
#else
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
#include <libswresample/swresample.h>
#include <libavutil/opt.h>
#include <libavutil/audioconvert.h>
#ifndef AVUTIL_MATHEMATICS_H
#include <libavutil/mathematics.h>
#endif
Expand Down Expand Up @@ -63,6 +69,10 @@
#define AVDictionaryEntry AVMetadataTag
#endif

#ifndef AVCODEC_MAX_AUDIO_FRAME_SIZE
#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000
#endif

struct ffmpeg_input {
AVPacket pkt;
int curr_pkt_size;
Expand All @@ -83,6 +93,7 @@ struct ffmpeg_private {
AVCodecContext *codec_context;
AVFormatContext *input_context;
AVCodec *codec;
SwrContext *swr;
int stream_index;

struct ffmpeg_input *input;
Expand Down Expand Up @@ -182,6 +193,7 @@ static int ffmpeg_open(struct input_plugin_data *ip_data)
AVCodec *codec;
AVCodecContext *cc = NULL;
AVFormatContext *ic = NULL;
SwrContext *swr = NULL;

ffmpeg_init();

Expand Down Expand Up @@ -241,20 +253,16 @@ static int ffmpeg_open(struct input_plugin_data *ip_data)
break;
}

#if (LIBAVCODEC_VERSION_INT > ((51<<16)+(64<<8)+0))
if (cc->sample_fmt == AV_SAMPLE_FMT_FLT || cc->sample_fmt == AV_SAMPLE_FMT_DBL) {
#else
if (cc->sample_fmt == AV_SAMPLE_FMT_FLT) {
#endif
err = -IP_ERROR_SAMPLE_FORMAT;
break;
}
/* We assume below that no more errors follow. */
} while (0);

if (err < 0) {
/* Clean up. cc is never opened at this point. (See above assumption.) */
#if (LIBAVCODEC_VERSION_INT < ((53<<16)+(25<<8)+0))
av_close_input_file(ic);
#else
avformat_close_input(&ic);
#endif
return err;
}

Expand All @@ -266,26 +274,43 @@ static int ffmpeg_open(struct input_plugin_data *ip_data)
priv->input = ffmpeg_input_create();
if (priv->input == NULL) {
avcodec_close(cc);
#if (LIBAVCODEC_VERSION_INT < ((53<<16)+(25<<8)+0))
av_close_input_file(ic);
#else
avformat_close_input(&ic);
#endif
free(priv);
return -IP_ERROR_INTERNAL;
}
priv->output = ffmpeg_output_create();

/* Prepare for resampling. */
swr = swr_alloc();
av_opt_set_int(swr, "in_channel_layout", av_get_default_channel_layout(cc->channels), 0);
av_opt_set_int(swr, "out_channel_layout", av_get_default_channel_layout(cc->channels), 0);
av_opt_set_int(swr, "in_sample_rate", cc->sample_rate, 0);
av_opt_set_int(swr, "out_sample_rate", cc->sample_rate, 0);
av_opt_set_sample_fmt(swr, "in_sample_fmt", cc->sample_fmt, 0);
priv->swr = swr;

ip_data->private = priv;
ip_data->sf = sf_rate(cc->sample_rate) | sf_channels(cc->channels);
switch (cc->sample_fmt) {
case AV_SAMPLE_FMT_U8:
ip_data->sf |= sf_bits(8) | sf_signed(0);
av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_U8, 0);
break;
case AV_SAMPLE_FMT_S32:
ip_data->sf |= sf_bits(32) | sf_signed(1);
av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_S32, 0);
break;
/* AV_SAMPLE_FMT_S16 */
default:
ip_data->sf |= sf_bits(16) | sf_signed(1);
av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
break;
}
swr_init(swr);
#ifdef WORDS_BIGENDIAN
ip_data->sf |= sf_bigendian(1);
#endif
Expand All @@ -301,7 +326,12 @@ static int ffmpeg_close(struct input_plugin_data *ip_data)
struct ffmpeg_private *priv = ip_data->private;

avcodec_close(priv->codec_context);
#if (LIBAVCODEC_VERSION_INT < ((53<<16)+(25<<8)+0))
av_close_input_file(priv->input_context);
#else
avformat_close_input(&priv->input_context);
#endif
swr_free(&priv->swr);
ffmpeg_input_free(priv->input);
ffmpeg_output_free(priv->output);
free(priv);
Expand All @@ -314,8 +344,12 @@ static int ffmpeg_close(struct input_plugin_data *ip_data)
* It returns < 0 on error. 0 on EOF.
*/
static int ffmpeg_fill_buffer(AVFormatContext *ic, AVCodecContext *cc, struct ffmpeg_input *input,
struct ffmpeg_output *output)
struct ffmpeg_output *output, SwrContext *swr)
{
#if (LIBAVCODEC_VERSION_INT >= ((53<<16) + (25<<8) + 0))
AVFrame *frame = avcodec_alloc_frame();
int got_frame;
#endif
while (1) {
/* frame_size specifies the size of output->buffer for
* avcodec_decode_audio2. */
Expand All @@ -326,6 +360,9 @@ static int ffmpeg_fill_buffer(AVFormatContext *ic, AVCodecContext *cc, struct ff
av_free_packet(&input->pkt);
if (av_read_frame(ic, &input->pkt) < 0) {
/* Force EOF once we can read no longer. */
#if (LIBAVCODEC_VERSION_INT >= ((53<<16) + (25<<8) + 0))
avcodec_free_frame(&frame);
#endif
return 0;
}
input->curr_pkt_size = input->pkt.size;
Expand All @@ -345,7 +382,7 @@ static int ffmpeg_fill_buffer(AVFormatContext *ic, AVCodecContext *cc, struct ff
#elif (LIBAVCODEC_VERSION_INT <= ((52<<16) + (25<<8) + 0))
len = avcodec_decode_audio2(cc, (int16_t *) output->buffer, &frame_size,
input->curr_pkt_buf, input->curr_pkt_size);
#else
#elif (LIBAVCODEC_VERSION_INT < ((53<<16) + (25<<8) + 0))
{
AVPacket avpkt;
av_init_packet(&avpkt);
Expand All @@ -354,6 +391,14 @@ static int ffmpeg_fill_buffer(AVFormatContext *ic, AVCodecContext *cc, struct ff
len = avcodec_decode_audio3(cc, (int16_t *) output->buffer, &frame_size, &avpkt);
av_free_packet(&avpkt);
}
#else
{
AVPacket avpkt;
av_new_packet(&avpkt, input->curr_pkt_size);
memcpy(avpkt.data, input->curr_pkt_buf, input->curr_pkt_size);
len = avcodec_decode_audio4(cc, frame, &got_frame, &avpkt);
av_free_packet(&avpkt);
}
#endif
if (len < 0) {
/* this is often reached when seeking, not sure why */
Expand All @@ -362,11 +407,27 @@ static int ffmpeg_fill_buffer(AVFormatContext *ic, AVCodecContext *cc, struct ff
}
input->curr_pkt_size -= len;
input->curr_pkt_buf += len;
#if (LIBAVCODEC_VERSION_INT < ((53<<16) + (25<<8) + 0))
if (frame_size > 0) {
output->buffer_pos = output->buffer;
output->buffer_used_len = frame_size;
return frame_size;
}
#else
if (got_frame) {
int res = swr_convert(swr,
&output->buffer,
frame->nb_samples,
(const uint8_t **)frame->extended_data,
frame->nb_samples);
if (res < 0)
res = 0;
output->buffer_pos = output->buffer;
output->buffer_used_len = res * cc->channels * sizeof(int16_t);
avcodec_free_frame(&frame);
return output->buffer_used_len;
}
#endif
}
/* This should never get here. */
return -IP_ERROR_INTERNAL;
Expand All @@ -380,7 +441,8 @@ static int ffmpeg_read(struct input_plugin_data *ip_data, char *buffer, int coun
int out_size;

if (output->buffer_used_len == 0) {
rc = ffmpeg_fill_buffer(priv->input_context, priv->codec_context, priv->input, priv->output);
rc = ffmpeg_fill_buffer(priv->input_context, priv->codec_context,
priv->input, priv->output, priv->swr);
if (rc <= 0) {
return rc;
}
Expand Down

0 comments on commit fb939e5

Please sign in to comment.