diff --git a/CMakeLists.txt b/CMakeLists.txt index 46f3b0372..a0d037099 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -607,22 +607,40 @@ if(NOT ZM_NO_FFMPEG) set(optlibsnotfound "${optlibsnotfound} SWScale") endif(SWSCALE_LIBRARIES) - # rescale (using find_library and find_path) - find_library(AVRESAMPLE_LIBRARIES avresample) - if(AVRESAMPLE_LIBRARIES) - set(HAVE_LIBAVRESAMPLE 1) - list(APPEND ZM_BIN_LIBS "${AVRESAMPLE_LIBRARIES}") - find_path(AVRESAMPLE_INCLUDE_DIR "libavresample/avresample.h" /usr/include/ffmpeg) - if(AVRESAMPLE_INCLUDE_DIR) - include_directories("${AVRESAMPLE_INCLUDE_DIR}") - set(CMAKE_REQUIRED_INCLUDES "${AVRESAMPLE_INCLUDE_DIR}") - endif(AVRESAMPLE_INCLUDE_DIR) - mark_as_advanced(FORCE AVRESAMPLE_LIBRARIES AVRESAMPLE_INCLUDE_DIR) - check_include_file("libavresample/avresample.h" HAVE_LIBAVRESAMPLE_AVRESAMPLE_H) - set(optlibsfound "${optlibsfound} AVResample") - else(AVRESAMPLE_LIBRARIES) - set(optlibsnotfound "${optlibsnotfound} AVResample") - endif(AVRESAMPLE_LIBRARIES) + # SWresample (using find_library and find_path) + find_library(SWRESAMPLE_LIBRARIES swresample) + if(SWRESAMPLE_LIBRARIES) + set(HAVE_LIBSWRESAMPLE 1) + list(APPEND ZM_BIN_LIBS "${SWRESAMPLE_LIBRARIES}") + find_path(SWRESAMPLE_INCLUDE_DIR "libswresample/swresample.h" /usr/include/ffmpeg) + if(SWRESAMPLE_INCLUDE_DIR) + include_directories("${SWRESAMPLE_INCLUDE_DIR}") + set(CMAKE_REQUIRED_INCLUDES "${SWRESAMPLE_INCLUDE_DIR}") + endif(SWRESAMPLE_INCLUDE_DIR) + mark_as_advanced(FORCE SWRESAMPLE_LIBRARIES SWRESAMPLE_INCLUDE_DIR) + check_include_file("libswresample/swresample.h" HAVE_LIBSWRESAMPLE_SWRESAMPLE_H) + set(optlibsfound "${optlibsfound} SWResample") + else(SWRESAMPLE_LIBRARIES) + set(optlibsnotfound "${optlibsnotfound} SWResample") + + # AVresample (using find_library and find_path) + find_library(AVRESAMPLE_LIBRARIES avresample) + if(AVRESAMPLE_LIBRARIES) + set(HAVE_LIBAVRESAMPLE 1) + list(APPEND ZM_BIN_LIBS "${AVRESAMPLE_LIBRARIES}") + find_path(AVRESAMPLE_INCLUDE_DIR "libavresample/avresample.h" /usr/include/ffmpeg) + if(AVRESAMPLE_INCLUDE_DIR) + include_directories("${AVRESAMPLE_INCLUDE_DIR}") + set(CMAKE_REQUIRED_INCLUDES "${AVRESAMPLE_INCLUDE_DIR}") + endif(AVRESAMPLE_INCLUDE_DIR) + mark_as_advanced(FORCE AVRESAMPLE_LIBRARIES AVRESAMPLE_INCLUDE_DIR) + check_include_file("libavresample/avresample.h" HAVE_LIBAVRESAMPLE_AVRESAMPLE_H) + set(optlibsfound "${optlibsfound} AVResample") + else(AVRESAMPLE_LIBRARIES) + set(optlibsnotfound "${optlibsnotfound} AVResample") + endif(AVRESAMPLE_LIBRARIES) + + endif(SWRESAMPLE_LIBRARIES) # Find the path to the ffmpeg executable find_program(FFMPEG_EXECUTABLE diff --git a/distros/ubuntu1604/control b/distros/ubuntu1604/control index 991ed9e54..d91fd4f53 100644 --- a/distros/ubuntu1604/control +++ b/distros/ubuntu1604/control @@ -10,6 +10,7 @@ Build-Depends: debhelper (>= 9), dh-systemd, python-sphinx | python3-sphinx, apa ,libavcodec-dev (>= 6:10~) ,libavformat-dev (>= 6:10~) ,libavutil-dev (>= 6:10~) + ,libswresample-dev ,libswscale-dev (>= 6:10~) ,ffmpeg | libav-tools ,net-tools @@ -41,7 +42,9 @@ Package: zoneminder Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends} ,javascript-common - ,libmp4v2-2, libx264-142|libx264-148|libx264-152, libswscale-ffmpeg3|libswscale4|libswscale3|libswscale5 + ,libmp4v2-2, libx264-142|libx264-148|libx264-152 + ,libswscale-ffmpeg3|libswscale4|libswscale3|libswscale5 + ,libswresample2|libswresample3|libswresample24 ,ffmpeg | libav-tools ,libdate-manip-perl, libmime-lite-perl, libmime-tools-perl ,libdbd-mysql-perl diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index 746036efe..31916bdab 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -205,7 +205,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in, audio_out_stream = NULL; in_frame = NULL; out_frame = NULL; -#ifdef HAVE_LIBAVRESAMPLE +#if defined(HAVE_LIBSWRESAMPLE) || defined(HAVE_LIBAVRESAMPLE) resample_ctx = NULL; #endif @@ -220,7 +220,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in, audio_in_ctx = audio_in_stream->codec; #endif - if (audio_in_ctx->codec_id != AV_CODEC_ID_AAC) { + if ( audio_in_ctx->codec_id != AV_CODEC_ID_AAC ) { static char error_buffer[256]; avcodec_string(error_buffer, sizeof(error_buffer), audio_in_ctx, 0); Debug(2, "Got something other than AAC (%s)", error_buffer); @@ -241,8 +241,6 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in, Error("Unable to create audio out stream"); audio_out_stream = NULL; } else { - Debug(2, "setting parameters"); - #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) audio_out_ctx = avcodec_alloc_context3(audio_out_codec); // Copy params from instream to ctx @@ -466,10 +464,16 @@ VideoStore::~VideoStore() { avcodec_free_context(&audio_out_ctx); #endif audio_out_ctx = NULL; -#ifdef HAVE_LIBAVRESAMPLE +#if defined(HAVE_LIBAVRESAMPLE) || defined(HAVE_LIBSWRESAMPLE) if ( resample_ctx ) { +#if defined(HAVE_LIBSWRESAMPLE) + swr_free(&resample_ctx); +#else +#if defined(HAVE_LIBAVRESAMPLE) avresample_close(resample_ctx); avresample_free(&resample_ctx); +#endif +#endif } if ( in_frame ) { av_frame_free(&in_frame); @@ -491,7 +495,12 @@ VideoStore::~VideoStore() { } // VideoStore::~VideoStore() bool VideoStore::setup_resampler() { -#ifdef HAVE_LIBAVRESAMPLE +#if !defined(HAVE_LIBSWRESAMPLE) && !defined(HAVE_LIBAVRESAMPLE) + Error( + "Not built with resample library. " + "Cannot do audio conversion to AAC"); + return false; +#else #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) // Newer ffmpeg wants to keep everything separate... so have to lookup our own @@ -499,8 +508,7 @@ bool VideoStore::setup_resampler() { audio_in_codec = avcodec_find_decoder(audio_in_stream->codecpar->codec_id); #else - audio_in_codec = - avcodec_find_decoder(audio_in_ctx->codec_id); + audio_in_codec = avcodec_find_decoder(audio_in_ctx->codec_id); #endif ret = avcodec_open2(audio_in_ctx, audio_in_codec, NULL); if ( ret < 0 ) { @@ -531,6 +539,9 @@ bool VideoStore::setup_resampler() { audio_out_stream = avformat_new_stream(oc, NULL); audio_out_ctx = audio_out_stream->codec; #endif + // Some formats (i.e. WAV) do not produce the proper channel layout + if ( audio_in_ctx->channel_layout == 0 ) + audio_in_ctx->channel_layout = av_get_channel_layout("mono"); /* put sample parameters */ audio_out_ctx->bit_rate = audio_in_ctx->bit_rate; @@ -622,40 +633,55 @@ bool VideoStore::setup_resampler() { return false; } +#if defined(HAVE_LIBSWRESAMPLE) + resample_ctx = swr_alloc_set_opts(NULL, + av_get_default_channel_layout(audio_out_ctx->channels), + audio_out_ctx->sample_fmt, + audio_out_ctx->sample_rate, + av_get_default_channel_layout(audio_in_ctx->channels), + audio_in_ctx->sample_fmt, + audio_in_ctx->sample_rate, + 0, NULL); + if ( !resample_ctx ) { + Error("Could not allocate resample context"); + av_frame_free(&in_frame); + av_frame_free(&out_frame); + return false; + } + if ( (ret = swr_init(resample_ctx)) < 0 ) { + Error("Could not open resampler"); + av_frame_free(&in_frame); + av_frame_free(&out_frame); + swr_free(&resample_ctx); + return false; + } +#else +#if defined(HAVE_LIBAVRESAMPLE) // Setup the audio resampler resample_ctx = avresample_alloc_context(); if ( !resample_ctx ) { Error("Could not allocate resample ctx"); + av_frame_free(&in_frame); + av_frame_free(&out_frame); return false; } - // Some formats (i.e. WAV) do not produce the proper channel layout - uint64_t layout = av_get_channel_layout("mono"); - if ( audio_in_ctx->channel_layout == 0 ) { - av_opt_set_int(resample_ctx, "in_channel_layout", layout, 0); - Debug(1, "Bad in channel layout. Need to set it to mono (%d).", layout); - } else { - av_opt_set_int(resample_ctx, "in_channel_layout", - audio_in_ctx->channel_layout, 0); - layout = audio_in_ctx->channel_layout; - } - + av_opt_set_int(resample_ctx, "in_channel_layout", + audio_in_ctx->channel_layout, 0); av_opt_set_int(resample_ctx, "in_sample_fmt", - audio_in_ctx->sample_fmt, 0); + audio_in_ctx->sample_fmt, 0); av_opt_set_int(resample_ctx, "in_sample_rate", - audio_in_ctx->sample_rate, 0); - av_opt_set_int(resample_ctx, "in_channels", audio_in_ctx->channels, - 0); - // av_opt_set_int( resample_ctx, "out_channel_layout", - // audio_out_ctx->channel_layout, 0); + audio_in_ctx->sample_rate, 0); + av_opt_set_int(resample_ctx, "in_channels", + audio_in_ctx->channels, 0); av_opt_set_int(resample_ctx, "out_channel_layout", - layout, 0); + audio_in_ctx->channel_layout, 0); av_opt_set_int(resample_ctx, "out_sample_fmt", - audio_out_ctx->sample_fmt, 0); + audio_out_ctx->sample_fmt, 0); av_opt_set_int(resample_ctx, "out_sample_rate", - audio_out_ctx->sample_rate, 0); + audio_out_ctx->sample_rate, 0); av_opt_set_int(resample_ctx, "out_channels", - audio_out_ctx->channels, 0); + audio_out_ctx->channels, 0); ret = avresample_open(resample_ctx); if ( ret < 0 ) { @@ -664,6 +690,8 @@ bool VideoStore::setup_resampler() { } else { Debug(2, "Success opening resampler"); } +#endif +#endif out_frame->nb_samples = audio_out_ctx->frame_size; out_frame->format = audio_out_ctx->sample_fmt; @@ -694,11 +722,6 @@ bool VideoStore::setup_resampler() { } return true; -#else - Error( - "Not built with libavresample library. Cannot do audio conversion to " - "AAC"); - return false; #endif } // end bool VideoStore::setup_resampler() @@ -858,9 +881,9 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) { if ( audio_out_codec ) { Debug(3, "Have audio codec"); -#ifdef HAVE_LIBAVRESAMPLE +#if defined(HAVE_LIBSWRESAMPLE) || defined(HAVE_LIBAVRESAMPLE) -#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) + #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) ret = avcodec_send_packet(audio_in_ctx, ipkt); if ( ret < 0 ) { Error("avcodec_send_packet fail %s", av_make_error_string(ret).c_str()); @@ -877,7 +900,7 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) { "layout(%d)", in_frame->nb_samples, in_frame->format, in_frame->sample_rate, in_frame->channel_layout); -#else + #else /** * Decode the audio frame stored in the packet. * The in audio stream decoder is used to do this. @@ -897,11 +920,24 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) { Debug(2, "Not ready to transcode a frame yet."); return 0; } -#endif + #endif int frame_size = out_frame->nb_samples; // Resample the in into the audioSampleBuffer until we proceed the whole // decoded data + #if defined(HAVE_LIBSWRESAMPLE) + Debug(2, "Converting %d to %d samples", in_frame->nb_samples, out_frame->nb_samples); + if ((ret = swr_convert(resample_ctx, + out_frame->data, frame_size, + (const uint8_t**)in_frame->data, + in_frame->nb_samples)) < 0) { + Error("Could not resample frame (error '%s')\n", + av_make_error_string(ret).c_str()); + av_frame_unref(in_frame); + return 0; + } + #else + #if defined(HAVE_LIBAVRESAMPLE) if ((ret = avresample_convert(resample_ctx, NULL, 0, 0, in_frame->data, 0, in_frame->nb_samples)) < 0) { @@ -910,8 +946,11 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) { av_frame_unref(in_frame); return 0; } + #endif + #endif av_frame_unref(in_frame); + #if defined(HAVE_LIBAVRESAMPLE) int samples_available = avresample_available(resample_ctx); if (samples_available < frame_size) { @@ -926,6 +965,7 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) { Warning("Error reading resampled audio: "); return 0; } + #endif Debug(2, "Frame: samples(%d), format(%d), sample_rate(%d), channel layout(%d)", out_frame->nb_samples, out_frame->format, @@ -934,7 +974,7 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) { av_init_packet(&opkt); Debug(5, "after init packet"); -#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) + #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) if ((ret = avcodec_send_frame(audio_out_ctx, out_frame)) < 0) { Error("Could not send frame (error '%s')", av_make_error_string(ret).c_str()); @@ -958,7 +998,7 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) { // av_frame_unref( out_frame ); return 0; } -#else + #else if ((ret = avcodec_encode_audio2(audio_out_ctx, &opkt, out_frame, &data_present)) < 0) { Error("Could not encode frame (error '%s')", @@ -971,8 +1011,9 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) { zm_av_packet_unref(&opkt); return 0; } -#endif - + #endif +#else + Error("Have audio codec but no resampler?!"); #endif } else { av_init_packet(&opkt); diff --git a/src/zm_videostore.h b/src/zm_videostore.h index 282d96da7..bc7cd8417 100644 --- a/src/zm_videostore.h +++ b/src/zm_videostore.h @@ -3,8 +3,12 @@ #include "zm_ffmpeg.h" extern "C" { -#ifdef HAVE_LIBAVRESAMPLE -#include "libavresample/avresample.h" +#ifdef HAVE_LIBSWRESAMPLE + #include "libswresample/swresample.h" +#else + #ifdef HAVE_LIBAVRESAMPLE + #include "libavresample/avresample.h" + #endif #endif } @@ -38,8 +42,12 @@ private: // The following are used when encoding the audio stream to AAC AVCodec *audio_out_codec; AVCodecContext *audio_out_ctx; +#ifdef HAVE_LIBSWRESAMPLE + SwrContext *resample_ctx; +#else #ifdef HAVE_LIBAVRESAMPLE AVAudioResampleContext* resample_ctx; +#endif #endif uint8_t *converted_in_samples; diff --git a/zoneminder-config.cmake b/zoneminder-config.cmake index 8641bb4a8..e088e68dc 100644 --- a/zoneminder-config.cmake +++ b/zoneminder-config.cmake @@ -54,6 +54,8 @@ #cmakedefine HAVE_LIBAVUTIL_HWCONTEXT_H 0 #cmakedefine HAVE_LIBSWSCALE 1 #cmakedefine HAVE_LIBSWSCALE_SWSCALE_H 1 +#cmakedefine HAVE_LIBSWRESAMPLE 1 +#cmakedefine HAVE_LIBSWRESAMPLE_SWRESAMPLE_H 1 #cmakedefine HAVE_LIBAVRESAMPLE 1 #cmakedefine HAVE_LIBAVRESAMPLE_AVRESAMPLE_H 1 #cmakedefine HAVE_LIBVLC 1