From 1254022ea717fba6f189d6a66841e0ba204ed80a Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Wed, 22 Feb 2012 14:51:37 -0800 Subject: [PATCH 01/40] swscale: fix filtersize clipping. if srcW<=2, clip(x, 1, srcW-2) still allows srcW to be < 1. --- libswscale/utils.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libswscale/utils.c b/libswscale/utils.c index 2fe9c5b47f..6ae8af64e9 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -263,7 +263,8 @@ static int initFilter(int16_t **outFilter, int16_t **filterPos, int *outFilterSi if (xInc <= 1<<16) filterSize= 1 + sizeFactor; // upscale else filterSize= 1 + (sizeFactor*srcW + dstW - 1)/ dstW; - filterSize = av_clip(filterSize, 1, srcW - 2); + filterSize = FFMIN(filterSize, srcW - 2); + filterSize = FFMAX(filterSize, 1); FF_ALLOC_OR_GOTO(NULL, filter, dstW*sizeof(*filter)*filterSize, fail); From 3798205a77ce275613098ecb48645e6029811f14 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Sun, 12 Feb 2012 15:06:58 -0500 Subject: [PATCH 02/40] mov: set channel layout for AC-3 streams based on the 'dac3' atom info fixes Bug 225 --- libavcodec/Makefile | 2 +- libavcodec/ac3_parser.c | 2 +- libavcodec/ac3dec.c | 2 +- libavcodec/ac3tab.c | 2 +- libavcodec/ac3tab.h | 2 +- libavformat/mov.c | 5 +++++ 6 files changed, 10 insertions(+), 5 deletions(-) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 93ff7d4a67..a98ff5b52a 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -556,7 +556,7 @@ OBJS-$(CONFIG_MATROSKA_MUXER) += xiph.o mpeg4audio.o \ flacdec.o flacdata.o flac.o \ mpegaudiodata.o OBJS-$(CONFIG_MP3_MUXER) += mpegaudiodata.o mpegaudiodecheader.o -OBJS-$(CONFIG_MOV_DEMUXER) += mpeg4audio.o mpegaudiodata.o +OBJS-$(CONFIG_MOV_DEMUXER) += mpeg4audio.o mpegaudiodata.o ac3tab.o OBJS-$(CONFIG_MOV_MUXER) += mpeg4audio.o mpegaudiodata.o OBJS-$(CONFIG_MPEGTS_MUXER) += mpegvideo.o mpeg4audio.o OBJS-$(CONFIG_MPEGTS_DEMUXER) += mpeg4audio.o mpegaudiodata.o diff --git a/libavcodec/ac3_parser.c b/libavcodec/ac3_parser.c index 067b4f9879..d9ba1fd70b 100644 --- a/libavcodec/ac3_parser.c +++ b/libavcodec/ac3_parser.c @@ -134,7 +134,7 @@ int avpriv_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr) (hdr->num_blocks * 256.0)); hdr->channels = ff_ac3_channels_tab[hdr->channel_mode] + hdr->lfe_on; } - hdr->channel_layout = ff_ac3_channel_layout_tab[hdr->channel_mode]; + hdr->channel_layout = avpriv_ac3_channel_layout_tab[hdr->channel_mode]; if (hdr->lfe_on) hdr->channel_layout |= AV_CH_LOW_FREQUENCY; diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c index c0d7488d84..a8bc48ab6e 100644 --- a/libavcodec/ac3dec.c +++ b/libavcodec/ac3dec.c @@ -1378,7 +1378,7 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, avctx->request_channels < s->channels) { s->out_channels = avctx->request_channels; s->output_mode = avctx->request_channels == 1 ? AC3_CHMODE_MONO : AC3_CHMODE_STEREO; - s->channel_layout = ff_ac3_channel_layout_tab[s->output_mode]; + s->channel_layout = avpriv_ac3_channel_layout_tab[s->output_mode]; } avctx->channels = s->out_channels; avctx->channel_layout = s->channel_layout; diff --git a/libavcodec/ac3tab.c b/libavcodec/ac3tab.c index 7df3d828fb..951a1014ce 100644 --- a/libavcodec/ac3tab.c +++ b/libavcodec/ac3tab.c @@ -84,7 +84,7 @@ const uint8_t ff_ac3_channels_tab[8] = { /** * Map audio coding mode (acmod) to channel layout mask. */ -const uint16_t ff_ac3_channel_layout_tab[8] = { +const uint16_t avpriv_ac3_channel_layout_tab[8] = { AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, diff --git a/libavcodec/ac3tab.h b/libavcodec/ac3tab.h index e5cd368bb7..8ed50520e6 100644 --- a/libavcodec/ac3tab.h +++ b/libavcodec/ac3tab.h @@ -33,7 +33,7 @@ extern const uint16_t ff_ac3_frame_size_tab[38][3]; extern const uint8_t ff_ac3_channels_tab[8]; -extern const uint16_t ff_ac3_channel_layout_tab[8]; +extern const uint16_t avpriv_ac3_channel_layout_tab[8]; extern const uint8_t ff_ac3_enc_channel_map[8][2][6]; extern const uint8_t ff_ac3_dec_channel_map[8][2][6]; extern const uint16_t ff_ac3_sample_rate_tab[3]; diff --git a/libavformat/mov.c b/libavformat/mov.c index c2f13b6316..b11e0bfef7 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -25,11 +25,13 @@ //#define DEBUG //#define MOV_EXPORT_ALL_METADATA +#include "libavutil/audioconvert.h" #include "libavutil/intreadwrite.h" #include "libavutil/intfloat.h" #include "libavutil/mathematics.h" #include "libavutil/avstring.h" #include "libavutil/dict.h" +#include "libavcodec/ac3tab.h" #include "avformat.h" #include "internal.h" #include "avio_internal.h" @@ -552,6 +554,9 @@ static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom) acmod = (ac3info >> 11) & 0x7; lfeon = (ac3info >> 10) & 0x1; st->codec->channels = ((int[]){2,1,2,3,3,4,4,5})[acmod] + lfeon; + st->codec->channel_layout = avpriv_ac3_channel_layout_tab[acmod]; + if (lfeon) + st->codec->channel_layout |= AV_CH_LOW_FREQUENCY; st->codec->audio_service_type = bsmod; if (st->codec->channels > 1 && bsmod == 0x7) st->codec->audio_service_type = AV_AUDIO_SERVICE_TYPE_KARAOKE; From 62d5f9e5cab45df0505862e5ede2bae55d1881aa Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Thu, 9 Feb 2012 22:44:10 -0500 Subject: [PATCH 03/40] flacdec: set channel_layout based on channel count Channel layouts are specified in the FLAC format description at http://flac.sourceforge.net/format.html fixes Bug 209 --- libavcodec/flacdec.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libavcodec/flacdec.c b/libavcodec/flacdec.c index 7454d8b7f7..ad3827b6cc 100644 --- a/libavcodec/flacdec.c +++ b/libavcodec/flacdec.c @@ -33,6 +33,7 @@ #include +#include "libavutil/audioconvert.h" #include "libavutil/crc.h" #include "avcodec.h" #include "internal.h" @@ -62,6 +63,15 @@ typedef struct FLACContext { int32_t *decoded[FLAC_MAX_CHANNELS]; ///< decoded samples } FLACContext; +static const int64_t flac_channel_layouts[6] = { + AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_SURROUND, + AV_CH_LAYOUT_QUAD, + AV_CH_LAYOUT_5POINT0, + AV_CH_LAYOUT_5POINT1 +}; + static void allocate_buffers(FLACContext *s); int avpriv_flac_is_extradata_valid(AVCodecContext *avctx, @@ -120,6 +130,9 @@ static av_cold int flac_decode_init(AVCodecContext *avctx) avcodec_get_frame_defaults(&s->frame); avctx->coded_frame = &s->frame; + if (avctx->channels <= FF_ARRAY_ELEMS(flac_channel_layouts)) + avctx->channel_layout = flac_channel_layouts[avctx->channels - 1]; + return 0; } From 21b46747ad0c72e9c60740b75ec20a7a052126d5 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 12 Feb 2012 09:32:40 +0100 Subject: [PATCH 04/40] qtrleenc: switch to encode2(). --- libavcodec/qtrleenc.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/libavcodec/qtrleenc.c b/libavcodec/qtrleenc.c index 3ffce2bc7f..6936722df7 100644 --- a/libavcodec/qtrleenc.c +++ b/libavcodec/qtrleenc.c @@ -25,6 +25,7 @@ #include "libavutil/imgutils.h" #include "avcodec.h" #include "bytestream.h" +#include "internal.h" /** Maximum RLE code for bulk copy */ #define MAX_RLE_BULK 127 @@ -96,7 +97,7 @@ static av_cold int qtrle_encode_init(AVCodecContext *avctx) return -1; } - s->max_buf_size = s->avctx->width*s->avctx->height*s->pixel_size /* image base material */ + s->max_buf_size = s->avctx->width*s->avctx->height*s->pixel_size*2 /* image base material */ + 15 /* header + footer */ + s->avctx->height*2 /* skip code+rle end */ + s->avctx->width/MAX_RLE_BULK + 1 /* rle codes */; @@ -107,7 +108,7 @@ static av_cold int qtrle_encode_init(AVCodecContext *avctx) /** * Compute the best RLE sequence for a line */ -static void qtrle_encode_line(QtrleEncContext *s, AVFrame *p, int line, uint8_t **buf) +static void qtrle_encode_line(QtrleEncContext *s, const AVFrame *p, int line, uint8_t **buf) { int width=s->avctx->width; int i; @@ -237,7 +238,7 @@ static void qtrle_encode_line(QtrleEncContext *s, AVFrame *p, int line, uint8_t } /** Encode frame including header */ -static int encode_frame(QtrleEncContext *s, AVFrame *p, uint8_t *buf) +static int encode_frame(QtrleEncContext *s, const AVFrame *p, uint8_t *buf) { int i; int start_line = 0; @@ -278,19 +279,19 @@ static int encode_frame(QtrleEncContext *s, AVFrame *p, uint8_t *buf) return buf - orig_buf; } -static int qtrle_encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, void *data) +static int qtrle_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) { QtrleEncContext * const s = avctx->priv_data; - AVFrame *pict = data; AVFrame * const p = &s->frame; - int chunksize; + int ret; *p = *pict; - if (buf_size < s->max_buf_size) { + if ((ret = ff_alloc_packet(pkt, s->max_buf_size)) < 0) { /* Upper bound check for compressed data */ - av_log(avctx, AV_LOG_ERROR, "buf_size %d < %d\n", buf_size, s->max_buf_size); - return -1; + av_log(avctx, AV_LOG_ERROR, "Error getting output packet of size %d.\n", s->max_buf_size); + return ret; } if (avctx->gop_size == 0 || (s->avctx->frame_number % avctx->gop_size) == 0) { @@ -303,11 +304,16 @@ static int qtrle_encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, p->key_frame = 0; } - chunksize = encode_frame(s, pict, buf); + pkt->size = encode_frame(s, pict, pkt->data); /* save the current frame */ av_picture_copy(&s->previous_frame, (AVPicture *)p, avctx->pix_fmt, avctx->width, avctx->height); - return chunksize; + + if (p->key_frame) + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; } static av_cold int qtrle_encode_end(AVCodecContext *avctx) @@ -327,7 +333,7 @@ AVCodec ff_qtrle_encoder = { .id = CODEC_ID_QTRLE, .priv_data_size = sizeof(QtrleEncContext), .init = qtrle_encode_init, - .encode = qtrle_encode_frame, + .encode2 = qtrle_encode_frame, .close = qtrle_encode_end, .pix_fmts = (const enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGB555BE, PIX_FMT_ARGB, PIX_FMT_NONE}, .long_name = NULL_IF_CONFIG_SMALL("QuickTime Animation (RLE) video"), From 148fc9950622bb28ebb2d4a4ada7f316fc090f5e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 20 Feb 2012 13:21:58 +0100 Subject: [PATCH 05/40] lclenc: switch to encode2(). --- libavcodec/lclenc.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/libavcodec/lclenc.c b/libavcodec/lclenc.c index 4c902d5f17..eacd3228f5 100644 --- a/libavcodec/lclenc.c +++ b/libavcodec/lclenc.c @@ -68,12 +68,20 @@ typedef struct LclEncContext { * Encode a frame * */ -static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){ +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ LclEncContext *c = avctx->priv_data; - AVFrame *pict = data; AVFrame * const p = &c->pic; - int i; + int i, ret; int zret; // Zlib return code + int max_size = deflateBound(&c->zstream, avctx->width * avctx->height * 3); + + if (!pkt->data && + (ret = av_new_packet(pkt, max_size)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error allocating packet of size %d.\n", max_size); + return ret; + } *p = *pict; p->pict_type= AV_PICTURE_TYPE_I; @@ -89,8 +97,8 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, av_log(avctx, AV_LOG_ERROR, "Deflate reset error: %d\n", zret); return -1; } - c->zstream.next_out = buf; - c->zstream.avail_out = buf_size; + c->zstream.next_out = pkt->data; + c->zstream.avail_out = pkt->size; for(i = avctx->height - 1; i >= 0; i--) { c->zstream.next_in = p->data[0]+p->linesize[0]*i; @@ -107,7 +115,11 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, return -1; } - return c->zstream.total_out; + pkt->size = c->zstream.total_out; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; } /* @@ -176,7 +188,7 @@ AVCodec ff_zlib_encoder = { .id = CODEC_ID_ZLIB, .priv_data_size = sizeof(LclEncContext), .init = encode_init, - .encode = encode_frame, + .encode2 = encode_frame, .close = encode_end, .pix_fmts = (const enum PixelFormat[]) { PIX_FMT_BGR24, PIX_FMT_NONE }, .long_name = NULL_IF_CONFIG_SMALL("LCL (LossLess Codec Library) ZLIB"), From 6d9c27dc85844adb37504fb43c78c12631ab7416 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 22 Feb 2012 07:38:13 +0100 Subject: [PATCH 06/40] jpeglsenc: switch to encode2(). --- libavcodec/jpeglsenc.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/libavcodec/jpeglsenc.c b/libavcodec/jpeglsenc.c index 2b6e54ddd4..f264c79ae7 100644 --- a/libavcodec/jpeglsenc.c +++ b/libavcodec/jpeglsenc.c @@ -28,6 +28,7 @@ #include "avcodec.h" #include "get_bits.h" #include "golomb.h" +#include "internal.h" #include "mathops.h" #include "dsputil.h" #include "mjpeg.h" @@ -227,23 +228,19 @@ static void ls_store_lse(JLSState *state, PutBitContext *pb){ put_bits(pb, 16, state->reset); } -static int encode_picture_ls(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){ +static int encode_picture_ls(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ JpeglsContext * const s = avctx->priv_data; - AVFrame *pict = data; AVFrame * const p= (AVFrame*)&s->picture; const int near = avctx->prediction_method; PutBitContext pb, pb2; GetBitContext gb; uint8_t *buf2, *zero, *cur, *last; JLSState *state; - int i, size; + int i, size, ret; int comps; - buf2 = av_malloc(buf_size); - - init_put_bits(&pb, buf, buf_size); - init_put_bits(&pb2, buf2, buf_size); - *p = *pict; p->pict_type= AV_PICTURE_TYPE_I; p->key_frame= 1; @@ -253,6 +250,17 @@ static int encode_picture_ls(AVCodecContext *avctx, unsigned char *buf, int buf_ else comps = 3; + if ((ret = ff_alloc_packet(pkt, avctx->width*avctx->height*comps*4 + + FF_MIN_BUFFER_SIZE)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); + return ret; + } + + buf2 = av_malloc(pkt->size); + + init_put_bits(&pb, pkt->data, pkt->size); + init_put_bits(&pb2, buf2, pkt->size); + /* write our own JPEG header, can't use mjpeg_picture_header */ put_marker(&pb, SOI); put_marker(&pb, SOF48); @@ -366,7 +374,10 @@ static int encode_picture_ls(AVCodecContext *avctx, unsigned char *buf, int buf_ emms_c(); - return put_bits_count(&pb) >> 3; + pkt->size = put_bits_count(&pb) >> 3; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + return 0; } static av_cold int encode_init_ls(AVCodecContext *ctx) { @@ -388,7 +399,7 @@ AVCodec ff_jpegls_encoder = { //FIXME avoid MPV_* lossless JPEG should not need .id = CODEC_ID_JPEGLS, .priv_data_size = sizeof(JpeglsContext), .init = encode_init_ls, - .encode = encode_picture_ls, + .encode2 = encode_picture_ls, .pix_fmts = (const enum PixelFormat[]){PIX_FMT_BGR24, PIX_FMT_RGB24, PIX_FMT_GRAY8, PIX_FMT_GRAY16, PIX_FMT_NONE}, .long_name = NULL_IF_CONFIG_SMALL("JPEG-LS"), }; From f7fa73ac917534cc5f77469cac2b80462e475417 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 12 Feb 2012 09:32:40 +0100 Subject: [PATCH 07/40] libtheoraenc: switch to encode2(). --- libavcodec/libtheoraenc.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/libavcodec/libtheoraenc.c b/libavcodec/libtheoraenc.c index ecceceaa12..957994a44f 100644 --- a/libavcodec/libtheoraenc.c +++ b/libavcodec/libtheoraenc.c @@ -35,6 +35,7 @@ #include "libavutil/log.h" #include "libavutil/base64.h" #include "avcodec.h" +#include "internal.h" /* libtheora includes */ #include @@ -260,14 +261,13 @@ static av_cold int encode_init(AVCodecContext* avc_context) return 0; } -static int encode_frame(AVCodecContext* avc_context, uint8_t *outbuf, - int buf_size, void *data) +static int encode_frame(AVCodecContext* avc_context, AVPacket *pkt, + const AVFrame *frame, int *got_packet) { th_ycbcr_buffer t_yuv_buffer; TheoraContext *h = avc_context->priv_data; - AVFrame *frame = data; ogg_packet o_packet; - int result, i; + int result, i, ret; // EOS, finish and get 1st pass stats if applicable if (!frame) { @@ -328,18 +328,21 @@ static int encode_frame(AVCodecContext* avc_context, uint8_t *outbuf, } /* Copy ogg_packet content out to buffer */ - if (buf_size < o_packet.bytes) { - av_log(avc_context, AV_LOG_ERROR, "encoded frame too large\n"); - return -1; + if ((ret = ff_alloc_packet(pkt, o_packet.bytes)) < 0) { + av_log(avc_context, AV_LOG_ERROR, "Error getting output packet of size %ld.\n", o_packet.bytes); + return ret; } - memcpy(outbuf, o_packet.packet, o_packet.bytes); + memcpy(pkt->data, o_packet.packet, o_packet.bytes); // HACK: assumes no encoder delay, this is true until libtheora becomes // multithreaded (which will be disabled unless explictly requested) - avc_context->coded_frame->pts = frame->pts; + pkt->pts = pkt->dts = frame->pts; avc_context->coded_frame->key_frame = !(o_packet.granulepos & h->keyframe_mask); + if (avc_context->coded_frame->key_frame) + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; - return o_packet.bytes; + return 0; } static av_cold int encode_close(AVCodecContext* avc_context) @@ -364,7 +367,7 @@ AVCodec ff_libtheora_encoder = { .priv_data_size = sizeof(TheoraContext), .init = encode_init, .close = encode_close, - .encode = encode_frame, + .encode2 = encode_frame, .capabilities = CODEC_CAP_DELAY, // needed to get the statsfile summary .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_YUV444P, PIX_FMT_NONE}, .long_name = NULL_IF_CONFIG_SMALL("libtheora Theora"), From 278d88689ba89c78f6c2667cf98025835567d78d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 12 Feb 2012 09:32:40 +0100 Subject: [PATCH 08/40] ffv1enc: switch to encode2(). --- libavcodec/ffv1.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c index 366de02ac8..d2324fa41b 100644 --- a/libavcodec/ffv1.c +++ b/libavcodec/ffv1.c @@ -1080,17 +1080,25 @@ static int encode_slice(AVCodecContext *c, void *arg){ return 0; } -static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){ +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ FFV1Context *f = avctx->priv_data; RangeCoder * const c= &f->slice_context[0]->c; - AVFrame *pict = data; AVFrame * const p= &f->picture; int used_count= 0; uint8_t keystate=128; uint8_t *buf_p; - int i; + int i, ret; - ff_init_range_encoder(c, buf, buf_size); + if (!pkt->data && + (ret = av_new_packet(pkt, avctx->width*avctx->height*((8*2+1+1)*4)/8 + + FF_MIN_BUFFER_SIZE)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); + return ret; + } + + ff_init_range_encoder(c, pkt->data, pkt->size); ff_build_rac_states(c, 0.05*(1LL<<32), 256-8); *p = *pict; @@ -1110,7 +1118,7 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, if(!f->ac){ used_count += ff_rac_terminate(c); //printf("pos=%d\n", used_count); - init_put_bits(&f->slice_context[0]->pb, buf + used_count, buf_size - used_count); + init_put_bits(&f->slice_context[0]->pb, pkt->data + used_count, pkt->size - used_count); }else if (f->ac>1){ int i; for(i=1; i<256; i++){ @@ -1121,8 +1129,8 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, for(i=1; islice_count; i++){ FFV1Context *fs= f->slice_context[i]; - uint8_t *start= buf + (buf_size-used_count)*i/f->slice_count; - int len= buf_size/f->slice_count; + uint8_t *start = pkt->data + (pkt->size-used_count)*i/f->slice_count; + int len = pkt->size/f->slice_count; if(fs->ac){ ff_init_range_encoder(&fs->c, start, len); @@ -1132,7 +1140,7 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, } avctx->execute(avctx, encode_slice, &f->slice_context[0], NULL, f->slice_count, sizeof(void*)); - buf_p=buf; + buf_p = pkt->data; for(i=0; islice_count; i++){ FFV1Context *fs= f->slice_context[i]; int bytes; @@ -1147,7 +1155,7 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, used_count= 0; } if(i>0){ - av_assert0(bytes < buf_size/f->slice_count); + av_assert0(bytes < pkt->size/f->slice_count); memmove(buf_p, fs->ac ? fs->c.bytestream_start : fs->pb.buf, bytes); av_assert0(bytes < (1<<24)); AV_WB24(buf_p+bytes, bytes); @@ -1200,7 +1208,11 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, avctx->stats_out[0] = '\0'; f->picture_number++; - return buf_p-buf; + pkt->size = buf_p - pkt->data; + pkt->flags |= AV_PKT_FLAG_KEY*p->key_frame; + *got_packet = 1; + + return 0; } #endif /* CONFIG_FFV1_ENCODER */ @@ -1742,7 +1754,7 @@ AVCodec ff_ffv1_encoder = { .id = CODEC_ID_FFV1, .priv_data_size = sizeof(FFV1Context), .init = encode_init, - .encode = encode_frame, + .encode2 = encode_frame, .close = common_end, .capabilities = CODEC_CAP_SLICE_THREADS, .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_YUV444P, PIX_FMT_YUV422P, PIX_FMT_YUV411P, PIX_FMT_YUV410P, PIX_FMT_RGB32, PIX_FMT_YUV420P16, PIX_FMT_YUV422P16, PIX_FMT_YUV444P16, PIX_FMT_NONE}, From df53a473170399bf7bc94b397a1d9f1d50366049 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 20 Feb 2012 13:21:58 +0100 Subject: [PATCH 09/40] libschroedingerenc: switch to encode2(). --- libavcodec/libschroedingerenc.c | 43 ++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/libavcodec/libschroedingerenc.c b/libavcodec/libschroedingerenc.c index 2aadd3af3f..ed017a1a1f 100644 --- a/libavcodec/libschroedingerenc.c +++ b/libavcodec/libschroedingerenc.c @@ -35,6 +35,7 @@ #include #include "avcodec.h" +#include "internal.h" #include "libdirac_libschro.h" #include "libschroedinger.h" #include "bytestream.h" @@ -71,6 +72,9 @@ typedef struct SchroEncoderParams { /** end of sequence pulled */ int eos_pulled; + + /* counter for frames submitted to encoder, used as dts */ + int64_t dts; } SchroEncoderParams; /** @@ -175,6 +179,7 @@ static int libschroedinger_encode_init(AVCodecContext *avccontext) schro_encoder_setting_set_double(p_schro_params->encoder, "au_distance", avccontext->gop_size); avccontext->has_b_frames = 1; + p_schro_params->dts = -1; } /* FIXME - Need to handle SCHRO_ENCODER_RATE_CONTROL_LOW_DELAY. */ @@ -236,7 +241,7 @@ static int libschroedinger_encode_init(AVCodecContext *avccontext) } static SchroFrame *libschroedinger_frame_from_data(AVCodecContext *avccontext, - void *in_data) + const AVFrame *frame) { SchroEncoderParams *p_schro_params = avccontext->priv_data; SchroFrame *in_frame; @@ -246,7 +251,7 @@ static SchroFrame *libschroedinger_frame_from_data(AVCodecContext *avccontext, in_frame = ff_create_schro_frame(avccontext, p_schro_params->frame_format); if (in_frame) - avpicture_layout((AVPicture *)in_data, avccontext->pix_fmt, + avpicture_layout((const AVPicture *)frame, avccontext->pix_fmt, avccontext->width, avccontext->height, in_frame->components[0].data, p_schro_params->frame_size); @@ -262,9 +267,8 @@ static void SchroedingerFreeFrame(void *data) av_free(enc_frame); } -static int libschroedinger_encode_frame(AVCodecContext *avccontext, - unsigned char *frame, - int buf_size, void *data) +static int libschroedinger_encode_frame(AVCodecContext *avccontext, AVPacket *pkt, + const AVFrame *frame, int *got_packet) { int enc_size = 0; SchroEncoderParams *p_schro_params = avccontext->priv_data; @@ -275,8 +279,9 @@ static int libschroedinger_encode_frame(AVCodecContext *avccontext, int presentation_frame; int parse_code; int last_frame_in_sequence = 0; + int pkt_size, ret; - if (!data) { + if (!frame) { /* Push end of sequence if not already signalled. */ if (!p_schro_params->eos_signalled) { schro_encoder_end_of_stream(encoder); @@ -285,7 +290,7 @@ static int libschroedinger_encode_frame(AVCodecContext *avccontext, } else { /* Allocate frame data to schro input buffer. */ SchroFrame *in_frame = libschroedinger_frame_from_data(avccontext, - data); + frame); /* Load next frame. */ schro_encoder_push_frame(encoder, in_frame); } @@ -373,28 +378,42 @@ static int libschroedinger_encode_frame(AVCodecContext *avccontext, if (!p_frame_output) return 0; - memcpy(frame, p_frame_output->p_encbuf, p_frame_output->size); + pkt_size = p_frame_output->size; + if (last_frame_in_sequence && p_schro_params->enc_buf_size > 0) + pkt_size += p_schro_params->enc_buf_size; + if ((ret = ff_alloc_packet(pkt, pkt_size)) < 0) { + av_log(avccontext, AV_LOG_ERROR, "Error getting output packet of size %d.\n", pkt_size); + goto error; + } + + memcpy(pkt->data, p_frame_output->p_encbuf, p_frame_output->size); avccontext->coded_frame->key_frame = p_frame_output->key_frame; /* Use the frame number of the encoded frame as the pts. It is OK to * do so since Dirac is a constant frame rate codec. It expects input * to be of constant frame rate. */ + pkt->pts = avccontext->coded_frame->pts = p_frame_output->frame_num; + pkt->dts = p_schro_params->dts++; enc_size = p_frame_output->size; /* Append the end of sequence information to the last frame in the * sequence. */ if (last_frame_in_sequence && p_schro_params->enc_buf_size > 0) { - memcpy(frame + enc_size, p_schro_params->enc_buf, + memcpy(pkt->data + enc_size, p_schro_params->enc_buf, p_schro_params->enc_buf_size); enc_size += p_schro_params->enc_buf_size; av_freep(&p_schro_params->enc_buf); p_schro_params->enc_buf_size = 0; } + if (p_frame_output->key_frame) + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + +error: /* free frame */ SchroedingerFreeFrame(p_frame_output); - - return enc_size; + return ret; } @@ -427,7 +446,7 @@ AVCodec ff_libschroedinger_encoder = { .id = CODEC_ID_DIRAC, .priv_data_size = sizeof(SchroEncoderParams), .init = libschroedinger_encode_init, - .encode = libschroedinger_encode_frame, + .encode2 = libschroedinger_encode_frame, .close = libschroedinger_encode_close, .capabilities = CODEC_CAP_DELAY, .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_YUV444P, PIX_FMT_NONE}, From 3c0ed7d1a8ccb170c1ce5acacfe5e9c26135541e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 22 Feb 2012 07:38:13 +0100 Subject: [PATCH 10/40] asv1enc: switch to encode2(). --- libavcodec/asv1.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/libavcodec/asv1.c b/libavcodec/asv1.c index 71b6fba9ae..94073c087e 100644 --- a/libavcodec/asv1.c +++ b/libavcodec/asv1.c @@ -325,10 +325,12 @@ static inline int decode_mb(ASV1Context *a, DCTELEM block[6][64]){ return 0; } +#define MAX_MB_SIZE (30*16*16*3/2/8) + static inline int encode_mb(ASV1Context *a, DCTELEM block[6][64]){ int i; - if(a->pb.buf_end - a->pb.buf - (put_bits_count(&a->pb)>>3) < 30*16*16*3/2/8){ + if (a->pb.buf_end - a->pb.buf - (put_bits_count(&a->pb)>>3) < MAX_MB_SIZE) { av_log(a->avctx, AV_LOG_ERROR, "encoded frame too large\n"); return -1; } @@ -461,14 +463,22 @@ static int decode_frame(AVCodecContext *avctx, } #if CONFIG_ASV1_ENCODER || CONFIG_ASV2_ENCODER -static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){ +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ ASV1Context * const a = avctx->priv_data; - AVFrame *pict = data; AVFrame * const p= &a->picture; - int size; + int size, ret; int mb_x, mb_y; - init_put_bits(&a->pb, buf, buf_size); + if (!pkt->data && + (ret = av_new_packet(pkt, a->mb_height*a->mb_width*MAX_MB_SIZE + + FF_MIN_BUFFER_SIZE)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); + return ret; + } + + init_put_bits(&a->pb, pkt->data, pkt->size); *p = *pict; p->pict_type= AV_PICTURE_TYPE_I; @@ -505,14 +515,18 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, size= put_bits_count(&a->pb)/32; if(avctx->codec_id == CODEC_ID_ASV1) - a->dsp.bswap_buf((uint32_t*)buf, (uint32_t*)buf, size); + a->dsp.bswap_buf((uint32_t*)pkt->data, (uint32_t*)pkt->data, size); else{ int i; for(i=0; i<4*size; i++) - buf[i]= av_reverse[ buf[i] ]; + pkt->data[i] = av_reverse[pkt->data[i]]; } - return size*4; + pkt->size = size*4; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; } #endif /* CONFIG_ASV1_ENCODER || CONFIG_ASV2_ENCODER */ @@ -634,7 +648,7 @@ AVCodec ff_asv1_encoder = { .id = CODEC_ID_ASV1, .priv_data_size = sizeof(ASV1Context), .init = encode_init, - .encode = encode_frame, + .encode2 = encode_frame, //encode_end, .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE}, .long_name= NULL_IF_CONFIG_SMALL("ASUS V1"), @@ -648,7 +662,7 @@ AVCodec ff_asv2_encoder = { .id = CODEC_ID_ASV2, .priv_data_size = sizeof(ASV1Context), .init = encode_init, - .encode = encode_frame, + .encode2 = encode_frame, //encode_end, .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE}, .long_name= NULL_IF_CONFIG_SMALL("ASUS V2"), From c2ff63e3ac82d5ee501e480d4714e982fc45cf8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 23 Feb 2012 11:38:24 +0200 Subject: [PATCH 11/40] rtpenc: Move the trailing comma into FF_RTP_FLAG_OPTS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This simplifies adding more flags to the macro. Signed-off-by: Martin Storsjö --- libavformat/movenc.c | 2 +- libavformat/rtpenc.c | 2 +- libavformat/rtpenc.h | 2 +- libavformat/rtsp.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index d50a0e045e..2c6a6e1864 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -51,7 +51,7 @@ static const AVOption options[] = { { "separate_moof", "Write separate moof/mdat atoms for each track", 0, AV_OPT_TYPE_CONST, {.dbl = FF_MOV_FLAG_SEPARATE_MOOF}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "frag_custom", "Flush fragments on caller requests", 0, AV_OPT_TYPE_CONST, {.dbl = FF_MOV_FLAG_FRAG_CUSTOM}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "isml", "Create a live smooth streaming feed (for pushing to a publishing point)", 0, AV_OPT_TYPE_CONST, {.dbl = FF_MOV_FLAG_ISML}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, - FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags), + FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags) { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_INT, {.dbl = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM}, { "iods_audio_profile", "iods audio profile atom.", offsetof(MOVMuxContext, iods_audio_profile), AV_OPT_TYPE_INT, {.dbl = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM}, { "iods_video_profile", "iods video profile atom.", offsetof(MOVMuxContext, iods_video_profile), AV_OPT_TYPE_INT, {.dbl = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM}, diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c index a4a6987032..e19541798b 100644 --- a/libavformat/rtpenc.c +++ b/libavformat/rtpenc.c @@ -31,7 +31,7 @@ //#define DEBUG static const AVOption options[] = { - FF_RTP_FLAG_OPTS(RTPMuxContext, flags), + FF_RTP_FLAG_OPTS(RTPMuxContext, flags) { "payload_type", "Specify RTP payload type", offsetof(RTPMuxContext, payload_type), AV_OPT_TYPE_INT, {.dbl = -1 }, -1, 127, AV_OPT_FLAG_ENCODING_PARAM }, { NULL }, }; diff --git a/libavformat/rtpenc.h b/libavformat/rtpenc.h index 72d7f65783..fdad24947b 100644 --- a/libavformat/rtpenc.h +++ b/libavformat/rtpenc.h @@ -67,7 +67,7 @@ typedef struct RTPMuxContext RTPMuxContext; #define FF_RTP_FLAG_OPTS(ctx, fieldname) \ { "rtpflags", "RTP muxer flags", offsetof(ctx, fieldname), AV_OPT_TYPE_FLAGS, {.dbl = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "rtpflags" }, \ - { "latm", "Use MP4A-LATM packetization instead of MPEG4-GENERIC for AAC", 0, AV_OPT_TYPE_CONST, {.dbl = FF_RTP_FLAG_MP4A_LATM}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "rtpflags" } \ + { "latm", "Use MP4A-LATM packetization instead of MPEG4-GENERIC for AAC", 0, AV_OPT_TYPE_CONST, {.dbl = FF_RTP_FLAG_MP4A_LATM}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "rtpflags" }, \ void ff_rtp_send_data(AVFormatContext *s1, const uint8_t *buf1, int len, int m); diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 359d910076..29994e4eb3 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -73,7 +73,7 @@ const AVOption ff_rtsp_options[] = { { "initial_pause", "Don't start playing the stream immediately", OFFSET(initial_pause), AV_OPT_TYPE_INT, {0}, 0, 1, DEC }, - FF_RTP_FLAG_OPTS(RTSPState, rtp_muxer_flags), + FF_RTP_FLAG_OPTS(RTSPState, rtp_muxer_flags) { "rtsp_transport", "RTSP transport protocols", OFFSET(lower_transport_mask), AV_OPT_TYPE_FLAGS, {0}, INT_MIN, INT_MAX, DEC|ENC, "rtsp_transport" }, \ { "udp", "UDP", 0, AV_OPT_TYPE_CONST, {1 << RTSP_LOWER_TRANSPORT_UDP}, 0, 0, DEC|ENC, "rtsp_transport" }, \ { "tcp", "TCP", 0, AV_OPT_TYPE_CONST, {1 << RTSP_LOWER_TRANSPORT_TCP}, 0, 0, DEC|ENC, "rtsp_transport" }, \ From c4584f3c1ff3997fd98c3cc992fe82cb99f6b248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 7 Feb 2012 16:39:14 +0200 Subject: [PATCH 12/40] rtpenc: Allow packetizing H263 according to the old RFC 2190 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to newer RFCs, this packetization scheme should only be used for interfacing with legacy systems. Implementing this packetization mode properly requires parsing the full H263 bitstream to find macroblock boundaries (and knowing their macroblock and gob numbers and motion vector predictors). This implementation tries to look for GOB headers (which can be inserted by using -ps ), but if the GOBs aren't small enough to fit into the MTU, the packetizer blindly splits packets at any offset and claims it to be a GOB boundary (by using Mode A from the RFC). While not correct, this seems to work with some receivers. Signed-off-by: Martin Storsjö --- libavformat/Makefile | 1 + libavformat/rtp.c | 4 +- libavformat/rtpenc.c | 5 ++ libavformat/rtpenc.h | 6 ++ libavformat/rtpenc_h263.c | 7 +- libavformat/rtpenc_h263_rfc2190.c | 104 ++++++++++++++++++++++++++++++ libavformat/sdp.c | 3 + 7 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 libavformat/rtpenc_h263_rfc2190.c diff --git a/libavformat/Makefile b/libavformat/Makefile index 5c0e34242e..9682ece804 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -242,6 +242,7 @@ OBJS-$(CONFIG_RTP_MUXER) += rtp.o \ rtpenc_latm.o \ rtpenc_amr.o \ rtpenc_h263.o \ + rtpenc_h263_rfc2190.o \ rtpenc_mpv.o \ rtpenc.o \ rtpenc_h264.o \ diff --git a/libavformat/rtp.c b/libavformat/rtp.c index b6b4b72aa3..6516779feb 100644 --- a/libavformat/rtp.c +++ b/libavformat/rtp.c @@ -106,7 +106,9 @@ int ff_rtp_get_payload_type(AVFormatContext *fmt, AVCodecContext *codec) /* static payload type */ for (i = 0; AVRtpPayloadTypes[i].pt >= 0; ++i) if (AVRtpPayloadTypes[i].codec_id == codec->codec_id) { - if (codec->codec_id == CODEC_ID_H263) + if (codec->codec_id == CODEC_ID_H263 && (!fmt || + !fmt->oformat->priv_class || + !av_opt_flag_is_set(fmt->priv_data, "rtpflags", "rfc2190"))) continue; if (codec->codec_id == CODEC_ID_PCM_S16BE) if (codec->channels != AVRtpPayloadTypes[i].audio_channels) diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c index e19541798b..4d4e168c97 100644 --- a/libavformat/rtpenc.c +++ b/libavformat/rtpenc.c @@ -443,6 +443,11 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt) ff_rtp_send_h264(s1, pkt->data, size); break; case CODEC_ID_H263: + if (s->flags & FF_RTP_FLAG_RFC2190) { + ff_rtp_send_h263_rfc2190(s1, pkt->data, size); + break; + } + /* Fallthrough */ case CODEC_ID_H263P: ff_rtp_send_h263(s1, pkt->data, size); break; diff --git a/libavformat/rtpenc.h b/libavformat/rtpenc.h index fdad24947b..ff423a55d1 100644 --- a/libavformat/rtpenc.h +++ b/libavformat/rtpenc.h @@ -64,15 +64,18 @@ struct RTPMuxContext { typedef struct RTPMuxContext RTPMuxContext; #define FF_RTP_FLAG_MP4A_LATM 1 +#define FF_RTP_FLAG_RFC2190 2 #define FF_RTP_FLAG_OPTS(ctx, fieldname) \ { "rtpflags", "RTP muxer flags", offsetof(ctx, fieldname), AV_OPT_TYPE_FLAGS, {.dbl = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "rtpflags" }, \ { "latm", "Use MP4A-LATM packetization instead of MPEG4-GENERIC for AAC", 0, AV_OPT_TYPE_CONST, {.dbl = FF_RTP_FLAG_MP4A_LATM}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "rtpflags" }, \ + { "rfc2190", "Use RFC 2190 packetization instead of RFC 4629 for H.263", 0, AV_OPT_TYPE_CONST, {.dbl = FF_RTP_FLAG_RFC2190}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "rtpflags" }, \ void ff_rtp_send_data(AVFormatContext *s1, const uint8_t *buf1, int len, int m); void ff_rtp_send_h264(AVFormatContext *s1, const uint8_t *buf1, int size); void ff_rtp_send_h263(AVFormatContext *s1, const uint8_t *buf1, int size); +void ff_rtp_send_h263_rfc2190(AVFormatContext *s1, const uint8_t *buf1, int size); void ff_rtp_send_aac(AVFormatContext *s1, const uint8_t *buff, int size); void ff_rtp_send_latm(AVFormatContext *s1, const uint8_t *buff, int size); void ff_rtp_send_amr(AVFormatContext *s1, const uint8_t *buff, int size); @@ -80,4 +83,7 @@ void ff_rtp_send_mpegvideo(AVFormatContext *s1, const uint8_t *buf1, int size); void ff_rtp_send_xiph(AVFormatContext *s1, const uint8_t *buff, int size); void ff_rtp_send_vp8(AVFormatContext *s1, const uint8_t *buff, int size); +const uint8_t *ff_h263_find_resync_marker_reverse(const uint8_t *restrict start, + const uint8_t *restrict end); + #endif /* AVFORMAT_RTPENC_H */ diff --git a/libavformat/rtpenc_h263.c b/libavformat/rtpenc_h263.c index fbc696e1b4..87f0bd7981 100644 --- a/libavformat/rtpenc_h263.c +++ b/libavformat/rtpenc_h263.c @@ -23,8 +23,8 @@ #include "avformat.h" #include "rtpenc.h" -static const uint8_t *find_resync_marker_reverse(const uint8_t *restrict start, - const uint8_t *restrict end) +const uint8_t *ff_h263_find_resync_marker_reverse(const uint8_t *restrict start, + const uint8_t *restrict end) { const uint8_t *p = end - 1; start += 1; /* Make sure we never return the original start. */ @@ -63,7 +63,8 @@ void ff_rtp_send_h263(AVFormatContext *s1, const uint8_t *buf1, int size) /* Look for a better place to split the frame into packets. */ if (len < size) { - const uint8_t *end = find_resync_marker_reverse(buf1, buf1 + len); + const uint8_t *end = ff_h263_find_resync_marker_reverse(buf1, + buf1 + len); len = end - buf1; } diff --git a/libavformat/rtpenc_h263_rfc2190.c b/libavformat/rtpenc_h263_rfc2190.c new file mode 100644 index 0000000000..305c1a27c8 --- /dev/null +++ b/libavformat/rtpenc_h263_rfc2190.c @@ -0,0 +1,104 @@ +/* + * RTP packetization for H.263 video + * Copyright (c) 2012 Martin Storsjo + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avformat.h" +#include "rtpenc.h" +#include "libavcodec/put_bits.h" +#include "libavcodec/get_bits.h" + +struct H263Info { + int src; + int i; + int u; + int s; + int a; + int pb; + int tr; +}; + +static void send_mode_a(AVFormatContext *s1, const struct H263Info *info, + const uint8_t *buf, int len, int m) +{ + RTPMuxContext *s = s1->priv_data; + PutBitContext pb; + + init_put_bits(&pb, s->buf, 32); + put_bits(&pb, 1, 0); /* F - 0, mode A */ + put_bits(&pb, 1, 0); /* P - 0, normal I/P */ + put_bits(&pb, 3, 0); /* SBIT - 0 bits */ + put_bits(&pb, 3, 0); /* EBIT - 0 bits */ + put_bits(&pb, 3, info->src); /* SRC - source format */ + put_bits(&pb, 1, info->i); /* I - inter/intra */ + put_bits(&pb, 1, info->u); /* U - unrestricted motion vector */ + put_bits(&pb, 1, info->s); /* S - syntax-baesd arithmetic coding */ + put_bits(&pb, 1, info->a); /* A - advanced prediction */ + put_bits(&pb, 4, 0); /* R - reserved */ + put_bits(&pb, 2, 0); /* DBQ - 0 */ + put_bits(&pb, 3, 0); /* TRB - 0 */ + put_bits(&pb, 8, info->tr); /* TR */ + flush_put_bits(&pb); + memcpy(s->buf + 4, buf, len); + + ff_rtp_send_data(s1, s->buf, len + 4, m); +} + +void ff_rtp_send_h263_rfc2190(AVFormatContext *s1, const uint8_t *buf, int size) +{ + RTPMuxContext *s = s1->priv_data; + int len; + GetBitContext gb; + struct H263Info info = { 0 }; + + s->timestamp = s->cur_timestamp; + + init_get_bits(&gb, buf, size*8); + if (get_bits(&gb, 22) == 0x20) { /* Picture Start Code */ + info.tr = get_bits(&gb, 8); + skip_bits(&gb, 2); /* PTYPE start, H261 disambiguation */ + skip_bits(&gb, 3); /* Split screen, document camera, freeze picture release */ + info.src = get_bits(&gb, 3); + info.i = get_bits(&gb, 1); + info.u = get_bits(&gb, 1); + info.s = get_bits(&gb, 1); + info.a = get_bits(&gb, 1); + info.pb = get_bits(&gb, 1); + } + + while (size > 0) { + len = FFMIN(s->max_payload_size - 4, size); + + /* Look for a better place to split the frame into packets. */ + if (len < size) { + const uint8_t *end = ff_h263_find_resync_marker_reverse(buf, + buf + len); + len = end - buf; + if (len == s->max_payload_size - 4) + av_log(s1, AV_LOG_WARNING, + "No GOB boundary found within MTU size, splitting at " + "a random boundary\n"); + } + + send_mode_a(s1, &info, buf, len, len == size); + + buf += len; + size -= len; + } +} diff --git a/libavformat/sdp.c b/libavformat/sdp.c index 5e0bf72050..b2c4f7bcd8 100644 --- a/libavformat/sdp.c +++ b/libavformat/sdp.c @@ -404,6 +404,9 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, * actually specifies the maximum video size, but we only know * the current size. This is required for playback on Android * stagefright and on Samsung bada. */ + if (!fmt || !fmt->oformat->priv_class || + !av_opt_flag_is_set(fmt->priv_data, "rtpflags", "rfc2190") || + c->codec_id == CODEC_ID_H263P) av_strlcatf(buff, size, "a=rtpmap:%d H263-2000/90000\r\n" "a=framesize:%d %d-%d\r\n", payload_type, From ada4e362b9fa8cef033afb040f99b07069a7a5ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Sun, 5 Sep 2010 01:10:54 +0300 Subject: [PATCH 13/40] rtpenc: Add an error message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also return a proper error code. Signed-off-by: Martin Storsjö --- libavformat/rtpenc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c index 4d4e168c97..604c4a0552 100644 --- a/libavformat/rtpenc.c +++ b/libavformat/rtpenc.c @@ -85,8 +85,10 @@ static int rtp_write_header(AVFormatContext *s1) int max_packet_size, n; AVStream *st; - if (s1->nb_streams != 1) - return -1; + if (s1->nb_streams != 1) { + av_log(s1, AV_LOG_ERROR, "Only one stream supported in the RTP muxer\n"); + return AVERROR(EINVAL); + } st = s1->streams[0]; if (!is_supported(st->codec->codec_id)) { av_log(s1, AV_LOG_ERROR, "Unsupported codec %x\n", st->codec->codec_id); From 2b83e8b7005d531bc78b0fd4f699e9faa54ce9bb Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Wed, 22 Feb 2012 12:19:52 -0800 Subject: [PATCH 14/40] truemotion2: error out if the huffman tree has no nodes. This prevents crashers and errors further down when reading nodes in the empty tree. Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org --- libavcodec/truemotion2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/truemotion2.c b/libavcodec/truemotion2.c index 9e45045342..7be148c602 100644 --- a/libavcodec/truemotion2.c +++ b/libavcodec/truemotion2.c @@ -132,7 +132,7 @@ static int tm2_build_huff_table(TM2Context *ctx, TM2Codes *code) huff.val_bits, huff.max_bits); return -1; } - if((huff.nodes < 0) || (huff.nodes > 0x10000)) { + if((huff.nodes <= 0) || (huff.nodes > 0x10000)) { av_log(ctx->avctx, AV_LOG_ERROR, "Incorrect number of Huffman tree nodes: %i\n", huff.nodes); return -1; } From 8e8124e173c8584654d34fd9959c57dac951e36b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 20 Feb 2012 13:21:58 +0100 Subject: [PATCH 15/40] ljpegenc: switch to encode2(). --- libavcodec/ljpegenc.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/libavcodec/ljpegenc.c b/libavcodec/ljpegenc.c index ac5c716496..d2b9317114 100644 --- a/libavcodec/ljpegenc.c +++ b/libavcodec/ljpegenc.c @@ -32,21 +32,37 @@ #include "avcodec.h" #include "dsputil.h" +#include "internal.h" #include "mpegvideo.h" #include "mjpeg.h" #include "mjpegenc.h" -static int encode_picture_lossless(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){ +static int encode_picture_lossless(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ MpegEncContext * const s = avctx->priv_data; MJpegContext * const m = s->mjpeg_ctx; - AVFrame *pict = data; const int width= s->width; const int height= s->height; AVFrame * const p= (AVFrame*)&s->current_picture; const int predictor= avctx->prediction_method+1; + const int mb_width = (width + s->mjpeg_hsample[0] - 1) / s->mjpeg_hsample[0]; + const int mb_height = (height + s->mjpeg_vsample[0] - 1) / s->mjpeg_vsample[0]; + int ret, max_pkt_size = FF_MIN_BUFFER_SIZE; - init_put_bits(&s->pb, buf, buf_size); + if (avctx->pix_fmt == PIX_FMT_BGRA) + max_pkt_size += width * height * 3 * 4; + else { + max_pkt_size += mb_width * mb_height * 3 * 4 + * s->mjpeg_hsample[0] * s->mjpeg_vsample[0]; + } + if ((ret = ff_alloc_packet(pkt, max_pkt_size)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error getting output packet of size %d.\n", max_pkt_size); + return ret; + } + + init_put_bits(&s->pb, pkt->data, pkt->size); *p = *pict; p->pict_type= AV_PICTURE_TYPE_I; @@ -104,8 +120,6 @@ static int encode_picture_lossless(AVCodecContext *avctx, unsigned char *buf, in } }else{ int mb_x, mb_y, i; - const int mb_width = (width + s->mjpeg_hsample[0] - 1) / s->mjpeg_hsample[0]; - const int mb_height = (height + s->mjpeg_vsample[0] - 1) / s->mjpeg_vsample[0]; for(mb_y = 0; mb_y < mb_height; mb_y++) { if(s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < mb_width * 4 * 3 * s->mjpeg_hsample[0] * s->mjpeg_vsample[0]){ @@ -181,7 +195,11 @@ static int encode_picture_lossless(AVCodecContext *avctx, unsigned char *buf, in s->picture_number++; flush_put_bits(&s->pb); - return put_bits_ptr(&s->pb) - s->pb.buf; + pkt->size = put_bits_ptr(&s->pb) - s->pb.buf; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; // return (put_bits_count(&f->pb)+7)/8; } @@ -192,7 +210,7 @@ AVCodec ff_ljpeg_encoder = { //FIXME avoid MPV_* lossless JPEG should not need t .id = CODEC_ID_LJPEG, .priv_data_size = sizeof(MpegEncContext), .init = ff_MPV_encode_init, - .encode = encode_picture_lossless, + .encode2 = encode_picture_lossless, .close = ff_MPV_encode_end, .long_name = NULL_IF_CONFIG_SMALL("Lossless JPEG"), }; From a5f848c86db28b0c328593abeea4678903a66f07 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 6 Feb 2012 07:34:57 +0100 Subject: [PATCH 16/40] libxavs: split extradata writing out of encode_nals(). This is done in preparation for the following patch implementing encode2(). This commit is analogous to 05d699222dd5af4f5775f9890aa825ede05a144f for libx264. --- libavcodec/libxavs.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/libavcodec/libxavs.c b/libavcodec/libxavs.c index 8587eae99b..83f74a713c 100644 --- a/libavcodec/libxavs.c +++ b/libavcodec/libxavs.c @@ -86,14 +86,6 @@ static int encode_nals(AVCodecContext *ctx, uint8_t *buf, } for (i = 0; i < nnal; i++) { - /* Don't put the SEI in extradata. */ - if (skip_sei && nals[i].i_type == NAL_SEI) { - x4->sei = av_malloc( 5 + nals[i].i_payload * 4 / 3 ); - if (xavs_nal_encode(x4->sei, &x4->sei_size, 1, nals + i) < 0) - return -1; - - continue; - } s = xavs_nal_encode(p, &size, 1, nals + i); if (s < 0) return -1; @@ -329,12 +321,27 @@ static av_cold int XAVS_init(AVCodecContext *avctx) /* We Have PPS and SPS in AVS */ if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) { xavs_nal_t *nal; - int nnal, s; + int nnal, s, i, size; + uint8_t *p; s = xavs_encoder_headers(x4->enc, &nal, &nnal); - avctx->extradata = av_malloc(s); - avctx->extradata_size = encode_nals(avctx, avctx->extradata, s, nal, nnal, 1); + avctx->extradata = p = av_malloc(s); + for (i = 0; i < nnal; i++) { + /* Don't put the SEI in extradata. */ + if (nal[i].i_type == NAL_SEI) { + x4->sei = av_malloc( 5 + nal[i].i_payload * 4 / 3 ); + if (xavs_nal_encode(x4->sei, &x4->sei_size, 1, nal + i) < 0) + return -1; + + continue; + } + size = xavs_nal_encode(p, &s, 1, nal + i); + if (size < 0) + return -1; + p += size; + } + avctx->extradata_size = p - avctx->extradata; } return 0; } From d3b577f00d14fb8b8a962163a136dde96d9396b4 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 21 Feb 2012 22:57:59 +0100 Subject: [PATCH 17/40] libxavs: add an AVClass at the beginning of XavsContext. --- libavcodec/libxavs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/libxavs.c b/libavcodec/libxavs.c index 83f74a713c..f285ac4e04 100644 --- a/libavcodec/libxavs.c +++ b/libavcodec/libxavs.c @@ -37,6 +37,7 @@ #define XAVS_PART_B8X8 0x100 /* Analyze b16x8, b*/ typedef struct XavsContext { + AVClass *class; xavs_param_t params; xavs_t *enc; xavs_picture_t pic; From 84db922bf9066af37e38df6d22b6622b730a961f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 22 Feb 2012 07:38:13 +0100 Subject: [PATCH 18/40] libxavs: switch to encode2(). --- libavcodec/libxavs.c | 88 +++++++++++++++++++++++++++++++------------- 1 file changed, 63 insertions(+), 25 deletions(-) diff --git a/libavcodec/libxavs.c b/libavcodec/libxavs.c index f285ac4e04..9e45a3796b 100644 --- a/libavcodec/libxavs.c +++ b/libavcodec/libxavs.c @@ -54,6 +54,9 @@ typedef struct XavsContext { int fast_pskip; int mbtree; int mixed_refs; + + int64_t *pts_buffer; + int out_frame_count; } XavsContext; static void XAVS_log(void *p, int level, const char *fmt, va_list args) @@ -71,13 +74,24 @@ static void XAVS_log(void *p, int level, const char *fmt, va_list args) av_vlog(p, level_map[level], fmt, args); } -static int encode_nals(AVCodecContext *ctx, uint8_t *buf, - int size, xavs_nal_t *nals, - int nnal, int skip_sei) +static int encode_nals(AVCodecContext *ctx, AVPacket *pkt, + xavs_nal_t *nals, int nnal) { XavsContext *x4 = ctx->priv_data; - uint8_t *p = buf; - int i, s; + uint8_t *p; + int i, s, ret, size = x4->sei_size + FF_MIN_BUFFER_SIZE; + + if (!nnal) + return 0; + + for (i = 0; i < nnal; i++) + size += nals[i].i_payload; + + if ((ret = ff_alloc_packet(pkt, size)) < 0) { + av_log(ctx, AV_LOG_ERROR, "Error getting output packet of size %d.\n", size); + return ret; + } + p = pkt->data; /* Write the SEI as part of the first frame. */ if (x4->sei_size > 0 && nnal > 0) { @@ -92,17 +106,17 @@ static int encode_nals(AVCodecContext *ctx, uint8_t *buf, return -1; p += s; } + pkt->size = p - pkt->data; - return p - buf; + return 1; } -static int XAVS_frame(AVCodecContext *ctx, uint8_t *buf, - int bufsize, void *data) +static int XAVS_frame(AVCodecContext *ctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) { XavsContext *x4 = ctx->priv_data; - AVFrame *frame = data; xavs_nal_t *nal; - int nnal, i; + int nnal, i, ret; xavs_picture_t pic_out; x4->pic.img.i_csp = XAVS_CSP_I420; @@ -116,29 +130,44 @@ static int XAVS_frame(AVCodecContext *ctx, uint8_t *buf, x4->pic.i_pts = frame->pts; x4->pic.i_type = XAVS_TYPE_AUTO; + x4->pts_buffer[ctx->frame_number % (ctx->max_b_frames+1)] = frame->pts; } if (xavs_encoder_encode(x4->enc, &nal, &nnal, frame? &x4->pic: NULL, &pic_out) < 0) return -1; - bufsize = encode_nals(ctx, buf, bufsize, nal, nnal, 0); + ret = encode_nals(ctx, pkt, nal, nnal); - if (bufsize < 0) + if (ret < 0) return -1; - if (!bufsize && !frame && !(x4->end_of_stream)){ - buf[bufsize] = 0x0; - buf[bufsize+1] = 0x0; - buf[bufsize+2] = 0x01; - buf[bufsize+3] = 0xb1; - bufsize += 4; - x4->end_of_stream = END_OF_STREAM; - return bufsize; + if (!ret) { + if (!frame && !(x4->end_of_stream)) { + if ((ret = ff_alloc_packet(pkt, 4)) < 0) + return ret; + + pkt->data[0] = 0x0; + pkt->data[1] = 0x0; + pkt->data[2] = 0x01; + pkt->data[3] = 0xb1; + pkt->dts = 2*x4->pts_buffer[(x4->out_frame_count-1)%(ctx->max_b_frames+1)] - + x4->pts_buffer[(x4->out_frame_count-2)%(ctx->max_b_frames+1)]; + x4->end_of_stream = END_OF_STREAM; + *got_packet = 1; + } + return 0; } - /* FIXME: libxavs now provides DTS */ - /* but AVFrame doesn't have a field for it. */ + x4->out_pic.pts = pic_out.i_pts; + pkt->pts = pic_out.i_pts; + if (ctx->has_b_frames) { + if (!x4->out_frame_count) + pkt->dts = pkt->pts - (x4->pts_buffer[1] - x4->pts_buffer[0]); + else + pkt->dts = x4->pts_buffer[(x4->out_frame_count-1)%(ctx->max_b_frames+1)]; + } else + pkt->dts = pkt->pts; switch (pic_out.i_type) { case XAVS_TYPE_IDR: @@ -156,11 +185,16 @@ static int XAVS_frame(AVCodecContext *ctx, uint8_t *buf, /* There is no IDR frame in AVS JiZhun */ /* Sequence header is used as a flag */ - x4->out_pic.key_frame = pic_out.i_type == XAVS_TYPE_I; + if (pic_out.i_type == XAVS_TYPE_I) { + x4->out_pic.key_frame = 1; + pkt->flags |= AV_PKT_FLAG_KEY; + } x4->out_pic.quality = (pic_out.i_qpplus1 - 1) * FF_QP2LAMBDA; - return bufsize; + x4->out_frame_count++; + *got_packet = ret; + return 0; } static av_cold int XAVS_close(AVCodecContext *avctx) @@ -169,6 +203,7 @@ static av_cold int XAVS_close(AVCodecContext *avctx) av_freep(&avctx->extradata); av_free(x4->sei); + av_freep(&x4->pts_buffer); if (x4->enc) xavs_encoder_close(x4->enc); @@ -317,6 +352,9 @@ static av_cold int XAVS_init(AVCodecContext *avctx) if (!x4->enc) return -1; + if (!(x4->pts_buffer = av_mallocz((avctx->max_b_frames+1) * sizeof(*x4->pts_buffer)))) + return AVERROR(ENOMEM); + avctx->coded_frame = &x4->out_pic; /* TAG: Do we have GLOBAL HEADER in AVS */ /* We Have PPS and SPS in AVS */ @@ -384,7 +422,7 @@ AVCodec ff_libxavs_encoder = { .id = CODEC_ID_CAVS, .priv_data_size = sizeof(XavsContext), .init = XAVS_init, - .encode = XAVS_frame, + .encode2 = XAVS_frame, .close = XAVS_close, .capabilities = CODEC_CAP_DELAY | CODEC_CAP_AUTO_THREADS, .pix_fmts = (const enum PixelFormat[]) { PIX_FMT_YUV420P, PIX_FMT_NONE }, From 19a65b5be47944c607a9e979edb098924d95f2e4 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Wed, 22 Feb 2012 16:46:31 -0800 Subject: [PATCH 19/40] swscale: fix overflows in filterPos[] calculation for large sizes. Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org --- libswscale/utils.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libswscale/utils.c b/libswscale/utils.c index 6ae8af64e9..796adb60e1 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -244,7 +244,7 @@ static int initFilter(int16_t **outFilter, int16_t **filterPos, int *outFilterSi xDstInSrc+= xInc; } } else { - int xDstInSrc; + int64_t xDstInSrc; int sizeFactor; if (flags&SWS_BICUBIC) sizeFactor= 4; @@ -810,8 +810,8 @@ int sws_init_context(SwsContext *c, SwsFilter *srcFilter, SwsFilter *dstFilter) if (!dstFilter) dstFilter= &dummyFilter; if (!srcFilter) srcFilter= &dummyFilter; - c->lumXInc= ((srcW<<16) + (dstW>>1))/dstW; - c->lumYInc= ((srcH<<16) + (dstH>>1))/dstH; + c->lumXInc= (((int64_t)srcW<<16) + (dstW>>1))/dstW; + c->lumYInc= (((int64_t)srcH<<16) + (dstH>>1))/dstH; c->dstFormatBpp = av_get_bits_per_pixel(&av_pix_fmt_descriptors[dstFormat]); c->srcFormatBpp = av_get_bits_per_pixel(&av_pix_fmt_descriptors[srcFormat]); c->vRounder= 4* 0x0001000100010001ULL; @@ -897,8 +897,8 @@ int sws_init_context(SwsContext *c, SwsFilter *srcFilter, SwsFilter *dstFilter) else c->canMMX2BeUsed=0; - c->chrXInc= ((c->chrSrcW<<16) + (c->chrDstW>>1))/c->chrDstW; - c->chrYInc= ((c->chrSrcH<<16) + (c->chrDstH>>1))/c->chrDstH; + c->chrXInc= (((int64_t)c->chrSrcW<<16) + (c->chrDstW>>1))/c->chrDstW; + c->chrYInc= (((int64_t)c->chrSrcH<<16) + (c->chrDstH>>1))/c->chrDstH; // match pixel 0 of the src to pixel 0 of dst and match pixel n-2 of src to pixel n-2 of dst // but only for the FAST_BILINEAR mode otherwise do correct scaling @@ -913,8 +913,8 @@ int sws_init_context(SwsContext *c, SwsFilter *srcFilter, SwsFilter *dstFilter) } //we don't use the x86 asm scaler if MMX is available else if (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) { - c->lumXInc = ((srcW-2)<<16)/(dstW-2) - 20; - c->chrXInc = ((c->chrSrcW-2)<<16)/(c->chrDstW-2) - 20; + c->lumXInc = ((int64_t)(srcW-2)<<16)/(dstW-2) - 20; + c->chrXInc = ((int64_t)(c->chrSrcW-2)<<16)/(c->chrDstW-2) - 20; } } From 491865b57db5fbb3053c221fd6d94b0435cad105 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Wed, 22 Feb 2012 16:47:14 -0800 Subject: [PATCH 20/40] swscale: fix underflows in firstline calculations for extreme resizes. Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org --- libswscale/swscale.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libswscale/swscale.c b/libswscale/swscale.c index b231302216..bd909bf163 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -407,9 +407,9 @@ static int swScale(SwsContext *c, const uint8_t* src[], (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? dst[3] + dstStride[3] * dstY : NULL, }; - const int firstLumSrcY= vLumFilterPos[dstY]; //First line needed as input - const int firstLumSrcY2= vLumFilterPos[FFMIN(dstY | ((1<chrDstVSubSample) - 1), dstH-1)]; - const int firstChrSrcY= vChrFilterPos[chrDstY]; //First line needed as input + const int firstLumSrcY= FFMAX(1 - vLumFilterSize, vLumFilterPos[dstY]); //First line needed as input + const int firstLumSrcY2= FFMAX(1 - vLumFilterSize, vLumFilterPos[FFMIN(dstY | ((1<chrDstVSubSample) - 1), dstH-1)]); + const int firstChrSrcY= FFMAX(1 - vChrFilterSize, vChrFilterPos[chrDstY]); //First line needed as input // Last line needed as input int lastLumSrcY = FFMIN(c->srcH, firstLumSrcY + vLumFilterSize) - 1; From 1d8c4af396b6ed84c84b5ebf0bf1163c4a7a3017 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Wed, 22 Feb 2012 16:48:38 -0800 Subject: [PATCH 21/40] swscale: take first/lastline over/underflows into account for MMX. Fixes crashes for extremely large resizes (several 100-fold). Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org --- libswscale/x86/swscale_mmx.c | 38 ++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/libswscale/x86/swscale_mmx.c b/libswscale/x86/swscale_mmx.c index 764472e95e..64d5f0fc9d 100644 --- a/libswscale/x86/swscale_mmx.c +++ b/libswscale/x86/swscale_mmx.c @@ -117,6 +117,44 @@ void updateMMXDitherTables(SwsContext *c, int dstY, int lumBufIndex, int chrBufI const int16_t **chrUSrcPtr= (const int16_t **) chrUPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize; const int16_t **alpSrcPtr= (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? (const int16_t **) alpPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize : NULL; int i; + + if (firstLumSrcY < 0 || firstLumSrcY + vLumFilterSize > c->srcH) { + const int16_t **tmpY = (const int16_t **) lumPixBuf + 2 * vLumBufSize; + int neg = -firstLumSrcY, i, end = FFMIN(c->srcH - firstLumSrcY, vLumFilterSize); + for (i = 0; i < neg; i++) + tmpY[i] = lumSrcPtr[neg]; + for ( ; i < end; i++) + tmpY[i] = lumSrcPtr[i]; + for ( ; i < vLumFilterSize; i++) + tmpY[i] = tmpY[i-1]; + lumSrcPtr = tmpY; + + if (alpSrcPtr) { + const int16_t **tmpA = (const int16_t **) alpPixBuf + 2 * vLumBufSize; + for (i = 0; i < neg; i++) + tmpA[i] = alpSrcPtr[neg]; + for ( ; i < end; i++) + tmpA[i] = alpSrcPtr[i]; + for ( ; i < vLumFilterSize; i++) + tmpA[i] = tmpA[i - 1]; + alpSrcPtr = tmpA; + } + } + if (firstChrSrcY < 0 || firstChrSrcY + vChrFilterSize > c->chrSrcH) { + const int16_t **tmpU = (const int16_t **) chrUPixBuf + 2 * vChrBufSize; + int neg = -firstChrSrcY, i, end = FFMIN(c->chrSrcH - firstChrSrcY, vChrFilterSize); + for (i = 0; i < neg; i++) { + tmpU[i] = chrUSrcPtr[neg]; + } + for ( ; i < end; i++) { + tmpU[i] = chrUSrcPtr[i]; + } + for ( ; i < vChrFilterSize; i++) { + tmpU[i] = tmpU[i - 1]; + } + chrUSrcPtr = tmpU; + } + if (flags & SWS_ACCURATE_RND) { int s= APCK_SIZE / 8; for (i=0; i Date: Wed, 22 Feb 2012 14:22:56 -0800 Subject: [PATCH 22/40] lcl: don't overwrite input memory. If the PNG filter is enabled, a PNG-style filter will run over the input buffer, writing into the buffer. Therefore, if no zlib compression was used, ensure that we copy into a temporary buffer, otherwise we overwrite user-provided input data. --- libavcodec/lcldec.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libavcodec/lcldec.c b/libavcodec/lcldec.c index b66a3ce65b..a7f0bde23e 100644 --- a/libavcodec/lcldec.c +++ b/libavcodec/lcldec.c @@ -236,9 +236,14 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPac * gives a file with ZLIB fourcc, but frame is really uncompressed. * To be sure that's true check also frame size */ if (c->compression == COMP_ZLIB_NORMAL && c->imgtype == IMGTYPE_RGB24 && - len == width * height * 3) - break; - if (c->flags & FLAG_MULTITHREAD) { + len == width * height * 3) { + if (c->flags & FLAG_PNGFILTER) { + memcpy(c->decomp_buf, encoded, len); + encoded = c->decomp_buf; + } else { + break; + } + } else if (c->flags & FLAG_MULTITHREAD) { int ret; mthread_inlen = AV_RL32(encoded); mthread_inlen = FFMIN(mthread_inlen, len - 8); From b315042c8ce984bec431c5965120853a843cbfa5 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Thu, 23 Feb 2012 17:17:01 +0100 Subject: [PATCH 23/40] Remove libpostproc. This library does not fit into Libav as a whole and its code is just a maintenance burden. Furthermore it is now available as an external project, which completely obviates any reason to keep it around. URL: http://git.videolan.org/?p=libpostproc.git --- .gitignore | 1 - Changelog | 1 + LICENSE | 1 - Makefile | 3 +- cmdutils.c | 6 - configure | 8 +- doc/APIchanges | 1 - libavutil/avutil.h | 1 - libpostproc/Makefile | 6 - libpostproc/libpostproc.v | 4 - libpostproc/postprocess.c | 1071 ------ libpostproc/postprocess.h | 104 - libpostproc/postprocess_altivec_template.c | 1210 ------- libpostproc/postprocess_internal.h | 179 - libpostproc/postprocess_template.c | 3634 -------------------- 15 files changed, 3 insertions(+), 6227 deletions(-) delete mode 100644 libpostproc/Makefile delete mode 100644 libpostproc/libpostproc.v delete mode 100644 libpostproc/postprocess.c delete mode 100644 libpostproc/postprocess.h delete mode 100644 libpostproc/postprocess_altivec_template.c delete mode 100644 libpostproc/postprocess_internal.h delete mode 100644 libpostproc/postprocess_template.c diff --git a/.gitignore b/.gitignore index 754051d79d..e08648ba03 100644 --- a/.gitignore +++ b/.gitignore @@ -24,7 +24,6 @@ libavfilter/libavfilter* libavformat/libavformat* libavutil/avconfig.h libavutil/libavutil* -libpostproc/libpostproc* libswscale/libswscale* tests/audiogen tests/base64 diff --git a/Changelog b/Changelog index 23d9f7eabb..65accca721 100644 --- a/Changelog +++ b/Changelog @@ -9,6 +9,7 @@ version : - CDXL demuxer and decoder - Apple ProRes encoder - Sun Rasterfile Encoder +- remove libpostproc version 0.8: diff --git a/LICENSE b/LICENSE index 293be1dcf6..97923b1380 100644 --- a/LICENSE +++ b/LICENSE @@ -13,7 +13,6 @@ configure to activate them. In this case, Libav's license changes to GPL v2+. Specifically, the GPL parts of Libav are -- libpostproc - optional x86 optimizations in the files libavcodec/x86/idct_mmx.c - the X11 grabber in libavdevice/x11grab.c diff --git a/Makefile b/Makefile index 006e35cce6..ae9191cd10 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ $(foreach VAR,$(SILENT),$(eval override $(VAR) = @$($(VAR)))) $(eval INSTALL = @$(call ECHO,INSTALL,$$(^:$(SRC_PATH)/%=%)); $(INSTALL)) endif -ALLFFLIBS = avcodec avdevice avfilter avformat avutil postproc swscale +ALLFFLIBS = avcodec avdevice avfilter avformat avutil swscale IFLAGS := -I. -I$(SRC_PATH) CPPFLAGS := $(IFLAGS) $(CPPFLAGS) @@ -72,7 +72,6 @@ FFLIBS-$(CONFIG_AVDEVICE) += avdevice FFLIBS-$(CONFIG_AVFILTER) += avfilter FFLIBS-$(CONFIG_AVFORMAT) += avformat FFLIBS-$(CONFIG_AVCODEC) += avcodec -FFLIBS-$(CONFIG_POSTPROC) += postproc FFLIBS-$(CONFIG_SWSCALE) += swscale FFLIBS := avutil diff --git a/cmdutils.c b/cmdutils.c index 8ee2cddf68..985931cce6 100644 --- a/cmdutils.c +++ b/cmdutils.c @@ -33,9 +33,6 @@ #include "libavfilter/avfilter.h" #include "libavdevice/avdevice.h" #include "libswscale/swscale.h" -#if CONFIG_POSTPROC -#include "libpostproc/postprocess.h" -#endif #include "libavutil/avstring.h" #include "libavutil/mathematics.h" #include "libavutil/parseutils.h" @@ -496,9 +493,6 @@ static void print_all_libs_info(int flags, int level) PRINT_LIB_INFO(avdevice, AVDEVICE, flags, level); PRINT_LIB_INFO(avfilter, AVFILTER, flags, level); PRINT_LIB_INFO(swscale, SWSCALE, flags, level); -#if CONFIG_POSTPROC - PRINT_LIB_INFO(postproc, POSTPROC, flags, level); -#endif } void show_banner(void) diff --git a/configure b/configure index 5e62e22f36..cbeffbb6f6 100755 --- a/configure +++ b/configure @@ -88,7 +88,6 @@ Configuration options: --disable-avcodec disable libavcodec build --disable-avformat disable libavformat build --disable-swscale disable libswscale build - --enable-postproc enable libpostproc build (deprecated) [no] --disable-avfilter disable video filter support [no] --disable-pthreads disable pthreads [auto] --disable-w32threads disable Win32 threads [auto] @@ -974,7 +973,6 @@ CONFIG_LIST=" nonfree openssl pic - postproc rdft rtpdec runtime_cpudetect @@ -1532,7 +1530,6 @@ yadif_filter_deps="gpl" # libraries avdevice_deps="avcodec avformat" avformat_deps="avcodec" -postproc_deps="gpl" # programs avconv_deps="avcodec avformat swscale" @@ -3066,7 +3063,7 @@ enabled extra_warnings && check_cflags -Winline # add some linker flags check_ldflags -Wl,--warn-common -check_ldflags -Wl,-rpath-link=libpostproc:libswscale:libavfilter:libavdevice:libavformat:libavcodec:libavutil +check_ldflags -Wl,-rpath-link=libswscale:libavfilter:libavdevice:libavformat:libavcodec:libavutil test_ldflags -Wl,-Bsymbolic && append SHFLAGS -Wl,-Bsymbolic enabled xmm_clobber_test && \ @@ -3222,7 +3219,6 @@ echo "optimize for size ${small-no}" echo "optimizations ${optimizations-no}" echo "static ${static-no}" echo "shared ${shared-no}" -echo "postprocessing support ${postproc-no}" echo "new filter support ${avfilter-no}" echo "network support ${network-no}" echo "threading support ${thread_type-no}" @@ -3374,7 +3370,6 @@ get_version LIBAVDEVICE libavdevice/avdevice.h get_version LIBAVFILTER libavfilter/version.h get_version LIBAVFORMAT libavformat/version.h get_version LIBAVUTIL libavutil/avutil.h -get_version LIBPOSTPROC libpostproc/postprocess.h get_version LIBSWSCALE libswscale/swscale.h cat > $TMPH < - * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file - * postprocessing. - */ - -/* - C MMX MMX2 3DNow AltiVec -isVertDC Ec Ec Ec -isVertMinMaxOk Ec Ec Ec -doVertLowPass E e e Ec -doVertDefFilter Ec Ec e e Ec -isHorizDC Ec Ec Ec -isHorizMinMaxOk a E Ec -doHorizLowPass E e e Ec -doHorizDefFilter Ec Ec e e Ec -do_a_deblock Ec E Ec E -deRing E e e* Ecp -Vertical RKAlgo1 E a a -Horizontal RKAlgo1 a a -Vertical X1# a E E -Horizontal X1# a E E -LinIpolDeinterlace e E E* -CubicIpolDeinterlace a e e* -LinBlendDeinterlace e E E* -MedianDeinterlace# E Ec Ec -TempDeNoiser# E e e Ec - -* I do not have a 3DNow! CPU -> it is untested, but no one said it does not work so it seems to work -# more or less selfinvented filters so the exactness is not too meaningful -E = Exact implementation -e = almost exact implementation (slightly different rounding,...) -a = alternative / approximate impl -c = checked against the other implementations (-vo md5) -p = partially optimized, still some work to do -*/ - -/* -TODO: -reduce the time wasted on the mem transfer -unroll stuff if instructions depend too much on the prior one -move YScale thing to the end instead of fixing QP -write a faster and higher quality deblocking filter :) -make the mainloop more flexible (variable number of blocks at once - (the if/else stuff per block is slowing things down) -compare the quality & speed of all filters -split this huge file -optimize c versions -try to unroll inner for(x=0 ... loop to avoid these damn if(x ... checks -... -*/ - -//Changelog: use git log - -#include "config.h" -#include "libavutil/avutil.h" -#include -#include -#include -#include -//#undef HAVE_MMX2 -//#define HAVE_AMD3DNOW -//#undef HAVE_MMX -//#undef ARCH_X86 -//#define DEBUG_BRIGHTNESS -#include "postprocess.h" -#include "postprocess_internal.h" -#include "libavutil/avstring.h" - -unsigned postproc_version(void) -{ - return LIBPOSTPROC_VERSION_INT; -} - -const char *postproc_configuration(void) -{ - return LIBAV_CONFIGURATION; -} - -const char *postproc_license(void) -{ -#define LICENSE_PREFIX "libpostproc license: " - return LICENSE_PREFIX LIBAV_LICENSE + sizeof(LICENSE_PREFIX) - 1; -} - -#if HAVE_ALTIVEC_H -#include -#endif - -#define GET_MODE_BUFFER_SIZE 500 -#define OPTIONS_ARRAY_SIZE 10 -#define BLOCK_SIZE 8 -#define TEMP_STRIDE 8 -//#define NUM_BLOCKS_AT_ONCE 16 //not used yet - -#if ARCH_X86 -DECLARE_ASM_CONST(8, uint64_t, w05)= 0x0005000500050005LL; -DECLARE_ASM_CONST(8, uint64_t, w04)= 0x0004000400040004LL; -DECLARE_ASM_CONST(8, uint64_t, w20)= 0x0020002000200020LL; -DECLARE_ASM_CONST(8, uint64_t, b00)= 0x0000000000000000LL; -DECLARE_ASM_CONST(8, uint64_t, b01)= 0x0101010101010101LL; -DECLARE_ASM_CONST(8, uint64_t, b02)= 0x0202020202020202LL; -DECLARE_ASM_CONST(8, uint64_t, b08)= 0x0808080808080808LL; -DECLARE_ASM_CONST(8, uint64_t, b80)= 0x8080808080808080LL; -#endif - -DECLARE_ASM_CONST(8, int, deringThreshold)= 20; - - -static struct PPFilter filters[]= -{ - {"hb", "hdeblock", 1, 1, 3, H_DEBLOCK}, - {"vb", "vdeblock", 1, 2, 4, V_DEBLOCK}, -/* {"hr", "rkhdeblock", 1, 1, 3, H_RK1_FILTER}, - {"vr", "rkvdeblock", 1, 2, 4, V_RK1_FILTER},*/ - {"h1", "x1hdeblock", 1, 1, 3, H_X1_FILTER}, - {"v1", "x1vdeblock", 1, 2, 4, V_X1_FILTER}, - {"ha", "ahdeblock", 1, 1, 3, H_A_DEBLOCK}, - {"va", "avdeblock", 1, 2, 4, V_A_DEBLOCK}, - {"dr", "dering", 1, 5, 6, DERING}, - {"al", "autolevels", 0, 1, 2, LEVEL_FIX}, - {"lb", "linblenddeint", 1, 1, 4, LINEAR_BLEND_DEINT_FILTER}, - {"li", "linipoldeint", 1, 1, 4, LINEAR_IPOL_DEINT_FILTER}, - {"ci", "cubicipoldeint", 1, 1, 4, CUBIC_IPOL_DEINT_FILTER}, - {"md", "mediandeint", 1, 1, 4, MEDIAN_DEINT_FILTER}, - {"fd", "ffmpegdeint", 1, 1, 4, FFMPEG_DEINT_FILTER}, - {"l5", "lowpass5", 1, 1, 4, LOWPASS5_DEINT_FILTER}, - {"tn", "tmpnoise", 1, 7, 8, TEMP_NOISE_FILTER}, - {"fq", "forcequant", 1, 0, 0, FORCE_QUANT}, - {NULL, NULL,0,0,0,0} //End Marker -}; - -static const char *replaceTable[]= -{ - "default", "hb:a,vb:a,dr:a", - "de", "hb:a,vb:a,dr:a", - "fast", "h1:a,v1:a,dr:a", - "fa", "h1:a,v1:a,dr:a", - "ac", "ha:a:128:7,va:a,dr:a", - NULL //End Marker -}; - - -#if ARCH_X86 -static inline void prefetchnta(void *p) -{ - __asm__ volatile( "prefetchnta (%0)\n\t" - : : "r" (p) - ); -} - -static inline void prefetcht0(void *p) -{ - __asm__ volatile( "prefetcht0 (%0)\n\t" - : : "r" (p) - ); -} - -static inline void prefetcht1(void *p) -{ - __asm__ volatile( "prefetcht1 (%0)\n\t" - : : "r" (p) - ); -} - -static inline void prefetcht2(void *p) -{ - __asm__ volatile( "prefetcht2 (%0)\n\t" - : : "r" (p) - ); -} -#endif - -/* The horizontal functions exist only in C because the MMX - * code is faster with vertical filters and transposing. */ - -/** - * Check if the given 8x8 Block is mostly "flat" - */ -static inline int isHorizDC_C(uint8_t src[], int stride, PPContext *c) -{ - int numEq= 0; - int y; - const int dcOffset= ((c->nonBQP*c->ppMode.baseDcDiff)>>8) + 1; - const int dcThreshold= dcOffset*2 + 1; - - for(y=0; y c->ppMode.flatnessThreshold; -} - -/** - * Check if the middle 8x8 Block in the given 8x16 block is flat - */ -static inline int isVertDC_C(uint8_t src[], int stride, PPContext *c) -{ - int numEq= 0; - int y; - const int dcOffset= ((c->nonBQP*c->ppMode.baseDcDiff)>>8) + 1; - const int dcThreshold= dcOffset*2 + 1; - - src+= stride*4; // src points to begin of the 8x8 Block - for(y=0; y c->ppMode.flatnessThreshold; -} - -static inline int isHorizMinMaxOk_C(uint8_t src[], int stride, int QP) -{ - int i; - for(i=0; i<2; i++){ - if((unsigned)(src[0] - src[5] + 2*QP) > 4*QP) return 0; - src += stride; - if((unsigned)(src[2] - src[7] + 2*QP) > 4*QP) return 0; - src += stride; - if((unsigned)(src[4] - src[1] + 2*QP) > 4*QP) return 0; - src += stride; - if((unsigned)(src[6] - src[3] + 2*QP) > 4*QP) return 0; - src += stride; - } - return 1; -} - -static inline int isVertMinMaxOk_C(uint8_t src[], int stride, int QP) -{ - int x; - src+= stride*4; - for(x=0; x 4*QP) return 0; - if((unsigned)(src[1+x + 2*stride] - src[1+x + 7*stride] + 2*QP) > 4*QP) return 0; - if((unsigned)(src[2+x + 4*stride] - src[2+x + 1*stride] + 2*QP) > 4*QP) return 0; - if((unsigned)(src[3+x + 6*stride] - src[3+x + 3*stride] + 2*QP) > 4*QP) return 0; - } - return 1; -} - -static inline int horizClassify_C(uint8_t src[], int stride, PPContext *c) -{ - if( isHorizDC_C(src, stride, c) ){ - if( isHorizMinMaxOk_C(src, stride, c->QP) ) - return 1; - else - return 0; - }else{ - return 2; - } -} - -static inline int vertClassify_C(uint8_t src[], int stride, PPContext *c) -{ - if( isVertDC_C(src, stride, c) ){ - if( isVertMinMaxOk_C(src, stride, c->QP) ) - return 1; - else - return 0; - }else{ - return 2; - } -} - -static inline void doHorizDefFilter_C(uint8_t dst[], int stride, PPContext *c) -{ - int y; - for(y=0; yQP){ - const int q=(dst[3] - dst[4])/2; - const int leftEnergy= 5*(dst[2] - dst[1]) + 2*(dst[0] - dst[3]); - const int rightEnergy= 5*(dst[6] - dst[5]) + 2*(dst[4] - dst[7]); - - int d= FFABS(middleEnergy) - FFMIN( FFABS(leftEnergy), FFABS(rightEnergy) ); - d= FFMAX(d, 0); - - d= (5*d + 32) >> 6; - d*= FFSIGN(-middleEnergy); - - if(q>0) - { - d= d<0 ? 0 : d; - d= d>q ? q : d; - } - else - { - d= d>0 ? 0 : d; - d= dQP ? dst[-1] : dst[0]; - const int last= FFABS(dst[8] - dst[7]) < c->QP ? dst[8] : dst[7]; - - int sums[10]; - sums[0] = 4*first + dst[0] + dst[1] + dst[2] + 4; - sums[1] = sums[0] - first + dst[3]; - sums[2] = sums[1] - first + dst[4]; - sums[3] = sums[2] - first + dst[5]; - sums[4] = sums[3] - first + dst[6]; - sums[5] = sums[4] - dst[0] + dst[7]; - sums[6] = sums[5] - dst[1] + last; - sums[7] = sums[6] - dst[2] + last; - sums[8] = sums[7] - dst[3] + last; - sums[9] = sums[8] - dst[4] + last; - - dst[0]= (sums[0] + sums[2] + 2*dst[0])>>4; - dst[1]= (sums[1] + sums[3] + 2*dst[1])>>4; - dst[2]= (sums[2] + sums[4] + 2*dst[2])>>4; - dst[3]= (sums[3] + sums[5] + 2*dst[3])>>4; - dst[4]= (sums[4] + sums[6] + 2*dst[4])>>4; - dst[5]= (sums[5] + sums[7] + 2*dst[5])>>4; - dst[6]= (sums[6] + sums[8] + 2*dst[6])>>4; - dst[7]= (sums[7] + sums[9] + 2*dst[7])>>4; - - dst+= stride; - } -} - -/** - * Experimental Filter 1 (Horizontal) - * will not damage linear gradients - * Flat blocks should look like they were passed through the (1,1,2,2,4,2,2,1,1) 9-Tap filter - * can only smooth blocks at the expected locations (it cannot smooth them if they did move) - * MMX2 version does correct clipping C version does not - * not identical with the vertical one - */ -static inline void horizX1Filter(uint8_t *src, int stride, int QP) -{ - int y; - static uint64_t *lut= NULL; - if(lut==NULL) - { - int i; - lut = av_malloc(256*8); - for(i=0; i<256; i++) - { - int v= i < 128 ? 2*i : 2*(i-256); -/* -//Simulate 112242211 9-Tap filter - uint64_t a= (v/16) & 0xFF; - uint64_t b= (v/8) & 0xFF; - uint64_t c= (v/4) & 0xFF; - uint64_t d= (3*v/8) & 0xFF; -*/ -//Simulate piecewise linear interpolation - uint64_t a= (v/16) & 0xFF; - uint64_t b= (v*3/16) & 0xFF; - uint64_t c= (v*5/16) & 0xFF; - uint64_t d= (7*v/16) & 0xFF; - uint64_t A= (0x100 - a)&0xFF; - uint64_t B= (0x100 - b)&0xFF; - uint64_t C= (0x100 - c)&0xFF; - uint64_t D= (0x100 - c)&0xFF; - - lut[i] = (a<<56) | (b<<48) | (c<<40) | (d<<32) | - (D<<24) | (C<<16) | (B<<8) | (A); - //lut[i] = (v<<32) | (v<<24); - } - } - - for(y=0; yQP; - const int dcOffset= ((c->nonBQP*c->ppMode.baseDcDiff)>>8) + 1; - const int dcThreshold= dcOffset*2 + 1; -//START_TIMER - src+= step*4; // src points to begin of the 8x8 Block - for(y=0; y<8; y++){ - int numEq= 0; - - if(((unsigned)(src[-1*step] - src[0*step] + dcOffset)) < dcThreshold) numEq++; - if(((unsigned)(src[ 0*step] - src[1*step] + dcOffset)) < dcThreshold) numEq++; - if(((unsigned)(src[ 1*step] - src[2*step] + dcOffset)) < dcThreshold) numEq++; - if(((unsigned)(src[ 2*step] - src[3*step] + dcOffset)) < dcThreshold) numEq++; - if(((unsigned)(src[ 3*step] - src[4*step] + dcOffset)) < dcThreshold) numEq++; - if(((unsigned)(src[ 4*step] - src[5*step] + dcOffset)) < dcThreshold) numEq++; - if(((unsigned)(src[ 5*step] - src[6*step] + dcOffset)) < dcThreshold) numEq++; - if(((unsigned)(src[ 6*step] - src[7*step] + dcOffset)) < dcThreshold) numEq++; - if(((unsigned)(src[ 7*step] - src[8*step] + dcOffset)) < dcThreshold) numEq++; - if(numEq > c->ppMode.flatnessThreshold){ - int min, max, x; - - if(src[0] > src[step]){ - max= src[0]; - min= src[step]; - }else{ - max= src[step]; - min= src[0]; - } - for(x=2; x<8; x+=2){ - if(src[x*step] > src[(x+1)*step]){ - if(src[x *step] > max) max= src[ x *step]; - if(src[(x+1)*step] < min) min= src[(x+1)*step]; - }else{ - if(src[(x+1)*step] > max) max= src[(x+1)*step]; - if(src[ x *step] < min) min= src[ x *step]; - } - } - if(max-min < 2*QP){ - const int first= FFABS(src[-1*step] - src[0]) < QP ? src[-1*step] : src[0]; - const int last= FFABS(src[8*step] - src[7*step]) < QP ? src[8*step] : src[7*step]; - - int sums[10]; - sums[0] = 4*first + src[0*step] + src[1*step] + src[2*step] + 4; - sums[1] = sums[0] - first + src[3*step]; - sums[2] = sums[1] - first + src[4*step]; - sums[3] = sums[2] - first + src[5*step]; - sums[4] = sums[3] - first + src[6*step]; - sums[5] = sums[4] - src[0*step] + src[7*step]; - sums[6] = sums[5] - src[1*step] + last; - sums[7] = sums[6] - src[2*step] + last; - sums[8] = sums[7] - src[3*step] + last; - sums[9] = sums[8] - src[4*step] + last; - - src[0*step]= (sums[0] + sums[2] + 2*src[0*step])>>4; - src[1*step]= (sums[1] + sums[3] + 2*src[1*step])>>4; - src[2*step]= (sums[2] + sums[4] + 2*src[2*step])>>4; - src[3*step]= (sums[3] + sums[5] + 2*src[3*step])>>4; - src[4*step]= (sums[4] + sums[6] + 2*src[4*step])>>4; - src[5*step]= (sums[5] + sums[7] + 2*src[5*step])>>4; - src[6*step]= (sums[6] + sums[8] + 2*src[6*step])>>4; - src[7*step]= (sums[7] + sums[9] + 2*src[7*step])>>4; - } - }else{ - const int middleEnergy= 5*(src[4*step] - src[3*step]) + 2*(src[2*step] - src[5*step]); - - if(FFABS(middleEnergy) < 8*QP){ - const int q=(src[3*step] - src[4*step])/2; - const int leftEnergy= 5*(src[2*step] - src[1*step]) + 2*(src[0*step] - src[3*step]); - const int rightEnergy= 5*(src[6*step] - src[5*step]) + 2*(src[4*step] - src[7*step]); - - int d= FFABS(middleEnergy) - FFMIN( FFABS(leftEnergy), FFABS(rightEnergy) ); - d= FFMAX(d, 0); - - d= (5*d + 32) >> 6; - d*= FFSIGN(-middleEnergy); - - if(q>0){ - d= d<0 ? 0 : d; - d= d>q ? q : d; - }else{ - d= d>0 ? 0 : d; - d= dppMode= *ppMode; //FIXME - - // Using ifs here as they are faster than function pointers although the - // difference would not be measurable here but it is much better because - // someone might exchange the CPU whithout restarting MPlayer ;) -#if CONFIG_RUNTIME_CPUDETECT -#if ARCH_X86 - // ordered per speed fastest first - if(c->cpuCaps & PP_CPU_CAPS_MMX2) - postProcess_MMX2(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); - else if(c->cpuCaps & PP_CPU_CAPS_3DNOW) - postProcess_3DNow(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); - else if(c->cpuCaps & PP_CPU_CAPS_MMX) - postProcess_MMX(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); - else - postProcess_C(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); -#else -#if HAVE_ALTIVEC - if(c->cpuCaps & PP_CPU_CAPS_ALTIVEC) - postProcess_altivec(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); - else -#endif - postProcess_C(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); -#endif -#else /* CONFIG_RUNTIME_CPUDETECT */ -#if HAVE_MMX2 - postProcess_MMX2(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); -#elif HAVE_AMD3DNOW - postProcess_3DNow(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); -#elif HAVE_MMX - postProcess_MMX(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); -#elif HAVE_ALTIVEC - postProcess_altivec(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); -#else - postProcess_C(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); -#endif -#endif /* !CONFIG_RUNTIME_CPUDETECT */ -} - -//static void postProcess(uint8_t src[], int srcStride, uint8_t dst[], int dstStride, int width, int height, -// QP_STORE_T QPs[], int QPStride, int isColor, struct PPMode *ppMode); - -/* -pp Command line Help -*/ -const char pp_help[] = -"Available postprocessing filters:\n" -"Filters Options\n" -"short long name short long option Description\n" -"* * a autoq CPU power dependent enabler\n" -" c chrom chrominance filtering enabled\n" -" y nochrom chrominance filtering disabled\n" -" n noluma luma filtering disabled\n" -"hb hdeblock (2 threshold) horizontal deblocking filter\n" -" 1. difference factor: default=32, higher -> more deblocking\n" -" 2. flatness threshold: default=39, lower -> more deblocking\n" -" the h & v deblocking filters share these\n" -" so you can't set different thresholds for h / v\n" -"vb vdeblock (2 threshold) vertical deblocking filter\n" -"ha hadeblock (2 threshold) horizontal deblocking filter\n" -"va vadeblock (2 threshold) vertical deblocking filter\n" -"h1 x1hdeblock experimental h deblock filter 1\n" -"v1 x1vdeblock experimental v deblock filter 1\n" -"dr dering deringing filter\n" -"al autolevels automatic brightness / contrast\n" -" f fullyrange stretch luminance to (0..255)\n" -"lb linblenddeint linear blend deinterlacer\n" -"li linipoldeint linear interpolating deinterlace\n" -"ci cubicipoldeint cubic interpolating deinterlacer\n" -"md mediandeint median deinterlacer\n" -"fd ffmpegdeint ffmpeg deinterlacer\n" -"l5 lowpass5 FIR lowpass deinterlacer\n" -"de default hb:a,vb:a,dr:a\n" -"fa fast h1:a,v1:a,dr:a\n" -"ac ha:a:128:7,va:a,dr:a\n" -"tn tmpnoise (3 threshold) temporal noise reducer\n" -" 1. <= 2. <= 3. larger -> stronger filtering\n" -"fq forceQuant force quantizer\n" -"Usage:\n" -"[: