From 19be0f3ca61bf36dcf145ba8241a449ff5acdeba Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Sat, 9 Jun 2012 19:19:07 +0200 Subject: [PATCH 1/9] iac: add missing dependency --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index a1dbe9f9a7..fbb71b6e16 100755 --- a/configure +++ b/configure @@ -1314,6 +1314,7 @@ h264_dxva2_hwaccel_select="dxva2 h264_decoder" h264_vaapi_hwaccel_select="vaapi h264_decoder" h264_vda_hwaccel_select="vda h264_decoder" h264_vdpau_decoder_select="vdpau h264_decoder" +iac_decoder_select="fft mdct sinewin" imc_decoder_select="fft mdct sinewin" jpegls_decoder_select="golomb" jpegls_encoder_select="golomb" From d7d071a673b5ca7e59ae7cc888eaa1dc24fc4f5e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 9 Jun 2012 16:00:16 +0200 Subject: [PATCH 2/9] vf_libopencv: add missing headers. Fix build after b74a1da4. --- libavfilter/vf_libopencv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavfilter/vf_libopencv.c b/libavfilter/vf_libopencv.c index b6dcd191ae..d38b5845bd 100644 --- a/libavfilter/vf_libopencv.c +++ b/libavfilter/vf_libopencv.c @@ -30,6 +30,8 @@ #include "libavutil/avstring.h" #include "libavutil/file.h" #include "avfilter.h" +#include "formats.h" +#include "video.h" static void fill_iplimage_from_picref(IplImage *img, const AVFilterBufferRef *picref, enum PixelFormat pixfmt) { From 3596de55fc054b5c336e7e542c26ced0505d4f2e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 9 Jun 2012 20:14:12 +0200 Subject: [PATCH 3/9] audioconvert: use av_popcount64 in av_get_channel_layout_nb_channels --- libavutil/audioconvert.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libavutil/audioconvert.c b/libavutil/audioconvert.c index 2560127aac..1a8e5ee239 100644 --- a/libavutil/audioconvert.c +++ b/libavutil/audioconvert.c @@ -175,11 +175,7 @@ void av_get_channel_layout_string(char *buf, int buf_size, int av_get_channel_layout_nb_channels(uint64_t channel_layout) { - int count; - uint64_t x = channel_layout; - for (count = 0; x; count++) - x &= x-1; // unset lowest set bit - return count; + return av_popcount64(channel_layout); } uint64_t av_get_default_channel_layout(int nb_channels) From 406b257de936b59f1fc943e399fbf1289fec6b95 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 28 May 2012 08:16:40 +0200 Subject: [PATCH 4/9] audioconvert: add a function for getting channel's index in layout --- libavutil/audioconvert.c | 10 ++++++++++ libavutil/audioconvert.h | 12 ++++++++++++ 2 files changed, 22 insertions(+) diff --git a/libavutil/audioconvert.c b/libavutil/audioconvert.c index 1a8e5ee239..9e2f812d7c 100644 --- a/libavutil/audioconvert.c +++ b/libavutil/audioconvert.c @@ -192,3 +192,13 @@ uint64_t av_get_default_channel_layout(int nb_channels) default: return 0; } } + +int av_get_channel_layout_channel_index(uint64_t channel_layout, + uint64_t channel) +{ + if (!(channel_layout & channel) || + av_get_channel_layout_nb_channels(channel) != 1) + return AVERROR(EINVAL); + channel_layout &= channel - 1; + return av_get_channel_layout_nb_channels(channel_layout); +} diff --git a/libavutil/audioconvert.h b/libavutil/audioconvert.h index 35a1a087f6..6f6b4447ef 100644 --- a/libavutil/audioconvert.h +++ b/libavutil/audioconvert.h @@ -143,6 +143,18 @@ int av_get_channel_layout_nb_channels(uint64_t channel_layout); */ uint64_t av_get_default_channel_layout(int nb_channels); +/** + * Get the index of a channel in channel_layout. + * + * @param channel a channel layout describing exactly one channel which must be + * present in channel_layout. + * + * @return index of channel in channel_layout on success, a negative AVERROR + * on error. + */ +int av_get_channel_layout_channel_index(uint64_t channel_layout, + uint64_t channel); + /** * @} */ From 5df320e167dc5b5a6fa46e2d1d59f51263dea181 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 28 May 2012 08:39:10 +0200 Subject: [PATCH 5/9] audioconvert: add a function for getting the name of a single channel. --- libavutil/audioconvert.c | 11 +++++++++++ libavutil/audioconvert.h | 7 +++++++ 2 files changed, 18 insertions(+) diff --git a/libavutil/audioconvert.c b/libavutil/audioconvert.c index 9e2f812d7c..36d07ee5a4 100644 --- a/libavutil/audioconvert.c +++ b/libavutil/audioconvert.c @@ -202,3 +202,14 @@ int av_get_channel_layout_channel_index(uint64_t channel_layout, channel_layout &= channel - 1; return av_get_channel_layout_nb_channels(channel_layout); } + +const char *av_get_channel_name(uint64_t channel) +{ + int i; + if (av_get_channel_layout_nb_channels(channel) != 1) + return NULL; + for (i = 0; i < 64; i++) + if ((1ULL< Date: Mon, 28 May 2012 12:20:57 +0200 Subject: [PATCH 6/9] audioconvert: add a function for extracting the channel with the given index --- libavutil/audioconvert.c | 14 ++++++++++++++ libavutil/audioconvert.h | 5 +++++ 2 files changed, 19 insertions(+) diff --git a/libavutil/audioconvert.c b/libavutil/audioconvert.c index 36d07ee5a4..1ac63a37a6 100644 --- a/libavutil/audioconvert.c +++ b/libavutil/audioconvert.c @@ -213,3 +213,17 @@ const char *av_get_channel_name(uint64_t channel) return get_channel_name(i); return NULL; } + +uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index) +{ + int i; + + if (av_get_channel_layout_nb_channels(channel_layout) <= index) + return 0; + + for (i = 0; i < 64; i++) { + if ((1ULL << i) & channel_layout && !index--) + return 1ULL << i; + } + return 0; +} diff --git a/libavutil/audioconvert.h b/libavutil/audioconvert.h index e516ae8296..691c64a9de 100644 --- a/libavutil/audioconvert.h +++ b/libavutil/audioconvert.h @@ -155,6 +155,11 @@ uint64_t av_get_default_channel_layout(int nb_channels); int av_get_channel_layout_channel_index(uint64_t channel_layout, uint64_t channel); +/** + * Get the channel with the given index in channel_layout. + */ +uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index); + /** * Get the name of a given channel. * From b0f0dfc4851da74e77d3d55bf83f3c8b8617e22a Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 28 May 2012 21:40:44 +0200 Subject: [PATCH 7/9] Bump lavu minor and add an APIChanges entry for audioconvert functions. --- doc/APIchanges | 4 ++++ libavutil/avutil.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index dca33aa0eb..729bddc853 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,10 @@ libavutil: 2011-04-18 API changes, most recent first: +2012-xx-xx - xxxxxxx - lavu 51.32.0 - audioconvert.h + Add av_get_channel_layout_channel_index(), av_get_channel_name() + and av_channel_layout_extract_channel(). + 2012-05-25 - e0e0793 - lavu 51.31.0 - opt.h Add av_opt_set_bin() diff --git a/libavutil/avutil.h b/libavutil/avutil.h index 1c8e0767df..25c159dc5d 100644 --- a/libavutil/avutil.h +++ b/libavutil/avutil.h @@ -152,7 +152,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 51 -#define LIBAVUTIL_VERSION_MINOR 31 +#define LIBAVUTIL_VERSION_MINOR 32 #define LIBAVUTIL_VERSION_MICRO 0 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From 5db5169e46a5f1676aafb82ec8c3f5dc6fb6bb6d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 2 Jun 2012 07:26:41 +0200 Subject: [PATCH 8/9] avconv: multithreaded demuxing. When there are multiple input files, run demuxing for each input file in a separate thread, so reading packets does not block. This is useful for achieving low latency when reading from multiple (possibly slow) input streams. --- avconv.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 155 insertions(+), 2 deletions(-) diff --git a/avconv.c b/avconv.c index 23ee164676..7d50d583e5 100644 --- a/avconv.c +++ b/avconv.c @@ -69,6 +69,14 @@ #include #endif +#if HAVE_THREADS +#if HAVE_PTHREADS +#include +#else +#include "libavcodec/w32pthreads.h" +#endif +#endif + #include #include "cmdutils.h" @@ -140,6 +148,11 @@ static float dts_delta_threshold = 10; static int print_stats = 1; +#if HAVE_THREADS +/* signal to input threads that they should exit; set by the main thread */ +static int transcoding_finished; +#endif + #define DEFAULT_PASS_LOGFILENAME_PREFIX "av2pass" typedef struct InputFilter { @@ -219,6 +232,15 @@ typedef struct InputFile { int nb_streams; /* number of stream that avconv is aware of; may be different from ctx.nb_streams if new streams appear during av_read_frame() */ int rate_emu; + +#if HAVE_THREADS + pthread_t thread; /* thread reading from this file */ + int finished; /* the thread has exited */ + int joined; /* the thread has been joined */ + pthread_mutex_t fifo_lock; /* lock for access to fifo */ + pthread_cond_t fifo_cond; /* the main thread will signal on this cond after reading from fifo */ + AVFifoBuffer *fifo; /* demuxed packets are stored here; freed by the main thread */ +#endif } InputFile; typedef struct OutputStream { @@ -2765,6 +2787,125 @@ static int select_input_file(uint8_t *no_packet) return file_index; } +#if HAVE_THREADS +static void *input_thread(void *arg) +{ + InputFile *f = arg; + int ret = 0; + + while (!transcoding_finished && ret >= 0) { + AVPacket pkt; + ret = av_read_frame(f->ctx, &pkt); + + if (ret == AVERROR(EAGAIN)) { + usleep(10000); + ret = 0; + continue; + } else if (ret < 0) + break; + + pthread_mutex_lock(&f->fifo_lock); + while (!av_fifo_space(f->fifo)) + pthread_cond_wait(&f->fifo_cond, &f->fifo_lock); + + av_dup_packet(&pkt); + av_fifo_generic_write(f->fifo, &pkt, sizeof(pkt), NULL); + + pthread_mutex_unlock(&f->fifo_lock); + } + + f->finished = 1; + return NULL; +} + +static void free_input_threads(void) +{ + int i; + + if (nb_input_files == 1) + return; + + transcoding_finished = 1; + + for (i = 0; i < nb_input_files; i++) { + InputFile *f = input_files[i]; + AVPacket pkt; + + if (f->joined) + continue; + + pthread_mutex_lock(&f->fifo_lock); + while (av_fifo_size(f->fifo)) { + av_fifo_generic_read(f->fifo, &pkt, sizeof(pkt), NULL); + av_free_packet(&pkt); + } + pthread_cond_signal(&f->fifo_cond); + pthread_mutex_unlock(&f->fifo_lock); + + pthread_join(f->thread, NULL); + f->joined = 1; + + while (av_fifo_size(f->fifo)) { + av_fifo_generic_read(f->fifo, &pkt, sizeof(pkt), NULL); + av_free_packet(&pkt); + } + av_fifo_free(f->fifo); + } +} + +static int init_input_threads(void) +{ + int i, ret; + + if (nb_input_files == 1) + return 0; + + for (i = 0; i < nb_input_files; i++) { + InputFile *f = input_files[i]; + + if (!(f->fifo = av_fifo_alloc(8*sizeof(AVPacket)))) + return AVERROR(ENOMEM); + + pthread_mutex_init(&f->fifo_lock, NULL); + pthread_cond_init (&f->fifo_cond, NULL); + + if ((ret = pthread_create(&f->thread, NULL, input_thread, f))) + return AVERROR(ret); + } + return 0; +} + +static int get_input_packet_mt(InputFile *f, AVPacket *pkt) +{ + int ret = 0; + + pthread_mutex_lock(&f->fifo_lock); + + if (av_fifo_size(f->fifo)) { + av_fifo_generic_read(f->fifo, pkt, sizeof(*pkt), NULL); + pthread_cond_signal(&f->fifo_cond); + } else { + if (f->finished) + ret = AVERROR_EOF; + else + ret = AVERROR(EAGAIN); + } + + pthread_mutex_unlock(&f->fifo_lock); + + return ret; +} +#endif + +static int get_input_packet(InputFile *f, AVPacket *pkt) +{ +#if HAVE_THREADS + if (nb_input_files > 1) + return get_input_packet_mt(f, pkt); +#endif + return av_read_frame(f->ctx, pkt); +} + /* * The following code is the main loop of the file converter */ @@ -2790,6 +2931,11 @@ static int transcode(void) timer_start = av_gettime(); +#if HAVE_THREADS + if ((ret = init_input_threads()) < 0) + goto fail; +#endif + for (; received_sigterm == 0;) { int file_index, ist_index; AVPacket pkt; @@ -2810,12 +2956,13 @@ static int transcode(void) usleep(10000); continue; } + av_log(NULL, AV_LOG_VERBOSE, "No more inputs to read from, finishing.\n"); break; } - /* read a frame from it and output it in the fifo */ is = input_files[file_index]->ctx; - ret = av_read_frame(is, &pkt); + ret = get_input_packet(input_files[file_index], &pkt); + if (ret == AVERROR(EAGAIN)) { no_packet[file_index] = 1; no_packet_count++; @@ -2897,6 +3044,9 @@ static int transcode(void) /* dump report by using the output first video and audio streams */ print_report(0, timer_start); } +#if HAVE_THREADS + free_input_threads(); +#endif /* at the end of stream, we must flush the decoder buffers */ for (i = 0; i < nb_input_streams; i++) { @@ -2941,6 +3091,9 @@ static int transcode(void) fail: av_freep(&no_packet); +#if HAVE_THREADS + free_input_threads(); +#endif if (output_streams) { for (i = 0; i < nb_output_streams; i++) { From bcbb30e2a0f3be3e6b158694687d0fde2f6db625 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 1 Jun 2012 00:07:36 +0200 Subject: [PATCH 9/9] libmp3lame: add missing layout terminator Signed-off-by: Anton Khirnov --- libavcodec/libmp3lame.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c index 8f25438932..a747f656cc 100644 --- a/libavcodec/libmp3lame.c +++ b/libavcodec/libmp3lame.c @@ -305,7 +305,8 @@ AVCodec ff_libmp3lame_encoder = { AV_SAMPLE_FMT_NONE }, .supported_samplerates = libmp3lame_sample_rates, .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, - AV_CH_LAYOUT_STEREO }, + AV_CH_LAYOUT_STEREO, + 0 }, .long_name = NULL_IF_CONFIG_SMALL("libmp3lame MP3 (MPEG audio layer 3)"), .priv_class = &libmp3lame_class, .defaults = libmp3lame_defaults,