252 lines
8.1 KiB
Diff
252 lines
8.1 KiB
Diff
commit fb939e5238c128ae1837430cbf838b945d4c99a9
|
|
Author: Stone Kang <stonekyx@gmail.com>
|
|
Date: Sun Jul 28 19:42:16 2013 +0800
|
|
|
|
Update ffmpeg.c to work with newer versions of FFmpeg
|
|
|
|
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>
|
|
|
|
diff --git a/Makefile b/Makefile
|
|
index 826ac51..5e3f491 100644
|
|
--- Makefile
|
|
+++ Makefile
|
|
@@ -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
|
|
diff --git a/ffmpeg.c b/ffmpeg.c
|
|
index 93c1831..e4da4df 100644
|
|
--- ffmpeg.c
|
|
+++ ffmpeg.c
|
|
@@ -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
|
|
@@ -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;
|
|
@@ -83,6 +93,7 @@ struct ffmpeg_private {
|
|
AVCodecContext *codec_context;
|
|
AVFormatContext *input_context;
|
|
AVCodec *codec;
|
|
+ SwrContext *swr;
|
|
int stream_index;
|
|
|
|
struct ffmpeg_input *input;
|
|
@@ -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();
|
|
|
|
@@ -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;
|
|
}
|
|
|
|
@@ -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
|
|
@@ -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);
|
|
@@ -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. */
|
|
@@ -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;
|
|
@@ -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);
|
|
@@ -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 */
|
|
@@ -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;
|
|
@@ -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;
|
|
}
|