mirror of https://github.com/mgba-emu/mgba.git
FFmpeg: Support libswresample (fixes #1120)
This commit is contained in:
parent
7876ae861b
commit
0933bca85d
2
CHANGES
2
CHANGES
|
@ -9,6 +9,8 @@ Bugfixes:
|
||||||
- GBA Serialize: Fix loading channel 3 volume (fixes mgba.io/i/1107)
|
- GBA Serialize: Fix loading channel 3 volume (fixes mgba.io/i/1107)
|
||||||
- GBA BIOS: Fix BitUnPack final byte
|
- GBA BIOS: Fix BitUnPack final byte
|
||||||
- GB I/O: DMA register is R/W
|
- GB I/O: DMA register is R/W
|
||||||
|
Misc:
|
||||||
|
- FFmpeg: Support libswresample (fixes mgba.io/i/1120, mgba.io/b/123)
|
||||||
|
|
||||||
0.6.3: (2017-04-14)
|
0.6.3: (2017-04-14)
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
|
|
|
@ -431,7 +431,7 @@ set(WANT_LIBZIP ${USE_LIBZIP})
|
||||||
set(WANT_SQLITE3 ${USE_SQLITE3})
|
set(WANT_SQLITE3 ${USE_SQLITE3})
|
||||||
set(USE_CMOCKA ${BUILD_SUITE})
|
set(USE_CMOCKA ${BUILD_SUITE})
|
||||||
|
|
||||||
find_feature(USE_FFMPEG "libavcodec;libavformat;libavresample;libavutil;libswscale")
|
find_feature(USE_FFMPEG "libavcodec;libavformat;libavutil;libswscale")
|
||||||
find_feature(USE_ZLIB "ZLIB")
|
find_feature(USE_ZLIB "ZLIB")
|
||||||
find_feature(USE_MINIZIP "minizip")
|
find_feature(USE_MINIZIP "minizip")
|
||||||
find_feature(USE_PNG "PNG")
|
find_feature(USE_PNG "PNG")
|
||||||
|
@ -441,6 +441,13 @@ find_feature(USE_EPOXY "epoxy")
|
||||||
find_feature(USE_CMOCKA "cmocka")
|
find_feature(USE_CMOCKA "cmocka")
|
||||||
find_feature(USE_SQLITE3 "sqlite3")
|
find_feature(USE_SQLITE3 "sqlite3")
|
||||||
|
|
||||||
|
if(USE_FFMPEG)
|
||||||
|
set(USE_LIBAVRESAMPLE ON)
|
||||||
|
set(USE_LIBSWRESAMPLE ON)
|
||||||
|
find_feature(USE_LIBAVRESAMPLE "libavresample")
|
||||||
|
find_feature(USE_LIBSWRESAMPLE "libswresample")
|
||||||
|
endif()
|
||||||
|
|
||||||
# Features
|
# Features
|
||||||
set(DEBUGGER_SRC
|
set(DEBUGGER_SRC
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/debugger/debugger.c
|
${CMAKE_CURRENT_SOURCE_DIR}/src/debugger/debugger.c
|
||||||
|
@ -474,22 +481,30 @@ source_group("Debugger" FILES ${DEBUGGER_SRC})
|
||||||
|
|
||||||
if(USE_FFMPEG)
|
if(USE_FFMPEG)
|
||||||
list(APPEND FEATURES FFMPEG)
|
list(APPEND FEATURES FFMPEG)
|
||||||
pkg_search_module(LIBSWRESAMPLE QUIET libswresample)
|
if(USE_LIBSWRESAMPLE)
|
||||||
if(NOT LIBSWRESAMPLE_FOUND)
|
list(APPEND FEATURES LIBSWRESAMPLE)
|
||||||
|
else()
|
||||||
|
list(APPEND FEATURES LIBAVRESAMPLE)
|
||||||
list(APPEND FEATURES LIBAV)
|
list(APPEND FEATURES LIBAV)
|
||||||
endif()
|
endif()
|
||||||
include_directories(AFTER ${LIBAVCODEC_INCLUDE_DIRS} ${LIBAVFORMAT_INCLUDE_DIRS} ${LIBAVRESAMPLE_INCLUDE_DIRS} ${LIBAVUTIL_INCLUDE_DIRS} ${LIBSWSCALE_INCLUDE_DIRS})
|
include_directories(AFTER ${LIBAVCODEC_INCLUDE_DIRS} ${LIBAVFORMAT_INCLUDE_DIRS} ${LIBAVRESAMPLE_INCLUDE_DIRS} ${LIBAVUTIL_INCLUDE_DIRS} ${LIBSWRESAMPLE_INCLUDE_DIRS} ${LIBSWSCALE_INCLUDE_DIRS})
|
||||||
link_directories(${LIBAVCODEC_LIBRARY_DIRS} ${LIBAVFORMAT_LIBRARY_DIRS} ${LIBAVRESAMPLE_LIBRARY_DIRS} ${LIBAVUTIL_LIBRARY_DIRS} ${LIBSWSCALE_LIBRARY_DIRS})
|
link_directories(${LIBAVCODEC_LIBRARY_DIRS} ${LIBAVFORMAT_LIBRARY_DIRS} ${LIBAVRESAMPLE_LIBRARY_DIRS} ${LIBAVUTIL_LIBRARY_DIRS} ${LIBSWRESAMPLE_LIBRARY_DIRS} ${LIBSWSCALE_LIBRARY_DIRS})
|
||||||
list(APPEND FEATURE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/feature/ffmpeg/ffmpeg-encoder.c")
|
list(APPEND FEATURE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/feature/ffmpeg/ffmpeg-encoder.c")
|
||||||
string(REGEX MATCH "^[0-9]+" LIBAVCODEC_VERSION_MAJOR ${libavcodec_VERSION})
|
string(REGEX MATCH "^[0-9]+" LIBAVCODEC_VERSION_MAJOR ${libavcodec_VERSION})
|
||||||
string(REGEX MATCH "^[0-9]+" LIBAVFORMAT_VERSION_MAJOR ${libavformat_VERSION})
|
string(REGEX MATCH "^[0-9]+" LIBAVFORMAT_VERSION_MAJOR ${libavformat_VERSION})
|
||||||
string(REGEX MATCH "^[0-9]+" LIBAVRESAMPLE_VERSION_MAJOR ${libavresample_VERSION})
|
|
||||||
string(REGEX MATCH "^[0-9]+" LIBAVUTIL_VERSION_MAJOR ${libavutil_VERSION})
|
string(REGEX MATCH "^[0-9]+" LIBAVUTIL_VERSION_MAJOR ${libavutil_VERSION})
|
||||||
string(REGEX MATCH "^[0-9]+" LIBSWSCALE_VERSION_MAJOR ${libswscale_VERSION})
|
string(REGEX MATCH "^[0-9]+" LIBSWSCALE_VERSION_MAJOR ${libswscale_VERSION})
|
||||||
list(APPEND DEPENDENCY_LIB ${LIBAVCODEC_LIBRARIES} ${LIBAVFORMAT_LIBRARIES} ${LIBAVRESAMPLE_LIBRARIES} ${LIBAVUTIL_LIBRARIES} ${LIBSWSCALE_LIBRARIES})
|
list(APPEND DEPENDENCY_LIB ${LIBAVCODEC_LIBRARIES} ${LIBAVFORMAT_LIBRARIES} ${LIBAVRESAMPLE_LIBRARIES} ${LIBAVUTIL_LIBRARIES} ${LIBSWSCALE_LIBRARIES} ${LIBSWRESAMPLE_LIBRARIES})
|
||||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavcodec${LIBAVCODEC_VERSION_MAJOR}|libavcodec-extra-${LIBAVCODEC_VERSION_MAJOR}|libavcodec-ffmpeg${LIBAVCODEC_VERSION_MAJOR}|libavcodec-ffmpeg-extra${LIBAVCODEC_VERSION_MAJOR}")
|
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavcodec${LIBAVCODEC_VERSION_MAJOR}|libavcodec-extra-${LIBAVCODEC_VERSION_MAJOR}|libavcodec-ffmpeg${LIBAVCODEC_VERSION_MAJOR}|libavcodec-ffmpeg-extra${LIBAVCODEC_VERSION_MAJOR}")
|
||||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavformat${LIBAVFORMAT_VERSION_MAJOR}|libavformat-ffmpeg${LIBAVFORMAT_VERSION_MAJOR}")
|
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavformat${LIBAVFORMAT_VERSION_MAJOR}|libavformat-ffmpeg${LIBAVFORMAT_VERSION_MAJOR}")
|
||||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavresample${LIBAVRESAMPLE_VERSION_MAJOR}|libavresample-ffmpeg${LIBAVRESAMPLE_VERSION_MAJOR}")
|
if(USE_LIBSWRESAMPLE)
|
||||||
|
string(REGEX MATCH "^[0-9]+" LIBSWRESAMPLE_VERSION_MAJOR ${libswresample_VERSION})
|
||||||
|
math(EXPR LIBSWRESAMPLE_VERSION_DEBIAN "${LIBSWRESAMPLE_VERSION_MAJOR} - 1")
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libswresample${LIBSWRESAMPLE_VERSION_DEBIAN}|libswresample-ffmpeg${LIBSWRESAMPLE_VERSION_DEBIAN}")
|
||||||
|
else()
|
||||||
|
string(REGEX MATCH "^[0-9]+" LIBAVRESAMPLE_VERSION_MAJOR ${libavresample_VERSION})
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavresample${LIBAVRESAMPLE_VERSION_MAJOR}|libavresample-ffmpeg${LIBAVRESAMPLE_VERSION_MAJOR}")
|
||||||
|
endif()
|
||||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavutil${LIBAVUTIL_VERSION_MAJOR}|libavutil-ffmpeg${LIBAVUTIL_VERSION_MAJOR}")
|
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavutil${LIBAVUTIL_VERSION_MAJOR}|libavutil-ffmpeg${LIBAVUTIL_VERSION_MAJOR}")
|
||||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libswscale${LIBSWSCALE_VERSION_MAJOR}|libswscale-ffmpeg${LIBSWSCALE_VERSION_MAJOR}")
|
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libswscale${LIBSWSCALE_VERSION_MAJOR}|libswscale-ffmpeg${LIBSWSCALE_VERSION_MAJOR}")
|
||||||
set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "libavcodec-extra|libavcodec-ffmpeg-extra${LIBAVCODEC_VERSION_MAJOR}")
|
set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "libavcodec-extra|libavcodec-ffmpeg-extra${LIBAVCODEC_VERSION_MAJOR}")
|
||||||
|
|
|
@ -63,6 +63,14 @@
|
||||||
#cmakedefine USE_LIBAV
|
#cmakedefine USE_LIBAV
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef USE_LIBAVRESAMPLE
|
||||||
|
#cmakedefine USE_LIBAVRESAMPLE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef USE_LIBSWRESAMPLE
|
||||||
|
#cmakedefine USE_LIBSWRESAMPLE
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef USE_LIBZIP
|
#ifndef USE_LIBZIP
|
||||||
#cmakedefine USE_LIBZIP
|
#cmakedefine USE_LIBZIP
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -19,7 +19,11 @@
|
||||||
#include <libavutil/mathematics.h>
|
#include <libavutil/mathematics.h>
|
||||||
#include <libavutil/opt.h>
|
#include <libavutil/opt.h>
|
||||||
|
|
||||||
|
#ifdef USE_LIBAVRESAMPLE
|
||||||
#include <libavresample/avresample.h>
|
#include <libavresample/avresample.h>
|
||||||
|
#else
|
||||||
|
#include <libswresample/swresample.h>
|
||||||
|
#endif
|
||||||
#include <libswscale/swscale.h>
|
#include <libswscale/swscale.h>
|
||||||
|
|
||||||
static void _ffmpegPostVideoFrame(struct mAVStream*, const color_t* pixels, size_t stride);
|
static void _ffmpegPostVideoFrame(struct mAVStream*, const color_t* pixels, size_t stride);
|
||||||
|
@ -248,6 +252,7 @@ bool FFmpegEncoderOpen(struct FFmpegEncoder* encoder, const char* outfile) {
|
||||||
encoder->audioFrame->nb_samples = encoder->audio->frame_size;
|
encoder->audioFrame->nb_samples = encoder->audio->frame_size;
|
||||||
encoder->audioFrame->format = encoder->audio->sample_fmt;
|
encoder->audioFrame->format = encoder->audio->sample_fmt;
|
||||||
encoder->audioFrame->pts = 0;
|
encoder->audioFrame->pts = 0;
|
||||||
|
#ifdef USE_LIBAVRESAMPLE
|
||||||
encoder->resampleContext = avresample_alloc_context();
|
encoder->resampleContext = avresample_alloc_context();
|
||||||
av_opt_set_int(encoder->resampleContext, "in_channel_layout", AV_CH_LAYOUT_STEREO, 0);
|
av_opt_set_int(encoder->resampleContext, "in_channel_layout", AV_CH_LAYOUT_STEREO, 0);
|
||||||
av_opt_set_int(encoder->resampleContext, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0);
|
av_opt_set_int(encoder->resampleContext, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0);
|
||||||
|
@ -256,6 +261,11 @@ bool FFmpegEncoderOpen(struct FFmpegEncoder* encoder, const char* outfile) {
|
||||||
av_opt_set_int(encoder->resampleContext, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
|
av_opt_set_int(encoder->resampleContext, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
|
||||||
av_opt_set_int(encoder->resampleContext, "out_sample_fmt", encoder->sampleFormat, 0);
|
av_opt_set_int(encoder->resampleContext, "out_sample_fmt", encoder->sampleFormat, 0);
|
||||||
avresample_open(encoder->resampleContext);
|
avresample_open(encoder->resampleContext);
|
||||||
|
#else
|
||||||
|
encoder->resampleContext = swr_alloc_set_opts(NULL, AV_CH_LAYOUT_STEREO, encoder->sampleFormat, encoder->sampleRate,
|
||||||
|
AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_S16, PREFERRED_SAMPLE_RATE, 0, NULL);
|
||||||
|
swr_init(encoder->resampleContext);
|
||||||
|
#endif
|
||||||
encoder->audioBufferSize = (encoder->audioFrame->nb_samples * PREFERRED_SAMPLE_RATE / encoder->sampleRate) * 4;
|
encoder->audioBufferSize = (encoder->audioFrame->nb_samples * PREFERRED_SAMPLE_RATE / encoder->sampleRate) * 4;
|
||||||
encoder->audioBuffer = av_malloc(encoder->audioBufferSize);
|
encoder->audioBuffer = av_malloc(encoder->audioBufferSize);
|
||||||
encoder->postaudioBufferSize = av_samples_get_buffer_size(0, encoder->audio->channels, encoder->audio->frame_size, encoder->audio->sample_fmt, 0);
|
encoder->postaudioBufferSize = av_samples_get_buffer_size(0, encoder->audio->channels, encoder->audio->frame_size, encoder->audio->sample_fmt, 0);
|
||||||
|
@ -362,7 +372,11 @@ void FFmpegEncoderClose(struct FFmpegEncoder* encoder) {
|
||||||
avcodec_close(encoder->audio);
|
avcodec_close(encoder->audio);
|
||||||
|
|
||||||
if (encoder->resampleContext) {
|
if (encoder->resampleContext) {
|
||||||
|
#ifdef USE_LIBAVRESAMPLE
|
||||||
avresample_close(encoder->resampleContext);
|
avresample_close(encoder->resampleContext);
|
||||||
|
#else
|
||||||
|
swr_free(&encoder->resampleContext);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (encoder->absf) {
|
if (encoder->absf) {
|
||||||
|
@ -414,10 +428,11 @@ void _ffmpegPostAudioFrame(struct mAVStream* stream, int16_t left, int16_t right
|
||||||
}
|
}
|
||||||
|
|
||||||
int channelSize = 2 * av_get_bytes_per_sample(encoder->audio->sample_fmt);
|
int channelSize = 2 * av_get_bytes_per_sample(encoder->audio->sample_fmt);
|
||||||
|
encoder->currentAudioSample = 0;
|
||||||
|
#ifdef USE_LIBAVRESAMPLE
|
||||||
avresample_convert(encoder->resampleContext, 0, 0, 0,
|
avresample_convert(encoder->resampleContext, 0, 0, 0,
|
||||||
(uint8_t**) &encoder->audioBuffer, 0, encoder->audioBufferSize / 4);
|
(uint8_t**) &encoder->audioBuffer, 0, encoder->audioBufferSize / 4);
|
||||||
|
|
||||||
encoder->currentAudioSample = 0;
|
|
||||||
if (avresample_available(encoder->resampleContext) < encoder->audioFrame->nb_samples) {
|
if (avresample_available(encoder->resampleContext) < encoder->audioFrame->nb_samples) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -425,6 +440,17 @@ void _ffmpegPostAudioFrame(struct mAVStream* stream, int16_t left, int16_t right
|
||||||
av_frame_make_writable(encoder->audioFrame);
|
av_frame_make_writable(encoder->audioFrame);
|
||||||
#endif
|
#endif
|
||||||
int samples = avresample_read(encoder->resampleContext, encoder->audioFrame->data, encoder->postaudioBufferSize / channelSize);
|
int samples = avresample_read(encoder->resampleContext, encoder->audioFrame->data, encoder->postaudioBufferSize / channelSize);
|
||||||
|
#else
|
||||||
|
#if LIBAVCODEC_VERSION_MAJOR >= 55
|
||||||
|
av_frame_make_writable(encoder->audioFrame);
|
||||||
|
#endif
|
||||||
|
if (swr_get_out_samples(encoder->resampleContext, encoder->audioBufferSize / 4) < encoder->audioFrame->nb_samples) {
|
||||||
|
swr_convert(encoder->resampleContext, NULL, 0, (const uint8_t**) &encoder->audioBuffer, encoder->audioBufferSize / 4);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int samples = swr_convert(encoder->resampleContext, encoder->audioFrame->data, encoder->postaudioBufferSize / channelSize,
|
||||||
|
(const uint8_t**) &encoder->audioBuffer, encoder->audioBufferSize / 4);
|
||||||
|
#endif
|
||||||
|
|
||||||
encoder->audioFrame->pts = av_rescale_q(encoder->currentAudioFrame, encoder->audio->time_base, encoder->audioStream->time_base);
|
encoder->audioFrame->pts = av_rescale_q(encoder->currentAudioFrame, encoder->audio->time_base, encoder->audioStream->time_base);
|
||||||
encoder->currentAudioFrame += samples;
|
encoder->currentAudioFrame += samples;
|
||||||
|
|
|
@ -57,7 +57,11 @@ struct FFmpegEncoder {
|
||||||
size_t currentAudioSample;
|
size_t currentAudioSample;
|
||||||
int64_t currentAudioFrame;
|
int64_t currentAudioFrame;
|
||||||
int64_t nextAudioPts; // TODO (0.6): Remove
|
int64_t nextAudioPts; // TODO (0.6): Remove
|
||||||
|
#ifdef USE_LIBAVRESAMPLE
|
||||||
struct AVAudioResampleContext* resampleContext;
|
struct AVAudioResampleContext* resampleContext;
|
||||||
|
#else
|
||||||
|
struct SwrContext* resampleContext;
|
||||||
|
#endif
|
||||||
#ifdef FFMPEG_USE_NEW_BSF
|
#ifdef FFMPEG_USE_NEW_BSF
|
||||||
struct AVBSFContext* absf; // Needed for AAC in MP4
|
struct AVBSFContext* absf; // Needed for AAC in MP4
|
||||||
#else
|
#else
|
||||||
|
|
Loading…
Reference in New Issue