From ca00a7e809a4b9c9fb146403d278964b88d16b85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 17 Aug 2012 14:53:52 +0300 Subject: [PATCH 01/13] amrwbdec: Decode the fr_quality bit properly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The way this bit is decoded was accidentally flipped in b70feb405, leading to warnings "Encountered a bad or corrupted frame" for each decoded frame. Signed-off-by: Martin Storsjö --- libavcodec/amrwbdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/amrwbdec.c b/libavcodec/amrwbdec.c index 4885c2d6a2..a90a27abe1 100644 --- a/libavcodec/amrwbdec.c +++ b/libavcodec/amrwbdec.c @@ -122,7 +122,7 @@ static int decode_mime_header(AMRWBContext *ctx, const uint8_t *buf) { /* Decode frame header (1st octet) */ ctx->fr_cur_mode = buf[0] >> 3 & 0x0F; - ctx->fr_quality = (buf[0] & 0x4) != 0x4; + ctx->fr_quality = (buf[0] & 0x4) == 0x4; return 1; } From 2e8f3cbcda536970aee03f5543185d7fc01232a1 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Tue, 7 Aug 2012 14:48:06 +0300 Subject: [PATCH 02/13] h264: vdpau: fix crash with unsupported colorspace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The h264_vdpau decoder crashed if output colorspace was not 8-bit 420. Add a check to error out instead (current hardware does not support other colorspaces, so successful decoding is not possible). Signed-off-by: Martin Storsjö --- libavcodec/h264.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libavcodec/h264.c b/libavcodec/h264.c index 2019de26ba..a191bc74de 100644 --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -3876,6 +3876,15 @@ again: if (avctx->bits_per_raw_sample != h->sps.bit_depth_luma || h->cur_chroma_format_idc != h->sps.chroma_format_idc) { + if (s->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU + && (h->sps.bit_depth_luma != 8 || + h->sps.chroma_format_idc > 1)) { + av_log(avctx, AV_LOG_ERROR, + "VDPAU decoding does not support video " + "colorspace\n"); + buf_index = -1; + goto end; + } if (h->sps.bit_depth_luma >= 8 && h->sps.bit_depth_luma <= 10) { avctx->bits_per_raw_sample = h->sps.bit_depth_luma; h->cur_chroma_format_idc = h->sps.chroma_format_idc; From d6b9da1178a8e84d1bf999337c058440826d3f54 Mon Sep 17 00:00:00 2001 From: Jordi Ortiz Date: Fri, 17 Aug 2012 18:38:59 +0200 Subject: [PATCH 03/13] avio: add (ff)url_get_multi_file_handle() for getting more than one fd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavformat/avio.c | 15 +++++++++++++++ libavformat/rtpproto.c | 30 ++++++++++++++++++++++-------- libavformat/url.h | 9 +++++++++ 3 files changed, 46 insertions(+), 8 deletions(-) diff --git a/libavformat/avio.c b/libavformat/avio.c index 5acaf30e90..45ee86688f 100644 --- a/libavformat/avio.c +++ b/libavformat/avio.c @@ -344,6 +344,21 @@ int ffurl_get_file_handle(URLContext *h) return h->prot->url_get_file_handle(h); } +int ffurl_get_multi_file_handle(URLContext *h, int **handles, int *numhandles) +{ + if (!h->prot->url_get_multi_file_handle) { + if (!h->prot->url_get_file_handle) + return AVERROR(ENOSYS); + *handles = av_malloc(sizeof(*handles)); + if (!*handles) + return AVERROR(ENOMEM); + *numhandles = 1; + *handles[0] = h->prot->url_get_file_handle(h); + return 0; + } + return h->prot->url_get_multi_file_handle(h, handles, numhandles); +} + int ffurl_shutdown(URLContext *h, int flags) { if (!h->prot->url_shutdown) diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c index e70b89ec9e..fc1ae06df3 100644 --- a/libavformat/rtpproto.c +++ b/libavformat/rtpproto.c @@ -320,13 +320,27 @@ int ff_rtp_get_rtcp_file_handle(URLContext *h) { return s->rtcp_fd; } +static int rtp_get_multi_file_handle(URLContext *h, int **handles, + int *numhandles) +{ + RTPContext *s = h->priv_data; + int *hs = *handles = av_malloc(sizeof(**handles) * 2); + if (!hs) + return AVERROR(ENOMEM); + hs[0] = s->rtp_fd; + hs[1] = s->rtcp_fd; + *numhandles = 2; + return 0; +} + URLProtocol ff_rtp_protocol = { - .name = "rtp", - .url_open = rtp_open, - .url_read = rtp_read, - .url_write = rtp_write, - .url_close = rtp_close, - .url_get_file_handle = rtp_get_file_handle, - .priv_data_size = sizeof(RTPContext), - .flags = URL_PROTOCOL_FLAG_NETWORK, + .name = "rtp", + .url_open = rtp_open, + .url_read = rtp_read, + .url_write = rtp_write, + .url_close = rtp_close, + .url_get_file_handle = rtp_get_file_handle, + .url_get_multi_file_handle = rtp_get_multi_file_handle, + .priv_data_size = sizeof(RTPContext), + .flags = URL_PROTOCOL_FLAG_NETWORK, }; diff --git a/libavformat/url.h b/libavformat/url.h index 0f0de7881c..195a8ff658 100644 --- a/libavformat/url.h +++ b/libavformat/url.h @@ -81,6 +81,8 @@ typedef struct URLProtocol { int64_t (*url_read_seek)(URLContext *h, int stream_index, int64_t timestamp, int flags); int (*url_get_file_handle)(URLContext *h); + int (*url_get_multi_file_handle)(URLContext *h, int **handles, + int *numhandles); int (*url_shutdown)(URLContext *h, int flags); int priv_data_size; const AVClass *priv_data_class; @@ -201,6 +203,13 @@ int64_t ffurl_size(URLContext *h); */ int ffurl_get_file_handle(URLContext *h); +/** + * Return the file descriptors associated with this URL. + * + * @return 0 on success or <0 on error. + */ +int ffurl_get_multi_file_handle(URLContext *h, int **handles, int *numhandles); + /** * Signal the URLContext that we are done reading or writing the stream. * From e7993ece9be619fe70da32f8b9f616b697b282bc Mon Sep 17 00:00:00 2001 From: Jordi Ortiz Date: Fri, 17 Aug 2012 20:06:27 +0200 Subject: [PATCH 04/13] rtsp.c: use ffurl_get_multi_file_handle() instead of ff_rtp_get_rtcp_file_handle() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavformat/rtsp.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 7506d39787..ce18610b4b 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -1695,6 +1695,7 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, int n, i, ret, tcp_fd, timeout_cnt = 0; int max_p = 0; struct pollfd *p = rt->p; + int *fds = NULL, fdsnum, fdsidx; for (;;) { if (ff_check_interrupt(&s->interrupt_callback)) @@ -1712,10 +1713,21 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, for (i = 0; i < rt->nb_rtsp_streams; i++) { rtsp_st = rt->rtsp_streams[i]; if (rtsp_st->rtp_handle) { - p[max_p].fd = ffurl_get_file_handle(rtsp_st->rtp_handle); - p[max_p++].events = POLLIN; - p[max_p].fd = ff_rtp_get_rtcp_file_handle(rtsp_st->rtp_handle); - p[max_p++].events = POLLIN; + if (ret = ffurl_get_multi_file_handle(rtsp_st->rtp_handle, + &fds, &fdsnum)) { + av_log(s, AV_LOG_ERROR, "Unable to recover rtp ports\n"); + return ret; + } + if (fdsnum != 2) { + av_log(s, AV_LOG_ERROR, + "Number of fds %d not supported\n", fdsnum); + return AVERROR_INVALIDDATA; + } + for (fdsidx = 0; fdsidx < fdsnum; fdsidx++) { + p[max_p].fd = fds[fdsidx]; + p[max_p++].events = POLLIN; + } + av_free(fds); } } n = poll(p, max_p, POLL_TIMEOUT_MS); From a2dd4f7780f5b968067d3db728ac64ae444eedab Mon Sep 17 00:00:00 2001 From: Jordi Ortiz Date: Fri, 17 Aug 2012 18:41:26 +0200 Subject: [PATCH 05/13] rtp: remove ff_rtp_get_rtcp_file_handle(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavformat/rtpdec.h | 5 ----- libavformat/rtpproto.c | 5 ----- 2 files changed, 10 deletions(-) diff --git a/libavformat/rtpdec.h b/libavformat/rtpdec.h index 81b6f637d2..20257a7d39 100644 --- a/libavformat/rtpdec.h +++ b/libavformat/rtpdec.h @@ -71,11 +71,6 @@ void ff_rtp_send_punch_packets(URLContext* rtp_handle); */ int ff_rtp_check_and_send_back_rr(RTPDemuxContext *s, int count); -/** - * Get the file handle for the RTCP socket. - */ -int ff_rtp_get_rtcp_file_handle(URLContext *h); - // these statistics are used for rtcp receiver reports... typedef struct { uint16_t max_seq; ///< highest sequence number seen diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c index fc1ae06df3..aca6a5a849 100644 --- a/libavformat/rtpproto.c +++ b/libavformat/rtpproto.c @@ -315,11 +315,6 @@ static int rtp_get_file_handle(URLContext *h) return s->rtp_fd; } -int ff_rtp_get_rtcp_file_handle(URLContext *h) { - RTPContext *s = h->priv_data; - return s->rtcp_fd; -} - static int rtp_get_multi_file_handle(URLContext *h, int **handles, int *numhandles) { From 8337b5db967ecadab4bb65c272cb47d350ecb83b Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Thu, 16 Aug 2012 22:27:15 +0200 Subject: [PATCH 06/13] rtmpdh: Do not generate the same private key every time when using libnettle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace mpz_random by mpz_urandomb with a random state initialization in order to improve the randomness. Signed-off-by: Martin Storsjö --- libavformat/rtmpdh.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libavformat/rtmpdh.c b/libavformat/rtmpdh.c index 92bce7a0bc..38c2f3df63 100644 --- a/libavformat/rtmpdh.c +++ b/libavformat/rtmpdh.c @@ -28,6 +28,7 @@ #include "config.h" #include "rtmpdh.h" +#include "libavutil/random_seed.h" #define P1024 \ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ @@ -78,7 +79,14 @@ ret = (mpz_set_str(bn, buf, 16) == 0); \ } while (0) #define bn_modexp(bn, y, q, p) mpz_powm(bn, y, q, p) -#define bn_random(bn, num_bytes) mpz_random(bn, num_bytes); +#define bn_random(bn, num_bytes) \ + do { \ + gmp_randstate_t rs; \ + gmp_randinit_mt(rs); \ + gmp_randseed_ui(rs, av_get_random_seed()); \ + mpz_urandomb(bn, rs, num_bytes); \ + gmp_randclear(rs); \ + } while (0) #elif CONFIG_GCRYPT #define bn_new(bn) bn = gcry_mpi_new(1) #define bn_free(bn) gcry_mpi_release(bn) From e0aa5e772bbe4c52182a5db321b0da6b98205ef1 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 15 Aug 2012 09:11:31 +0200 Subject: [PATCH 07/13] dvenc: don't use deprecated AVCODEC_MAX_AUDIO_FRAME_SIZE --- libavformat/dvenc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavformat/dvenc.c b/libavformat/dvenc.c index a7d281a799..577ba7c4da 100644 --- a/libavformat/dvenc.c +++ b/libavformat/dvenc.c @@ -38,6 +38,8 @@ #include "libavutil/fifo.h" #include "libavutil/mathematics.h" +#define MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio + struct DVMuxContext { const DVprofile* sys; /* current DV profile, e.g.: 525/60, 625/50 */ int n_ast; /* number of stereo audio streams (up to 2) */ @@ -255,7 +257,7 @@ static int dv_assemble_frame(DVMuxContext *c, AVStream* st, for (i = 0; i < c->n_ast && st != c->ast[i]; i++); /* FIXME: we have to have more sensible approach than this one */ - if (av_fifo_size(c->audio_data[i]) + data_size >= 100*AVCODEC_MAX_AUDIO_FRAME_SIZE) + if (av_fifo_size(c->audio_data[i]) + data_size >= 100*MAX_AUDIO_FRAME_SIZE) av_log(st->codec, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient video data or severe sync problem.\n", c->frames); av_fifo_generic_write(c->audio_data[i], data, data_size, NULL); @@ -343,7 +345,7 @@ static DVMuxContext* dv_init_mux(AVFormatContext* s) c->start_time = ff_iso8601_to_unix_time(t->value); for (i=0; i < c->n_ast; i++) { - if (c->ast[i] && !(c->audio_data[i]=av_fifo_alloc(100*AVCODEC_MAX_AUDIO_FRAME_SIZE))) { + if (c->ast[i] && !(c->audio_data[i]=av_fifo_alloc(100*MAX_AUDIO_FRAME_SIZE))) { while (i > 0) { i--; av_fifo_free(c->audio_data[i]); From 15c71dfd03a699a9ce503bf061d58b88ec49d860 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 15 Aug 2012 09:14:35 +0200 Subject: [PATCH 08/13] swf(dec): replace CODEC_ID with AV_CODEC_ID --- libavformat/swf.c | 6 +++--- libavformat/swfdec.c | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libavformat/swf.c b/libavformat/swf.c index 1762991d2b..e6adf69c02 100644 --- a/libavformat/swf.c +++ b/libavformat/swf.c @@ -23,7 +23,7 @@ #include "internal.h" const AVCodecTag ff_swf_codec_tags[] = { - { CODEC_ID_FLV1, 0x02 }, - { CODEC_ID_VP6F, 0x04 }, - { CODEC_ID_NONE, 0 }, + { AV_CODEC_ID_FLV1, 0x02 }, + { AV_CODEC_ID_VP6F, 0x04 }, + { AV_CODEC_ID_NONE, 0 }, }; diff --git a/libavformat/swfdec.c b/libavformat/swfdec.c index 09770f4f4a..6a923f307d 100644 --- a/libavformat/swfdec.c +++ b/libavformat/swfdec.c @@ -24,12 +24,12 @@ #include "swf.h" static const AVCodecTag swf_audio_codec_tags[] = { - { CODEC_ID_PCM_S16LE, 0x00 }, - { CODEC_ID_ADPCM_SWF, 0x01 }, - { CODEC_ID_MP3, 0x02 }, - { CODEC_ID_PCM_S16LE, 0x03 }, -// { CODEC_ID_NELLYMOSER, 0x06 }, - { CODEC_ID_NONE, 0 }, + { AV_CODEC_ID_PCM_S16LE, 0x00 }, + { AV_CODEC_ID_ADPCM_SWF, 0x01 }, + { AV_CODEC_ID_MP3, 0x02 }, + { AV_CODEC_ID_PCM_S16LE, 0x03 }, +// { AV_CODEC_ID_NELLYMOSER, 0x06 }, + { AV_CODEC_ID_NONE, 0 }, }; static int get_swf_tag(AVIOContext *pb, int *len_ptr) From 0a0f19b577d54ff2e72cc9a0fe027952db83f332 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 11 Aug 2012 14:50:36 +0200 Subject: [PATCH 09/13] lavc: add const to AVCodec* function parameters. --- libavcodec/avcodec.h | 14 +++++++------- libavcodec/options.c | 6 ++++-- libavcodec/utils.c | 11 ++++++----- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 2747c7a94b..b6917a0a7d 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1298,7 +1298,7 @@ typedef struct AVCodecContext { int log_level_offset; enum AVMediaType codec_type; /* see AVMEDIA_TYPE_xxx */ - struct AVCodec *codec; + const struct AVCodec *codec; char codec_name[32]; enum AVCodecID codec_id; /* see AV_CODEC_ID_xxx */ @@ -3150,7 +3150,7 @@ typedef struct AVSubtitle { * if c is non-NULL, returns the next registered codec after c, * or NULL if c is the last one. */ -AVCodec *av_codec_next(AVCodec *c); +AVCodec *av_codec_next(const AVCodec *c); /** * Return the LIBAVCODEC_VERSION_INT constant. @@ -3204,7 +3204,7 @@ void avcodec_register_all(void); * @return An AVCodecContext filled with default values or NULL on failure. * @see avcodec_get_context_defaults */ -AVCodecContext *avcodec_alloc_context3(AVCodec *codec); +AVCodecContext *avcodec_alloc_context3(const AVCodec *codec); /** * Set the fields of the given AVCodecContext to default values corresponding @@ -3215,7 +3215,7 @@ AVCodecContext *avcodec_alloc_context3(AVCodec *codec); * If codec is non-NULL, it is illegal to call avcodec_open2() with a * different codec on this AVCodecContext. */ -int avcodec_get_context_defaults3(AVCodecContext *s, AVCodec *codec); +int avcodec_get_context_defaults3(AVCodecContext *s, const AVCodec *codec); /** * Get the AVClass for AVCodecContext. It can be used in combination with @@ -3290,7 +3290,7 @@ void avcodec_get_frame_defaults(AVFrame *pic); * @see avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(), * av_dict_set(), av_opt_find(). */ -int avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVDictionary **options); +int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options); /** * Close a given AVCodecContext and free all the data associated with it @@ -4527,12 +4527,12 @@ int avcodec_is_open(AVCodecContext *s); /** * @return a non-zero number if codec is an encoder, zero otherwise */ -int av_codec_is_encoder(AVCodec *codec); +int av_codec_is_encoder(const AVCodec *codec); /** * @return a non-zero number if codec is a decoder, zero otherwise */ -int av_codec_is_decoder(AVCodec *codec); +int av_codec_is_decoder(const AVCodec *codec); /** * @return descriptor for given codec ID or NULL if no descriptor exists. diff --git a/libavcodec/options.c b/libavcodec/options.c index 8b1f6a3bc8..25018b9b97 100644 --- a/libavcodec/options.c +++ b/libavcodec/options.c @@ -77,7 +77,8 @@ static const AVClass av_codec_context_class = { .child_class_next = codec_child_class_next, }; -int avcodec_get_context_defaults3(AVCodecContext *s, AVCodec *codec){ +int avcodec_get_context_defaults3(AVCodecContext *s, const AVCodec *codec) +{ memset(s, 0, sizeof(AVCodecContext)); s->av_class = &av_codec_context_class; @@ -122,7 +123,8 @@ int avcodec_get_context_defaults3(AVCodecContext *s, AVCodec *codec){ return 0; } -AVCodecContext *avcodec_alloc_context3(AVCodec *codec){ +AVCodecContext *avcodec_alloc_context3(const AVCodec *codec) +{ AVCodecContext *avctx= av_malloc(sizeof(AVCodecContext)); if(avctx==NULL) return NULL; diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 43a8f67934..b5b0466650 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -96,7 +96,8 @@ void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size) /* encoder management */ static AVCodec *first_avcodec = NULL; -AVCodec *av_codec_next(AVCodec *c){ +AVCodec *av_codec_next(const AVCodec *c) +{ if(c) return c->next; else return first_avcodec; } @@ -112,12 +113,12 @@ static void avcodec_init(void) ff_dsputil_static_init(); } -int av_codec_is_encoder(AVCodec *codec) +int av_codec_is_encoder(const AVCodec *codec) { return codec && (codec->encode || codec->encode2); } -int av_codec_is_decoder(AVCodec *codec) +int av_codec_is_decoder(const AVCodec *codec) { return codec && codec->decode; } @@ -627,7 +628,7 @@ AVFrame *avcodec_alloc_frame(void){ return pic; } -int attribute_align_arg avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVDictionary **options) +int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options) { int ret = 0; AVDictionary *tmp = NULL; @@ -1508,7 +1509,7 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) { const char *codec_name; const char *profile = NULL; - AVCodec *p; + const AVCodec *p; char buf1[32]; int bitrate; AVRational display_aspect_ratio; From 91e59fea30f57af7abd1ad6a68a8f6663805ee44 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 11 Aug 2012 15:32:27 +0200 Subject: [PATCH 10/13] lavc: add avcodec_descriptor_get_by_name(). --- libavcodec/avcodec.h | 6 ++++++ libavcodec/codec_desc.c | 13 +++++++++++++ 2 files changed, 19 insertions(+) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index b6917a0a7d..9658b67ab6 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -4548,6 +4548,12 @@ const AVCodecDescriptor *avcodec_descriptor_get(enum AVCodecID id); */ const AVCodecDescriptor *avcodec_descriptor_next(const AVCodecDescriptor *prev); +/** + * @return codec descriptor with the given name or NULL if no such descriptor + * exists. + */ +const AVCodecDescriptor *avcodec_descriptor_get_by_name(const char *name); + /** * @} */ diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 2ace53b4d0..30a4e4a778 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "avcodec.h" #include "libavutil/common.h" @@ -1939,3 +1941,14 @@ const AVCodecDescriptor *avcodec_descriptor_next(const AVCodecDescriptor *prev) return prev + 1; return NULL; } + +const AVCodecDescriptor *avcodec_descriptor_get_by_name(const char *name) +{ + const AVCodecDescriptor *desc = NULL; + + while ((desc = avcodec_descriptor_next(desc))) { + if (!strcmp(desc->name, name)) + return desc; + } + return NULL; +} From 3c0df9058438b68925be2fc6f5af2a05086ad99e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 11 Aug 2012 11:50:32 +0200 Subject: [PATCH 11/13] avconv: make -shortest a per-output file option. --- Changelog | 1 + avconv.c | 15 ++++++++------- avconv.h | 4 +++- avconv_opt.c | 3 ++- doc/avconv.texi | 2 +- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/Changelog b/Changelog index 64c23d3170..4d0a9f53bf 100644 --- a/Changelog +++ b/Changelog @@ -42,6 +42,7 @@ version : - RTMPE protocol support - RTMPTE protocol support - Canopus Lossless Codec decoder +- avconv -shortest option is now per-output file version 0.8: diff --git a/avconv.c b/avconv.c index 83ff8b45e1..735fc3e767 100644 --- a/avconv.c +++ b/avconv.c @@ -719,7 +719,7 @@ static int poll_filter(OutputStream *ost) */ static int poll_filters(void) { - int i, ret = 0; + int i, j, ret = 0; while (ret >= 0 && !received_sigterm) { OutputStream *ost = NULL; @@ -746,10 +746,14 @@ static int poll_filters(void) ret = poll_filter(ost); if (ret == AVERROR_EOF) { + OutputFile *of = output_files[ost->file_index]; + ost->finished = 1; - if (opt_shortest) - return ret; + if (of->shortest) { + for (j = 0; j < of->ctx->nb_streams; j++) + output_streams[of->ost_index + j]->finished = 1; + } ret = 0; } else if (ret == AVERROR(EAGAIN)) @@ -2170,10 +2174,7 @@ static int process_input(void) } } - if (opt_shortest) - return AVERROR_EOF; - else - return AVERROR(EAGAIN); + return AVERROR(EAGAIN); } reset_eagain(); diff --git a/avconv.h b/avconv.h index 756d197ef5..94b3f670e6 100644 --- a/avconv.h +++ b/avconv.h @@ -113,6 +113,7 @@ typedef struct OptionsContext { uint64_t limit_filesize; float mux_preload; float mux_max_delay; + int shortest; int video_disable; int audio_disable; @@ -303,6 +304,8 @@ typedef struct OutputFile { int64_t recording_time; /* desired length of the resulting file in microseconds */ int64_t start_time; /* start time in microseconds */ uint64_t limit_filesize; + + int shortest; } OutputFile; extern InputStream **input_streams; @@ -333,7 +336,6 @@ extern int do_hex_dump; extern int do_pkt_dump; extern int copy_ts; extern int copy_tb; -extern int opt_shortest; extern int exit_on_error; extern int print_stats; extern int qp_hist; diff --git a/avconv_opt.c b/avconv_opt.c index 7b86d7613c..dc44986e68 100644 --- a/avconv_opt.c +++ b/avconv_opt.c @@ -1352,6 +1352,7 @@ loop_end: oc->duration = o->recording_time; output_files[nb_output_files - 1]->start_time = o->start_time; output_files[nb_output_files - 1]->limit_filesize = o->limit_filesize; + output_files[nb_output_files - 1]->shortest = o->shortest; av_dict_copy(&output_files[nb_output_files - 1]->opts, format_opts, 0); /* check filename in case of an image number is expected */ @@ -1836,7 +1837,7 @@ const OptionDef options[] = { { "adrift_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&audio_drift_threshold}, "audio drift threshold", "threshold" }, { "copyts", OPT_BOOL | OPT_EXPERT, {(void*)©_ts}, "copy timestamps" }, { "copytb", OPT_BOOL | OPT_EXPERT, {(void*)©_tb}, "copy input stream time base when stream copying" }, - { "shortest", OPT_BOOL | OPT_EXPERT, {(void*)&opt_shortest}, "finish encoding within shortest input" }, // + { "shortest", OPT_BOOL | OPT_EXPERT | OPT_OFFSET, {.off = OFFSET(shortest)}, "finish encoding within shortest input" }, { "dts_delta_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&dts_delta_threshold}, "timestamp discontinuity delta threshold", "threshold" }, { "xerror", OPT_BOOL, {(void*)&exit_on_error}, "exit on error", "error" }, { "copyinkf", OPT_BOOL | OPT_EXPERT | OPT_SPEC, {.off = OFFSET(copy_initial_nonkeyframes)}, "copy initial non-keyframes" }, diff --git a/doc/avconv.texi b/doc/avconv.texi index ff5bb5297c..fc6402820b 100644 --- a/doc/avconv.texi +++ b/doc/avconv.texi @@ -752,7 +752,7 @@ This option has been deprecated. Use the @code{asyncts} audio filter instead. Copy timestamps from input to output. @item -copytb Copy input stream time base from input to output when stream copying. -@item -shortest +@item -shortest (@emph{output}) Finish encoding when the shortest input stream ends. @item -dts_delta_threshold Timestamp discontinuity delta threshold. From 7c1019499602e23141d7ca06fe6df5ea5ab3a240 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 11 Aug 2012 15:23:22 +0200 Subject: [PATCH 12/13] cmdutils: refactor -codecs option. Make it print a list of AVCodecDescriptors. Add new -decoders and -encoders options that print lists of decoders and encoders respectively. --- cmdutils.c | 174 ++++++++++++++++++++++------------- cmdutils.h | 12 +++ cmdutils_common_opts.h | 2 + doc/avtools-common-opts.texi | 25 ++--- 4 files changed, 131 insertions(+), 82 deletions(-) diff --git a/cmdutils.c b/cmdutils.c index ae59f7953c..b017490f3f 100644 --- a/cmdutils.c +++ b/cmdutils.c @@ -632,81 +632,123 @@ void show_formats(void) } } +static char get_media_type_char(enum AVMediaType type) +{ + switch (type) { + case AVMEDIA_TYPE_VIDEO: return 'V'; + case AVMEDIA_TYPE_AUDIO: return 'A'; + case AVMEDIA_TYPE_SUBTITLE: return 'S'; + default: return '?'; + } +} + +static const AVCodec *next_codec_for_id(enum AVCodecID id, const AVCodec *prev, + int encoder) +{ + while ((prev = av_codec_next(prev))) { + if (prev->id == id && + (encoder ? av_codec_is_encoder(prev) : av_codec_is_decoder(prev))) + return prev; + } + return NULL; +} + +static void print_codecs_for_id(enum AVCodecID id, int encoder) +{ + const AVCodec *codec = NULL; + + printf(" (%s: ", encoder ? "encoders" : "decoders"); + + while ((codec = next_codec_for_id(id, codec, encoder))) + printf("%s ", codec->name); + + printf(")"); +} + void show_codecs(void) { - AVCodec *p = NULL, *p2; - const char *last_name; + const AVCodecDescriptor *desc = NULL; + printf("Codecs:\n" - " D..... = Decoding supported\n" - " .E.... = Encoding supported\n" - " ..V... = Video codec\n" - " ..A... = Audio codec\n" - " ..S... = Subtitle codec\n" - " ...S.. = Supports draw_horiz_band\n" - " ....D. = Supports direct rendering method 1\n" - " .....T = Supports weird frame truncation\n" - " ------\n"); - last_name= "000"; - for (;;) { - int decode = 0; - int encode = 0; - int cap = 0; - const char *type_str; + " D... = Decoding supported\n" + " .E.. = Encoding supported\n" + " ..V. = Video codec\n" + " ..A. = Audio codec\n" + " ..S. = Subtitle codec\n" + " ...I = Intra frame-only codec\n" + " -----\n"); + while ((desc = avcodec_descriptor_next(desc))) { + const AVCodec *codec = NULL; - p2 = NULL; - while ((p = av_codec_next(p))) { - if ((p2 == NULL || strcmp(p->name, p2->name) < 0) && - strcmp(p->name, last_name) > 0) { - p2 = p; - decode = encode = cap = 0; - } - if (p2 && strcmp(p->name, p2->name) == 0) { - if (av_codec_is_decoder(p)) - decode = 1; - if (av_codec_is_encoder(p)) - encode = 1; - cap |= p->capabilities; + printf(avcodec_find_decoder(desc->id) ? "D" : "."); + printf(avcodec_find_encoder(desc->id) ? "E" : "."); + + printf("%c", get_media_type_char(desc->type)); + printf((desc->props & AV_CODEC_PROP_INTRA_ONLY) ? "I" : "."); + + printf(" %-20s %s", desc->name, desc->long_name ? desc->long_name : ""); + + /* print decoders/encoders when there's more than one or their + * names are different from codec name */ + while ((codec = next_codec_for_id(desc->id, codec, 0))) { + if (strcmp(codec->name, desc->name)) { + print_codecs_for_id(desc->id, 0); + break; } } - if (p2 == NULL) - break; - last_name = p2->name; - - switch (p2->type) { - case AVMEDIA_TYPE_VIDEO: - type_str = "V"; - break; - case AVMEDIA_TYPE_AUDIO: - type_str = "A"; - break; - case AVMEDIA_TYPE_SUBTITLE: - type_str = "S"; - break; - default: - type_str = "?"; - break; + codec = NULL; + while ((codec = next_codec_for_id(desc->id, codec, 1))) { + if (strcmp(codec->name, desc->name)) { + print_codecs_for_id(desc->id, 1); + break; + } } - printf(" %s%s%s%s%s%s %-15s %s", - decode ? "D" : (/* p2->decoder ? "d" : */ " "), - encode ? "E" : " ", - type_str, - cap & CODEC_CAP_DRAW_HORIZ_BAND ? "S" : " ", - cap & CODEC_CAP_DR1 ? "D" : " ", - cap & CODEC_CAP_TRUNCATED ? "T" : " ", - p2->name, - p2->long_name ? p2->long_name : ""); -#if 0 - if (p2->decoder && decode == 0) - printf(" use %s for decoding", p2->decoder->name); -#endif + printf("\n"); } - printf("\n"); - printf("Note, the names of encoders and decoders do not always match, so there are\n" - "several cases where the above table shows encoder only or decoder only entries\n" - "even though both encoding and decoding are supported. For example, the h263\n" - "decoder corresponds to the h263 and h263p encoders, for file formats it is even\n" - "worse.\n"); +} + +static void print_codecs(int encoder) +{ + const AVCodecDescriptor *desc = NULL; + + printf("%s:\n" + " V... = Video\n" + " A... = Audio\n" + " S... = Subtitle\n" + " .F.. = Frame-level multithreading\n" + " ..S. = Slice-level multithreading\n" + " ...X = Codec is experimental\n" + " ---\n", + encoder ? "Encoders" : "Decoders"); + while ((desc = avcodec_descriptor_next(desc))) { + const AVCodec *codec = NULL; + + while ((codec = next_codec_for_id(desc->id, codec, encoder))) { + printf("%c", get_media_type_char(desc->type)); + printf((codec->capabilities & CODEC_CAP_FRAME_THREADS) ? "F" : "."); + printf((codec->capabilities & CODEC_CAP_SLICE_THREADS) ? "S" : "."); + printf((codec->capabilities & CODEC_CAP_EXPERIMENTAL) ? "X" : "."); + + printf(" %-20s %s", codec->name, codec->long_name ? codec->long_name : ""); + if (strcmp(codec->name, desc->name)) + printf(" (codec %s)", desc->name); + + printf("\n"); + } + } +} + +int show_decoders(const char *opt, const char *arg) +{ + print_codecs(0); + return 0; +} + +int show_encoders(const char *opt, const char *arg) +{ + print_codecs(1); + return 0; } void show_bsfs(void) diff --git a/cmdutils.h b/cmdutils.h index f013c2a33f..d787496a36 100644 --- a/cmdutils.h +++ b/cmdutils.h @@ -278,6 +278,18 @@ void show_formats(void); */ void show_codecs(void); +/** + * Print a listing containing all the decoders supported by the + * program. + */ +int show_decoders(const char *opt, const char *arg); + +/** + * Print a listing containing all the encoders supported by the + * program. + */ +int show_encoders(const char *opt, const char *arg); + /** * Print a listing containing all the filters supported by the * program. diff --git a/cmdutils_common_opts.h b/cmdutils_common_opts.h index 1158afab99..d9a09c0c19 100644 --- a/cmdutils_common_opts.h +++ b/cmdutils_common_opts.h @@ -6,6 +6,8 @@ { "version", OPT_EXIT, {(void*)show_version}, "show version" }, { "formats" , OPT_EXIT, {(void*)show_formats }, "show available formats" }, { "codecs" , OPT_EXIT, {(void*)show_codecs }, "show available codecs" }, + { "decoders" , OPT_EXIT, {(void*)show_decoders }, "show available decoders" }, + { "encoders" , OPT_EXIT, {(void*)show_encoders }, "show available encoders" }, { "bsfs" , OPT_EXIT, {(void*)show_bsfs }, "show available bit stream filters" }, { "protocols", OPT_EXIT, {(void*)show_protocols}, "show available protocols" }, { "filters", OPT_EXIT, {(void*)show_filters }, "show available filters" }, diff --git a/doc/avtools-common-opts.texi b/doc/avtools-common-opts.texi index 0be9cf0634..375e4b041c 100644 --- a/doc/avtools-common-opts.texi +++ b/doc/avtools-common-opts.texi @@ -69,23 +69,16 @@ Encoding available @end table @item -codecs -Show available codecs. +Show all codecs known to libavcodec. -The fields preceding the codec names have the following meanings: -@table @samp -@item D -Decoding available -@item E -Encoding available -@item V/A/S -Video/audio/subtitle codec -@item S -Codec supports slices -@item D -Codec supports direct rendering -@item T -Codec can handle input truncated at random locations instead of only at frame boundaries -@end table +Note that the term 'codec' is used throughout this documentation as a shortcut +for what is more correctly called a media bitstream format. + +@item -decoders +Show available decoders. + +@item -encoders +Show all available encoders. @item -bsfs Show available bitstream filters. From 7f9aaa499b8a5ce066cc17aac6ebbdf0111980b6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 15 Aug 2012 09:35:18 +0200 Subject: [PATCH 13/13] mpegvideo_enc: don't use deprecated avcodec_encode_video(). --- libavcodec/mpegvideo_enc.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index d527ace6dd..65f22817da 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -1068,6 +1068,22 @@ static int skip_check(MpegEncContext *s, Picture *p, Picture *ref) return 0; } +static int encode_frame(AVCodecContext *c, AVFrame *frame) +{ + AVPacket pkt = { 0 }; + int ret, got_output; + + av_init_packet(&pkt); + av_init_packet(&pkt); + ret = avcodec_encode_video2(c, &pkt, frame, &got_output); + if (ret < 0) + return ret; + + ret = pkt.size; + av_free_packet(&pkt); + return ret; +} + static int estimate_best_b_count(MpegEncContext *s) { AVCodec *codec = avcodec_find_encoder(s->avctx->codec_id); @@ -1075,8 +1091,6 @@ static int estimate_best_b_count(MpegEncContext *s) AVFrame input[FF_MAX_B_FRAMES + 2]; const int scale = s->avctx->brd_scale; int i, j, out_size, p_lambda, b_lambda, lambda2; - int outbuf_size = s->width * s->height; // FIXME - uint8_t *outbuf = av_malloc(outbuf_size); int64_t best_rd = INT64_MAX; int best_b_count = -1; @@ -1153,8 +1167,9 @@ static int estimate_best_b_count(MpegEncContext *s) input[0].pict_type = AV_PICTURE_TYPE_I; input[0].quality = 1 * FF_QP2LAMBDA; - out_size = avcodec_encode_video(c, outbuf, - outbuf_size, &input[0]); + + out_size = encode_frame(c, &input[0]); + //rd += (out_size * lambda2) >> FF_LAMBDA_SHIFT; for (i = 0; i < s->max_b_frames + 1; i++) { @@ -1163,14 +1178,15 @@ static int estimate_best_b_count(MpegEncContext *s) input[i + 1].pict_type = is_p ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_B; input[i + 1].quality = is_p ? p_lambda : b_lambda; - out_size = avcodec_encode_video(c, outbuf, outbuf_size, - &input[i + 1]); + + out_size = encode_frame(c, &input[i + 1]); + rd += (out_size * lambda2) >> (FF_LAMBDA_SHIFT - 3); } /* get the delayed frames */ while (out_size) { - out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL); + out_size = encode_frame(c, NULL); rd += (out_size * lambda2) >> (FF_LAMBDA_SHIFT - 3); } @@ -1182,7 +1198,6 @@ static int estimate_best_b_count(MpegEncContext *s) } } - av_freep(&outbuf); avcodec_close(c); av_freep(&c);