From 8b122937af9ad10e9352f69c712e782fd6cfb436 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Fri, 11 Apr 2014 23:35:11 +0200 Subject: [PATCH 1/2] Warn if rawvideo and an unreadable pix_fmt are written. Print an error if a combination of rawvideo and an unusual pix_fmt that will be impossible to decode are written to avi or mov. Fixes ticket #3545. --- libavcodec/raw.c | 25 +++++++++++++++++++++++++ libavcodec/raw.h | 3 +++ libavcodec/rawdec.c | 31 +++---------------------------- libavformat/avienc.c | 11 +++++++++++ libavformat/movenc.c | 10 ++++++++++ 5 files changed, 52 insertions(+), 28 deletions(-) diff --git a/libavcodec/raw.c b/libavcodec/raw.c index 16b1b39945..551a1722fc 100644 --- a/libavcodec/raw.c +++ b/libavcodec/raw.c @@ -234,3 +234,28 @@ unsigned int avcodec_pix_fmt_to_codec_tag(enum AVPixelFormat fmt) } return 0; } + +const PixelFormatTag avpriv_pix_fmt_bps_avi[] = { + { AV_PIX_FMT_MONOWHITE, 1 }, + { AV_PIX_FMT_PAL8, 2 }, + { AV_PIX_FMT_PAL8, 4 }, + { AV_PIX_FMT_PAL8, 8 }, + { AV_PIX_FMT_RGB444LE, 12 }, + { AV_PIX_FMT_RGB555LE, 15 }, + { AV_PIX_FMT_RGB555LE, 16 }, + { AV_PIX_FMT_BGR24, 24 }, + { AV_PIX_FMT_BGRA, 32 }, + { AV_PIX_FMT_NONE, 0 }, +}; + +const PixelFormatTag avpriv_pix_fmt_bps_mov[] = { + { AV_PIX_FMT_MONOWHITE, 1 }, + { AV_PIX_FMT_PAL8, 2 }, + { AV_PIX_FMT_PAL8, 4 }, + { AV_PIX_FMT_PAL8, 8 }, + { AV_PIX_FMT_RGB555BE, 16 }, + { AV_PIX_FMT_RGB24, 24 }, + { AV_PIX_FMT_ARGB, 32 }, + { AV_PIX_FMT_MONOWHITE,33 }, + { AV_PIX_FMT_NONE, 0 }, +}; diff --git a/libavcodec/raw.h b/libavcodec/raw.h index 3e59f28e33..a4179930a3 100644 --- a/libavcodec/raw.h +++ b/libavcodec/raw.h @@ -41,4 +41,7 @@ enum AVPixelFormat ff_find_pix_fmt(const PixelFormatTag *tags, unsigned int four #endif enum AVPixelFormat avpriv_find_pix_fmt(const PixelFormatTag *tags, unsigned int fourcc); +extern av_export const PixelFormatTag avpriv_pix_fmt_bps_avi[]; +extern av_export const PixelFormatTag avpriv_pix_fmt_bps_mov[]; + #endif /* AVCODEC_RAW_H */ diff --git a/libavcodec/rawdec.c b/libavcodec/rawdec.c index 4295ed5690..a03b1be9fe 100644 --- a/libavcodec/rawdec.c +++ b/libavcodec/rawdec.c @@ -62,31 +62,6 @@ static const AVClass rawdec_class = { .version = LIBAVUTIL_VERSION_INT, }; -static const PixelFormatTag pix_fmt_bps_avi[] = { - { AV_PIX_FMT_MONOWHITE, 1 }, - { AV_PIX_FMT_PAL8, 2 }, - { AV_PIX_FMT_PAL8, 4 }, - { AV_PIX_FMT_PAL8, 8 }, - { AV_PIX_FMT_RGB444LE, 12 }, - { AV_PIX_FMT_RGB555LE, 15 }, - { AV_PIX_FMT_RGB555LE, 16 }, - { AV_PIX_FMT_BGR24, 24 }, - { AV_PIX_FMT_BGRA, 32 }, - { AV_PIX_FMT_NONE, 0 }, -}; - -static const PixelFormatTag pix_fmt_bps_mov[] = { - { AV_PIX_FMT_MONOWHITE, 1 }, - { AV_PIX_FMT_PAL8, 2 }, - { AV_PIX_FMT_PAL8, 4 }, - { AV_PIX_FMT_PAL8, 8 }, - { AV_PIX_FMT_RGB555BE, 16 }, - { AV_PIX_FMT_RGB24, 24 }, - { AV_PIX_FMT_ARGB, 32 }, - { AV_PIX_FMT_MONOWHITE,33 }, - { AV_PIX_FMT_NONE, 0 }, -}; - #if LIBAVCODEC_VERSION_MAJOR < 55 enum AVPixelFormat ff_find_pix_fmt(const PixelFormatTag *tags, unsigned int fourcc) { @@ -103,15 +78,15 @@ static av_cold int raw_init_decoder(AVCodecContext *avctx) if ( avctx->codec_tag == MKTAG('r','a','w',' ') || avctx->codec_tag == MKTAG('N','O','1','6')) - avctx->pix_fmt = avpriv_find_pix_fmt(pix_fmt_bps_mov, + avctx->pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_mov, avctx->bits_per_coded_sample); else if (avctx->codec_tag == MKTAG('W', 'R', 'A', 'W')) - avctx->pix_fmt = avpriv_find_pix_fmt(pix_fmt_bps_avi, + avctx->pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_avi, avctx->bits_per_coded_sample); else if (avctx->codec_tag && (avctx->codec_tag & 0xFFFFFF) != MKTAG('B','I','T', 0)) avctx->pix_fmt = avpriv_find_pix_fmt(ff_raw_pix_fmt_tags, avctx->codec_tag); else if (avctx->pix_fmt == AV_PIX_FMT_NONE && avctx->bits_per_coded_sample) - avctx->pix_fmt = avpriv_find_pix_fmt(pix_fmt_bps_avi, + avctx->pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_avi, avctx->bits_per_coded_sample); desc = av_pix_fmt_desc_get(avctx->pix_fmt); diff --git a/libavformat/avienc.c b/libavformat/avienc.c index 24a3821390..5acc7c2b14 100644 --- a/libavformat/avienc.c +++ b/libavformat/avienc.c @@ -32,6 +32,8 @@ #include "libavutil/dict.h" #include "libavutil/avassert.h" #include "libavutil/timestamp.h" +#include "libavutil/pixdesc.h" +#include "libavcodec/raw.h" /* * TODO: @@ -296,6 +298,7 @@ static int avi_write_header(AVFormatContext *s) if (stream->codec_type != AVMEDIA_TYPE_DATA) { int ret; + enum AVPixelFormat pix_fmt; strf = ff_start_tag(pb, "strf"); switch (stream->codec_type) { @@ -306,6 +309,14 @@ static int avi_write_header(AVFormatContext *s) break; case AVMEDIA_TYPE_VIDEO: ff_put_bmp_header(pb, stream, ff_codec_bmp_tags, 0, 0); + pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_avi, + stream->bits_per_coded_sample); + if ( !stream->codec_tag + && stream->codec_id == AV_CODEC_ID_RAWVIDEO + && stream->pix_fmt != pix_fmt + && stream->pix_fmt != AV_PIX_FMT_NONE) + av_log(s, AV_LOG_ERROR, "%s rawvideo cannot be written to avi, output file will be unreadable\n", + av_get_pix_fmt_name(stream->pix_fmt)); break; case AVMEDIA_TYPE_AUDIO: if ((ret = ff_put_wav_header(pb, stream)) < 0) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 94acc941b3..808a2bc098 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -34,12 +34,14 @@ #include "libavcodec/get_bits.h" #include "libavcodec/put_bits.h" #include "libavcodec/vc1.h" +#include "libavcodec/raw.h" #include "internal.h" #include "libavutil/avstring.h" #include "libavutil/intfloat.h" #include "libavutil/mathematics.h" #include "libavutil/opt.h" #include "libavutil/dict.h" +#include "libavutil/pixdesc.h" #include "hevc.h" #include "rtpenc.h" #include "mov_chan.h" @@ -1009,6 +1011,7 @@ static int mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track) { int tag = track->enc->codec_tag; int i; + enum AVPixelFormat pix_fmt; for (i = 0; i < FF_ARRAY_ELEMS(mov_pix_fmt_tags); i++) { if (track->enc->pix_fmt == mov_pix_fmt_tags[i].pix_fmt) { @@ -1019,6 +1022,13 @@ static int mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track) } } + pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_mov, + track->enc->bits_per_coded_sample); + if (tag == MKTAG('r','a','w',' ') && + track->enc->pix_fmt != pix_fmt && + track->enc->pix_fmt != AV_PIX_FMT_NONE) + av_log(s, AV_LOG_ERROR, "%s rawvideo cannot be written to mov, output file will be unreadable\n", + av_get_pix_fmt_name(track->enc->pix_fmt)); return tag; } From c43222f436e941db3764576fc967da66f3709c35 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Fri, 11 Apr 2014 23:38:53 +0200 Subject: [PATCH 2/2] Improve amr bitrate calculation for VBR files. Fixes ticket #3541. --- libavformat/amr.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/libavformat/amr.c b/libavformat/amr.c index 47c1244b1d..6001525530 100644 --- a/libavformat/amr.c +++ b/libavformat/amr.c @@ -30,6 +30,11 @@ Only mono files are supported. #include "avformat.h" #include "internal.h" +typedef struct { + uint64_t cumulated_size; + uint64_t block_count; +} AMRContext; + static const char AMR_header[] = "#!AMR\n"; static const char AMRWB_header[] = "#!AMR-WB\n"; @@ -110,6 +115,7 @@ static int amr_read_packet(AVFormatContext *s, AVPacket *pkt) AVCodecContext *enc = s->streams[0]->codec; int read, size = 0, toc, mode; int64_t pos = avio_tell(s->pb); + AMRContext *amr = s->priv_data; if (url_feof(s->pb)) { return AVERROR(EIO); @@ -136,8 +142,11 @@ static int amr_read_packet(AVFormatContext *s, AVPacket *pkt) if (!size || av_new_packet(pkt, size)) return AVERROR(EIO); - /* Both AMR formats have 50 frames per second */ - s->streams[0]->codec->bit_rate = size*8*50; + if (amr->cumulated_size < UINT64_MAX - size) { + amr->cumulated_size += size; + /* Both AMR formats have 50 frames per second */ + s->streams[0]->codec->bit_rate = amr->cumulated_size / ++amr->block_count * 8 * 50; + } pkt->stream_index = 0; pkt->pos = pos; @@ -157,6 +166,7 @@ static int amr_read_packet(AVFormatContext *s, AVPacket *pkt) AVInputFormat ff_amr_demuxer = { .name = "amr", .long_name = NULL_IF_CONFIG_SMALL("3GPP AMR"), + .priv_data_size = sizeof(AMRContext), .read_probe = amr_probe, .read_header = amr_read_header, .read_packet = amr_read_packet,