From dcb7ef5483f26a7f20eee048821916f051216d62 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Thu, 26 Jul 2012 04:23:23 +0000 Subject: [PATCH 1/9] avprobe/avconv: fix tentative declaration compile errors on MSVS. --- avconv.c | 5 +++-- avprobe.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/avconv.c b/avconv.c index 7142ab41e9..439672a346 100644 --- a/avconv.c +++ b/avconv.c @@ -104,7 +104,7 @@ typedef struct MetadataMap { int index; ///< stream/chapter/program number } MetadataMap; -static const OptionDef options[]; +static const OptionDef *options; static int video_discard = 0; static int same_quant = 0; @@ -4858,7 +4858,7 @@ static int opt_filter_complex(const char *opt, const char *arg) } #define OFFSET(x) offsetof(OptionsContext, x) -static const OptionDef options[] = { +static const OptionDef real_options[] = { /* main options */ #include "cmdutils_common_opts.h" { "f", HAS_ARG | OPT_STRING | OPT_OFFSET, {.off = OFFSET(format)}, "force format", "fmt" }, @@ -4975,6 +4975,7 @@ int main(int argc, char **argv) OptionsContext o = { 0 }; int64_t ti; + options = real_options; reset_options(&o); av_log_set_flags(AV_LOG_SKIP_REPEATED); diff --git a/avprobe.c b/avprobe.c index 8e93d05ae9..aa7dae404f 100644 --- a/avprobe.c +++ b/avprobe.c @@ -44,7 +44,7 @@ static int use_byte_value_binary_prefix = 0; static int use_value_sexagesimal_format = 0; /* globals */ -static const OptionDef options[]; +static const OptionDef *options; /* AVprobe context */ static const char *input_filename; @@ -887,7 +887,7 @@ static void opt_pretty(void) use_value_sexagesimal_format = 1; } -static const OptionDef options[] = { +static const OptionDef real_options[] = { #include "cmdutils_common_opts.h" { "f", HAS_ARG, {(void*)opt_format}, "force format", "format" }, { "of", HAS_ARG, {(void*)&opt_output_format}, "output the document either as ini or json", "output_format" }, @@ -927,6 +927,7 @@ int main(int argc, char **argv) if (!buffer) exit(1); + options = real_options; parse_loglevel(argc, argv, options); av_register_all(); avformat_network_init(); From 60b9785530dfc290a4c8763214938eb367e68cbe Mon Sep 17 00:00:00 2001 From: Loren Merritt Date: Thu, 26 Jul 2012 22:51:13 +0000 Subject: [PATCH 2/9] vf_hqdn3d: cosmetics Change code style to match the rest of libav. Signed-off-by: Ronald S. Bultje --- libavfilter/vf_hqdn3d.c | 302 ++++++++++++++++++++-------------------- 1 file changed, 149 insertions(+), 153 deletions(-) diff --git a/libavfilter/vf_hqdn3d.c b/libavfilter/vf_hqdn3d.c index 9e01606041..1fa70c6e8f 100644 --- a/libavfilter/vf_hqdn3d.c +++ b/libavfilter/vf_hqdn3d.c @@ -32,165 +32,161 @@ #include "video.h" typedef struct { - int Coefs[4][512*16]; - unsigned int *Line; - unsigned short *Frame[3]; + int coefs[4][512*16]; + uint32_t *line; + uint16_t *frame_prev[3]; int hsub, vsub; } HQDN3DContext; -static inline unsigned int LowPassMul(unsigned int PrevMul, unsigned int CurrMul, int *Coef) +static inline uint32_t lowpass(unsigned int prev, unsigned int cur, int *coef) { - // int dMul= (PrevMul&0xFFFFFF)-(CurrMul&0xFFFFFF); - int dMul= PrevMul-CurrMul; - unsigned int d=((dMul+0x10007FF)>>12); - return CurrMul + Coef[d]; + int dmul = prev-cur; + unsigned int d = (dmul+0x10007FF)>>12; // 0x1000 to convert to unsigned, 7FF for rounding + return cur + coef[d]; } -static void deNoiseTemporal(unsigned char *FrameSrc, - unsigned char *FrameDest, - unsigned short *FrameAnt, - int W, int H, int sStride, int dStride, - int *Temporal) +static void denoise_temporal(uint8_t *src, uint8_t *dst, + uint16_t *frame_ant, + int w, int h, int sstride, int dstride, + int *temporal) { - long X, Y; - unsigned int PixelDst; + long x, y; + uint32_t pixel; - for (Y = 0; Y < H; Y++) { - for (X = 0; X < W; X++) { - PixelDst = LowPassMul(FrameAnt[X]<<8, FrameSrc[X]<<16, Temporal); - FrameAnt[X] = ((PixelDst+0x1000007F)>>8); - FrameDest[X]= ((PixelDst+0x10007FFF)>>16); + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + pixel = lowpass(frame_ant[x]<<8, src[x]<<16, temporal); + frame_ant[x] = ((pixel+0x1000007F)>>8); + dst[x]= ((pixel+0x10007FFF)>>16); } - FrameSrc += sStride; - FrameDest += dStride; - FrameAnt += W; + src += sstride; + dst += dstride; + frame_ant += w; } } -static void deNoiseSpacial(unsigned char *Frame, - unsigned char *FrameDest, - unsigned int *LineAnt, - int W, int H, int sStride, int dStride, - int *Horizontal, int *Vertical) +static void denoise_spatial(uint8_t *src, uint8_t *dst, + uint32_t *line_ant, + int w, int h, int sstride, int dstride, + int *horizontal, int *vertical) { - long X, Y; - long sLineOffs = 0, dLineOffs = 0; - unsigned int PixelAnt; - unsigned int PixelDst; + long x, y; + long sline_offs = 0, dline_offs = 0; + uint32_t pixel_ant; + uint32_t pixel; /* First pixel has no left nor top neighbor. */ - PixelDst = LineAnt[0] = PixelAnt = Frame[0]<<16; - FrameDest[0]= ((PixelDst+0x10007FFF)>>16); + pixel = line_ant[0] = pixel_ant = src[0]<<16; + dst[0]= ((pixel+0x10007FFF)>>16); /* First line has no top neighbor, only left. */ - for (X = 1; X < W; X++) { - PixelDst = LineAnt[X] = LowPassMul(PixelAnt, Frame[X]<<16, Horizontal); - FrameDest[X]= ((PixelDst+0x10007FFF)>>16); + for (x = 1; x < w; x++) { + pixel = line_ant[x] = lowpass(pixel_ant, src[x]<<16, horizontal); + dst[x]= ((pixel+0x10007FFF)>>16); } - for (Y = 1; Y < H; Y++) { - unsigned int PixelAnt; - sLineOffs += sStride, dLineOffs += dStride; + for (y = 1; y < h; y++) { + uint32_t pixel_ant; + sline_offs += sstride, dline_offs += dstride; /* First pixel on each line doesn't have previous pixel */ - PixelAnt = Frame[sLineOffs]<<16; - PixelDst = LineAnt[0] = LowPassMul(LineAnt[0], PixelAnt, Vertical); - FrameDest[dLineOffs]= ((PixelDst+0x10007FFF)>>16); + pixel_ant = src[sline_offs]<<16; + pixel = line_ant[0] = lowpass(line_ant[0], pixel_ant, vertical); + dst[dline_offs]= ((pixel+0x10007FFF)>>16); - for (X = 1; X < W; X++) { - unsigned int PixelDst; + for (x = 1; x < w; x++) { + uint32_t pixel; /* The rest are normal */ - PixelAnt = LowPassMul(PixelAnt, Frame[sLineOffs+X]<<16, Horizontal); - PixelDst = LineAnt[X] = LowPassMul(LineAnt[X], PixelAnt, Vertical); - FrameDest[dLineOffs+X]= ((PixelDst+0x10007FFF)>>16); + pixel_ant = lowpass(pixel_ant, src[sline_offs+x]<<16, horizontal); + pixel = line_ant[x] = lowpass(line_ant[x], pixel_ant, vertical); + dst[dline_offs+x]= ((pixel+0x10007FFF)>>16); } } } -static void deNoise(unsigned char *Frame, - unsigned char *FrameDest, - unsigned int *LineAnt, - unsigned short **FrameAntPtr, - int W, int H, int sStride, int dStride, - int *Horizontal, int *Vertical, int *Temporal) +static void denoise(uint8_t *src, uint8_t *dst, + uint32_t *line_ant, uint16_t **frame_ant_ptr, + int w, int h, int sstride, int dstride, + int *horizontal, int *vertical, int *temporal) { - long X, Y; - long sLineOffs = 0, dLineOffs = 0; - unsigned int PixelAnt; - unsigned int PixelDst; - unsigned short* FrameAnt=(*FrameAntPtr); + long x, y; + long sline_offs = 0, dline_offs = 0; + uint32_t pixel_ant; + uint32_t pixel; + uint16_t *frame_ant = *frame_ant_ptr; - if (!FrameAnt) { - (*FrameAntPtr) = FrameAnt = av_malloc(W*H*sizeof(unsigned short)); - for (Y = 0; Y < H; Y++) { - unsigned short* dst=&FrameAnt[Y*W]; - unsigned char* src=Frame+Y*sStride; - for (X = 0; X < W; X++) dst[X]=src[X]<<8; + if (!frame_ant) { + *frame_ant_ptr = frame_ant = av_malloc(w*h*sizeof(uint16_t)); + for (y = 0; y < h; y++) { + uint16_t *frame_dst = frame_ant+y*w; + uint8_t *frame_src = src+y*sstride; + for (x = 0; x < w; x++) + frame_dst[x] = frame_src[x]<<8; } } - if (!Horizontal[0] && !Vertical[0]) { - deNoiseTemporal(Frame, FrameDest, FrameAnt, - W, H, sStride, dStride, Temporal); + if (!horizontal[0] && !vertical[0]) { + denoise_temporal(src, dst, frame_ant, + w, h, sstride, dstride, temporal); return; } - if (!Temporal[0]) { - deNoiseSpacial(Frame, FrameDest, LineAnt, - W, H, sStride, dStride, Horizontal, Vertical); + if (!temporal[0]) { + denoise_spatial(src, dst, line_ant, + w, h, sstride, dstride, horizontal, vertical); return; } /* First pixel has no left nor top neighbor. Only previous frame */ - LineAnt[0] = PixelAnt = Frame[0]<<16; - PixelDst = LowPassMul(FrameAnt[0]<<8, PixelAnt, Temporal); - FrameAnt[0] = ((PixelDst+0x1000007F)>>8); - FrameDest[0]= ((PixelDst+0x10007FFF)>>16); + line_ant[0] = pixel_ant = src[0]<<16; + pixel = lowpass(frame_ant[0]<<8, pixel_ant, temporal); + frame_ant[0] = ((pixel+0x1000007F)>>8); + dst[0]= ((pixel+0x10007FFF)>>16); /* First line has no top neighbor. Only left one for each pixel and * last frame */ - for (X = 1; X < W; X++) { - LineAnt[X] = PixelAnt = LowPassMul(PixelAnt, Frame[X]<<16, Horizontal); - PixelDst = LowPassMul(FrameAnt[X]<<8, PixelAnt, Temporal); - FrameAnt[X] = ((PixelDst+0x1000007F)>>8); - FrameDest[X]= ((PixelDst+0x10007FFF)>>16); + for (x = 1; x < w; x++) { + line_ant[x] = pixel_ant = lowpass(pixel_ant, src[x]<<16, horizontal); + pixel = lowpass(frame_ant[x]<<8, pixel_ant, temporal); + frame_ant[x] = ((pixel+0x1000007F)>>8); + dst[x]= ((pixel+0x10007FFF)>>16); } - for (Y = 1; Y < H; Y++) { - unsigned int PixelAnt; - unsigned short* LinePrev=&FrameAnt[Y*W]; - sLineOffs += sStride, dLineOffs += dStride; + for (y = 1; y < h; y++) { + uint32_t pixel_ant; + uint16_t *line_prev = frame_ant+y*w; + sline_offs += sstride, dline_offs += dstride; /* First pixel on each line doesn't have previous pixel */ - PixelAnt = Frame[sLineOffs]<<16; - LineAnt[0] = LowPassMul(LineAnt[0], PixelAnt, Vertical); - PixelDst = LowPassMul(LinePrev[0]<<8, LineAnt[0], Temporal); - LinePrev[0] = ((PixelDst+0x1000007F)>>8); - FrameDest[dLineOffs]= ((PixelDst+0x10007FFF)>>16); + pixel_ant = src[sline_offs]<<16; + line_ant[0] = lowpass(line_ant[0], pixel_ant, vertical); + pixel = lowpass(line_prev[0]<<8, line_ant[0], temporal); + line_prev[0] = ((pixel+0x1000007F)>>8); + dst[dline_offs]= ((pixel+0x10007FFF)>>16); - for (X = 1; X < W; X++) { - unsigned int PixelDst; + for (x = 1; x < w; x++) { + uint32_t pixel; /* The rest are normal */ - PixelAnt = LowPassMul(PixelAnt, Frame[sLineOffs+X]<<16, Horizontal); - LineAnt[X] = LowPassMul(LineAnt[X], PixelAnt, Vertical); - PixelDst = LowPassMul(LinePrev[X]<<8, LineAnt[X], Temporal); - LinePrev[X] = ((PixelDst+0x1000007F)>>8); - FrameDest[dLineOffs+X]= ((PixelDst+0x10007FFF)>>16); + pixel_ant = lowpass(pixel_ant, src[sline_offs+x]<<16, horizontal); + line_ant[x] = lowpass(line_ant[x], pixel_ant, vertical); + pixel = lowpass(line_prev[x]<<8, line_ant[x], temporal); + line_prev[x] = ((pixel+0x1000007F)>>8); + dst[dline_offs+x]= ((pixel+0x10007FFF)>>16); } } } -static void PrecalcCoefs(int *Ct, double Dist25) +static void precalc_coefs(int *ct, double dist25) { int i; - double Gamma, Simil, C; + double gamma, simil, C; - Gamma = log(0.25) / log(1.0 - Dist25/255.0 - 0.00001); + gamma = log(0.25) / log(1.0 - dist25/255.0 - 0.00001); for (i = -255*16; i <= 255*16; i++) { - Simil = 1.0 - FFABS(i) / (16*255.0); - C = pow(Simil, Gamma) * 65536.0 * i / 16.0; - Ct[16*256+i] = lrint(C); + simil = 1.0 - FFABS(i) / (16*255.0); + C = pow(simil, gamma) * 65536.0 * i / 16.0; + ct[16*256+i] = lrint(C); } - Ct[0] = !!Dist25; + ct[0] = !!dist25; } #define PARAM1_DEFAULT 4.0 @@ -200,57 +196,57 @@ static void PrecalcCoefs(int *Ct, double Dist25) static int init(AVFilterContext *ctx, const char *args) { HQDN3DContext *hqdn3d = ctx->priv; - double LumSpac, LumTmp, ChromSpac, ChromTmp; - double Param1, Param2, Param3, Param4; + double lum_spac, lum_tmp, chrom_spac, chrom_tmp; + double param1, param2, param3, param4; - LumSpac = PARAM1_DEFAULT; - ChromSpac = PARAM2_DEFAULT; - LumTmp = PARAM3_DEFAULT; - ChromTmp = LumTmp * ChromSpac / LumSpac; + lum_spac = PARAM1_DEFAULT; + chrom_spac = PARAM2_DEFAULT; + lum_tmp = PARAM3_DEFAULT; + chrom_tmp = lum_tmp * chrom_spac / lum_spac; if (args) { switch (sscanf(args, "%lf:%lf:%lf:%lf", - &Param1, &Param2, &Param3, &Param4)) { + ¶m1, ¶m2, ¶m3, ¶m4)) { case 1: - LumSpac = Param1; - ChromSpac = PARAM2_DEFAULT * Param1 / PARAM1_DEFAULT; - LumTmp = PARAM3_DEFAULT * Param1 / PARAM1_DEFAULT; - ChromTmp = LumTmp * ChromSpac / LumSpac; + lum_spac = param1; + chrom_spac = PARAM2_DEFAULT * param1 / PARAM1_DEFAULT; + lum_tmp = PARAM3_DEFAULT * param1 / PARAM1_DEFAULT; + chrom_tmp = lum_tmp * chrom_spac / lum_spac; break; case 2: - LumSpac = Param1; - ChromSpac = Param2; - LumTmp = PARAM3_DEFAULT * Param1 / PARAM1_DEFAULT; - ChromTmp = LumTmp * ChromSpac / LumSpac; + lum_spac = param1; + chrom_spac = param2; + lum_tmp = PARAM3_DEFAULT * param1 / PARAM1_DEFAULT; + chrom_tmp = lum_tmp * chrom_spac / lum_spac; break; case 3: - LumSpac = Param1; - ChromSpac = Param2; - LumTmp = Param3; - ChromTmp = LumTmp * ChromSpac / LumSpac; + lum_spac = param1; + chrom_spac = param2; + lum_tmp = param3; + chrom_tmp = lum_tmp * chrom_spac / lum_spac; break; case 4: - LumSpac = Param1; - ChromSpac = Param2; - LumTmp = Param3; - ChromTmp = Param4; + lum_spac = param1; + chrom_spac = param2; + lum_tmp = param3; + chrom_tmp = param4; break; } } av_log(ctx, AV_LOG_VERBOSE, "ls:%lf cs:%lf lt:%lf ct:%lf\n", - LumSpac, ChromSpac, LumTmp, ChromTmp); - if (LumSpac < 0 || ChromSpac < 0 || isnan(ChromTmp)) { + lum_spac, chrom_spac, lum_tmp, chrom_tmp); + if (lum_spac < 0 || chrom_spac < 0 || isnan(chrom_tmp)) { av_log(ctx, AV_LOG_ERROR, "Invalid negative value for luma or chroma spatial strength, " "or resulting value for chroma temporal strength is nan.\n"); return AVERROR(EINVAL); } - PrecalcCoefs(hqdn3d->Coefs[0], LumSpac); - PrecalcCoefs(hqdn3d->Coefs[1], LumTmp); - PrecalcCoefs(hqdn3d->Coefs[2], ChromSpac); - PrecalcCoefs(hqdn3d->Coefs[3], ChromTmp); + precalc_coefs(hqdn3d->coefs[0], lum_spac); + precalc_coefs(hqdn3d->coefs[1], lum_tmp); + precalc_coefs(hqdn3d->coefs[2], chrom_spac); + precalc_coefs(hqdn3d->coefs[3], chrom_tmp); return 0; } @@ -259,10 +255,10 @@ static void uninit(AVFilterContext *ctx) { HQDN3DContext *hqdn3d = ctx->priv; - av_freep(&hqdn3d->Line); - av_freep(&hqdn3d->Frame[0]); - av_freep(&hqdn3d->Frame[1]); - av_freep(&hqdn3d->Frame[2]); + av_freep(&hqdn3d->line); + av_freep(&hqdn3d->frame_prev[0]); + av_freep(&hqdn3d->frame_prev[1]); + av_freep(&hqdn3d->frame_prev[2]); } static int query_formats(AVFilterContext *ctx) @@ -283,8 +279,8 @@ static int config_input(AVFilterLink *inlink) hqdn3d->hsub = av_pix_fmt_descriptors[inlink->format].log2_chroma_w; hqdn3d->vsub = av_pix_fmt_descriptors[inlink->format].log2_chroma_h; - hqdn3d->Line = av_malloc(inlink->w * sizeof(*hqdn3d->Line)); - if (!hqdn3d->Line) + hqdn3d->line = av_malloc(inlink->w * sizeof(*hqdn3d->line)); + if (!hqdn3d->line) return AVERROR(ENOMEM); return 0; @@ -305,24 +301,24 @@ static int end_frame(AVFilterLink *inlink) int ch = inpic->video->h >> hqdn3d->vsub; int ret; - deNoise(inpic->data[0], outpic->data[0], - hqdn3d->Line, &hqdn3d->Frame[0], inpic->video->w, inpic->video->h, + denoise(inpic->data[0], outpic->data[0], + hqdn3d->line, &hqdn3d->frame_prev[0], inpic->video->w, inpic->video->h, inpic->linesize[0], outpic->linesize[0], - hqdn3d->Coefs[0], - hqdn3d->Coefs[0], - hqdn3d->Coefs[1]); - deNoise(inpic->data[1], outpic->data[1], - hqdn3d->Line, &hqdn3d->Frame[1], cw, ch, + hqdn3d->coefs[0], + hqdn3d->coefs[0], + hqdn3d->coefs[1]); + denoise(inpic->data[1], outpic->data[1], + hqdn3d->line, &hqdn3d->frame_prev[1], cw, ch, inpic->linesize[1], outpic->linesize[1], - hqdn3d->Coefs[2], - hqdn3d->Coefs[2], - hqdn3d->Coefs[3]); - deNoise(inpic->data[2], outpic->data[2], - hqdn3d->Line, &hqdn3d->Frame[2], cw, ch, + hqdn3d->coefs[2], + hqdn3d->coefs[2], + hqdn3d->coefs[3]); + denoise(inpic->data[2], outpic->data[2], + hqdn3d->line, &hqdn3d->frame_prev[2], cw, ch, inpic->linesize[2], outpic->linesize[2], - hqdn3d->Coefs[2], - hqdn3d->Coefs[2], - hqdn3d->Coefs[3]); + hqdn3d->coefs[2], + hqdn3d->coefs[2], + hqdn3d->coefs[3]); if ((ret = ff_draw_slice(outlink, 0, inpic->video->h, 1)) < 0 || (ret = ff_end_frame(outlink)) < 0) From fb44e7401f44ce9c1dded07d992c57bd82ff666c Mon Sep 17 00:00:00 2001 From: Loren Merritt Date: Thu, 26 Jul 2012 22:51:12 +0000 Subject: [PATCH 3/9] factor identical ff_inplace_start_frame out of two filters Signed-off-by: Ronald S. Bultje --- libavfilter/vf_delogo.c | 38 +------------------------------------- libavfilter/vf_gradfun.c | 37 +------------------------------------ libavfilter/video.c | 36 ++++++++++++++++++++++++++++++++++++ libavfilter/video.h | 1 + 4 files changed, 39 insertions(+), 73 deletions(-) diff --git a/libavfilter/vf_delogo.c b/libavfilter/vf_delogo.c index 343585fc5e..e8b5431caf 100644 --- a/libavfilter/vf_delogo.c +++ b/libavfilter/vf_delogo.c @@ -214,42 +214,6 @@ static av_cold int init(AVFilterContext *ctx, const char *args) return 0; } -static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref) -{ - AVFilterLink *outlink = inlink->dst->outputs[0]; - AVFilterBufferRef *outpicref = NULL, *for_next_filter; - int ret = 0; - - if (inpicref->perms & AV_PERM_PRESERVE) { - outpicref = ff_get_video_buffer(outlink, AV_PERM_WRITE, - outlink->w, outlink->h); - if (!outpicref) - return AVERROR(ENOMEM); - - avfilter_copy_buffer_ref_props(outpicref, inpicref); - outpicref->video->w = outlink->w; - outpicref->video->h = outlink->h; - } else { - outpicref = avfilter_ref_buffer(inpicref, ~0); - if (!outpicref) - return AVERROR(ENOMEM); - } - - for_next_filter = avfilter_ref_buffer(outpicref, ~0); - if (for_next_filter) - ret = ff_start_frame(outlink, for_next_filter); - else - ret = AVERROR(ENOMEM); - - if (ret < 0) { - avfilter_unref_bufferp(&outpicref); - return ret; - } - - outlink->out_buf = outpicref; - return 0; -} - static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) { return 0; @@ -296,7 +260,7 @@ AVFilter avfilter_vf_delogo = { .inputs = (const AVFilterPad[]) {{ .name = "default", .type = AVMEDIA_TYPE_VIDEO, .get_video_buffer = ff_null_get_video_buffer, - .start_frame = start_frame, + .start_frame = ff_inplace_start_frame, .draw_slice = null_draw_slice, .end_frame = end_frame, .min_perms = AV_PERM_WRITE | AV_PERM_READ, diff --git a/libavfilter/vf_gradfun.c b/libavfilter/vf_gradfun.c index 52dcb7092f..f8896b5e57 100644 --- a/libavfilter/vf_gradfun.c +++ b/libavfilter/vf_gradfun.c @@ -180,41 +180,6 @@ static int config_input(AVFilterLink *inlink) return 0; } -static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref) -{ - AVFilterLink *outlink = inlink->dst->outputs[0]; - AVFilterBufferRef *outpicref = NULL, *for_next_filter; - int ret = 0; - - if (inpicref->perms & AV_PERM_PRESERVE) { - outpicref = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); - if (!outpicref) - return AVERROR(ENOMEM); - - avfilter_copy_buffer_ref_props(outpicref, inpicref); - outpicref->video->w = outlink->w; - outpicref->video->h = outlink->h; - } else { - outpicref = avfilter_ref_buffer(inpicref, ~0); - if (!outpicref) - return AVERROR(ENOMEM); - } - - for_next_filter = avfilter_ref_buffer(outpicref, ~0); - if (for_next_filter) - ret = ff_start_frame(outlink, for_next_filter); - else - ret = AVERROR(ENOMEM); - - if (ret < 0) { - avfilter_unref_bufferp(&outpicref); - return ret; - } - - outlink->out_buf = outpicref; - return 0; -} - static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) { return 0; @@ -261,7 +226,7 @@ AVFilter avfilter_vf_gradfun = { .inputs = (const AVFilterPad[]) {{ .name = "default", .type = AVMEDIA_TYPE_VIDEO, .config_props = config_input, - .start_frame = start_frame, + .start_frame = ff_inplace_start_frame, .draw_slice = null_draw_slice, .end_frame = end_frame, .min_perms = AV_PERM_READ, }, diff --git a/libavfilter/video.c b/libavfilter/video.c index 6e5063778a..ebbbc346bc 100644 --- a/libavfilter/video.c +++ b/libavfilter/video.c @@ -168,6 +168,42 @@ int ff_null_start_frame(AVFilterLink *link, AVFilterBufferRef *picref) return ff_start_frame(link->dst->outputs[0], buf_out); } +// for filters that support (but don't require) outpic==inpic +int ff_inplace_start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref) +{ + AVFilterLink *outlink = inlink->dst->outputs[0]; + AVFilterBufferRef *outpicref = NULL, *for_next_filter; + int ret = 0; + + if ((inpicref->perms & AV_PERM_WRITE) && !(inpicref->perms & AV_PERM_PRESERVE)) { + outpicref = avfilter_ref_buffer(inpicref, ~0); + if (!outpicref) + return AVERROR(ENOMEM); + } else { + outpicref = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); + if (!outpicref) + return AVERROR(ENOMEM); + + avfilter_copy_buffer_ref_props(outpicref, inpicref); + outpicref->video->w = outlink->w; + outpicref->video->h = outlink->h; + } + + for_next_filter = avfilter_ref_buffer(outpicref, ~0); + if (for_next_filter) + ret = ff_start_frame(outlink, for_next_filter); + else + ret = AVERROR(ENOMEM); + + if (ret < 0) { + avfilter_unref_bufferp(&outpicref); + return ret; + } + + outlink->out_buf = outpicref; + return 0; +} + static int default_start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) { AVFilterLink *outlink = NULL; diff --git a/libavfilter/video.h b/libavfilter/video.h index ef4a1a9c32..348240c6e6 100644 --- a/libavfilter/video.h +++ b/libavfilter/video.h @@ -39,6 +39,7 @@ AVFilterBufferRef *ff_null_get_video_buffer(AVFilterLink *link, int perms, int w AVFilterBufferRef *ff_get_video_buffer(AVFilterLink *link, int perms, int w, int h); +int ff_inplace_start_frame(AVFilterLink *link, AVFilterBufferRef *picref); int ff_null_start_frame(AVFilterLink *link, AVFilterBufferRef *picref); int ff_null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir); int ff_null_end_frame(AVFilterLink *link); From 85e228c71d44ce36f7c0f51d1cf9b63e84a082f3 Mon Sep 17 00:00:00 2001 From: Loren Merritt Date: Thu, 26 Jul 2012 22:51:14 +0000 Subject: [PATCH 4/9] vf_hqdn3d: simplify and optimize 14% faster on penryn, 2% on sandybridge, 9% on bulldozer Signed-off-by: Ronald S. Bultje --- libavfilter/vf_hqdn3d.c | 155 +++++++++++++--------------------------- 1 file changed, 50 insertions(+), 105 deletions(-) diff --git a/libavfilter/vf_hqdn3d.c b/libavfilter/vf_hqdn3d.c index 1fa70c6e8f..bb81b79f1d 100644 --- a/libavfilter/vf_hqdn3d.c +++ b/libavfilter/vf_hqdn3d.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2003 Daniel Moreno * Copyright (c) 2010 Baptiste Coudurier + * Copyright (c) 2012 Loren Merritt * * This file is part of Libav, ported from MPlayer. * @@ -51,13 +52,13 @@ static void denoise_temporal(uint8_t *src, uint8_t *dst, int *temporal) { long x, y; - uint32_t pixel; + uint32_t tmp; for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { - pixel = lowpass(frame_ant[x]<<8, src[x]<<16, temporal); - frame_ant[x] = ((pixel+0x1000007F)>>8); - dst[x]= ((pixel+0x10007FFF)>>16); + tmp = lowpass(frame_ant[x]<<8, src[x]<<16, temporal); + frame_ant[x] = (tmp+0x7F)>>8; + dst[x] = (tmp+0x7FFF)>>16; } src += sstride; dst += dstride; @@ -66,111 +67,66 @@ static void denoise_temporal(uint8_t *src, uint8_t *dst, } static void denoise_spatial(uint8_t *src, uint8_t *dst, - uint32_t *line_ant, + uint32_t *line_ant, uint16_t *frame_ant, int w, int h, int sstride, int dstride, - int *horizontal, int *vertical) + int *spatial, int *temporal) { long x, y; - long sline_offs = 0, dline_offs = 0; uint32_t pixel_ant; - uint32_t pixel; + uint32_t tmp; - /* First pixel has no left nor top neighbor. */ - pixel = line_ant[0] = pixel_ant = src[0]<<16; - dst[0]= ((pixel+0x10007FFF)>>16); - - /* First line has no top neighbor, only left. */ - for (x = 1; x < w; x++) { - pixel = line_ant[x] = lowpass(pixel_ant, src[x]<<16, horizontal); - dst[x]= ((pixel+0x10007FFF)>>16); + /* First line has no top neighbor. Only left one for each tmp and + * last frame */ + pixel_ant = src[0]<<16; + for (x = 0; x < w; x++) { + line_ant[x] = tmp = pixel_ant = lowpass(pixel_ant, src[x]<<16, spatial); + tmp = lowpass(frame_ant[x]<<8, tmp, temporal); + frame_ant[x] = (tmp+0x7F)>>8; + dst[x] = (tmp+0x7FFF)>>16; } for (y = 1; y < h; y++) { - uint32_t pixel_ant; - sline_offs += sstride, dline_offs += dstride; - /* First pixel on each line doesn't have previous pixel */ - pixel_ant = src[sline_offs]<<16; - pixel = line_ant[0] = lowpass(line_ant[0], pixel_ant, vertical); - dst[dline_offs]= ((pixel+0x10007FFF)>>16); - - for (x = 1; x < w; x++) { - uint32_t pixel; - /* The rest are normal */ - pixel_ant = lowpass(pixel_ant, src[sline_offs+x]<<16, horizontal); - pixel = line_ant[x] = lowpass(line_ant[x], pixel_ant, vertical); - dst[dline_offs+x]= ((pixel+0x10007FFF)>>16); + src += sstride; + dst += dstride; + frame_ant += w; + pixel_ant = src[0]<<16; + for (x = 0; x < w-1; x++) { + line_ant[x] = tmp = lowpass(line_ant[x], pixel_ant, spatial); + pixel_ant = lowpass(pixel_ant, src[x+1]<<16, spatial); + tmp = lowpass(frame_ant[x]<<8, tmp, temporal); + frame_ant[x] = (tmp+0x7F)>>8; + dst[x] = (tmp+0x7FFF)>>16; } + line_ant[x] = tmp = lowpass(line_ant[x], pixel_ant, spatial); + tmp = lowpass(frame_ant[x]<<8, tmp, temporal); + frame_ant[x] = (tmp+0x7F)>>8; + dst[x] = (tmp+0x7FFF)>>16; } } static void denoise(uint8_t *src, uint8_t *dst, uint32_t *line_ant, uint16_t **frame_ant_ptr, int w, int h, int sstride, int dstride, - int *horizontal, int *vertical, int *temporal) + int *spatial, int *temporal) { long x, y; - long sline_offs = 0, dline_offs = 0; - uint32_t pixel_ant; - uint32_t pixel; uint16_t *frame_ant = *frame_ant_ptr; - if (!frame_ant) { + uint8_t *frame_src = src; *frame_ant_ptr = frame_ant = av_malloc(w*h*sizeof(uint16_t)); - for (y = 0; y < h; y++) { - uint16_t *frame_dst = frame_ant+y*w; - uint8_t *frame_src = src+y*sstride; + for (y = 0; y < h; y++, src += sstride, frame_ant += w) for (x = 0; x < w; x++) - frame_dst[x] = frame_src[x]<<8; - } + frame_ant[x] = src[x]<<8; + src = frame_src; + frame_ant = *frame_ant_ptr; } - if (!horizontal[0] && !vertical[0]) { + if (spatial[0]) + denoise_spatial(src, dst, line_ant, frame_ant, + w, h, sstride, dstride, spatial, temporal); + else denoise_temporal(src, dst, frame_ant, w, h, sstride, dstride, temporal); - return; - } - if (!temporal[0]) { - denoise_spatial(src, dst, line_ant, - w, h, sstride, dstride, horizontal, vertical); - return; - } - - /* First pixel has no left nor top neighbor. Only previous frame */ - line_ant[0] = pixel_ant = src[0]<<16; - pixel = lowpass(frame_ant[0]<<8, pixel_ant, temporal); - frame_ant[0] = ((pixel+0x1000007F)>>8); - dst[0]= ((pixel+0x10007FFF)>>16); - - /* First line has no top neighbor. Only left one for each pixel and - * last frame */ - for (x = 1; x < w; x++) { - line_ant[x] = pixel_ant = lowpass(pixel_ant, src[x]<<16, horizontal); - pixel = lowpass(frame_ant[x]<<8, pixel_ant, temporal); - frame_ant[x] = ((pixel+0x1000007F)>>8); - dst[x]= ((pixel+0x10007FFF)>>16); - } - - for (y = 1; y < h; y++) { - uint32_t pixel_ant; - uint16_t *line_prev = frame_ant+y*w; - sline_offs += sstride, dline_offs += dstride; - /* First pixel on each line doesn't have previous pixel */ - pixel_ant = src[sline_offs]<<16; - line_ant[0] = lowpass(line_ant[0], pixel_ant, vertical); - pixel = lowpass(line_prev[0]<<8, line_ant[0], temporal); - line_prev[0] = ((pixel+0x1000007F)>>8); - dst[dline_offs]= ((pixel+0x10007FFF)>>16); - - for (x = 1; x < w; x++) { - uint32_t pixel; - /* The rest are normal */ - pixel_ant = lowpass(pixel_ant, src[sline_offs+x]<<16, horizontal); - line_ant[x] = lowpass(line_ant[x], pixel_ant, vertical); - pixel = lowpass(line_prev[x]<<8, line_ant[x], temporal); - line_prev[x] = ((pixel+0x1000007F)>>8); - dst[dline_offs+x]= ((pixel+0x10007FFF)>>16); - } - } } static void precalc_coefs(int *ct, double dist25) @@ -297,28 +253,16 @@ static int end_frame(AVFilterLink *inlink) AVFilterLink *outlink = inlink->dst->outputs[0]; AVFilterBufferRef *inpic = inlink ->cur_buf; AVFilterBufferRef *outpic = outlink->out_buf; - int cw = inpic->video->w >> hqdn3d->hsub; - int ch = inpic->video->h >> hqdn3d->vsub; - int ret; + int ret, c; - denoise(inpic->data[0], outpic->data[0], - hqdn3d->line, &hqdn3d->frame_prev[0], inpic->video->w, inpic->video->h, - inpic->linesize[0], outpic->linesize[0], - hqdn3d->coefs[0], - hqdn3d->coefs[0], - hqdn3d->coefs[1]); - denoise(inpic->data[1], outpic->data[1], - hqdn3d->line, &hqdn3d->frame_prev[1], cw, ch, - inpic->linesize[1], outpic->linesize[1], - hqdn3d->coefs[2], - hqdn3d->coefs[2], - hqdn3d->coefs[3]); - denoise(inpic->data[2], outpic->data[2], - hqdn3d->line, &hqdn3d->frame_prev[2], cw, ch, - inpic->linesize[2], outpic->linesize[2], - hqdn3d->coefs[2], - hqdn3d->coefs[2], - hqdn3d->coefs[3]); + for (c = 0; c < 3; c++) { + denoise(inpic->data[c], outpic->data[c], + hqdn3d->line, &hqdn3d->frame_prev[c], + inpic->video->w >> (!!c * hqdn3d->hsub), + inpic->video->h >> (!!c * hqdn3d->vsub), + inpic->linesize[c], outpic->linesize[c], + hqdn3d->coefs[c?2:0], hqdn3d->coefs[c?3:1]); + } if ((ret = ff_draw_slice(outlink, 0, inpic->video->h, 1)) < 0 || (ret = ff_end_frame(outlink)) < 0) @@ -337,6 +281,7 @@ AVFilter avfilter_vf_hqdn3d = { .inputs = (const AVFilterPad[]) {{ .name = "default", .type = AVMEDIA_TYPE_VIDEO, + .start_frame = ff_inplace_start_frame, .draw_slice = null_draw_slice, .config_props = config_input, .end_frame = end_frame }, From 0f583e6cc55dfea865b6b3c9b4ac653455f37ec2 Mon Sep 17 00:00:00 2001 From: Loren Merritt Date: Thu, 26 Jul 2012 22:51:15 +0000 Subject: [PATCH 5/9] vf_hqdn3d: reduce intermediate precision 11% faster on penryn, 7% on sandybridge, 5% on bulldozer Negligible change to output. Signed-off-by: Ronald S. Bultje --- libavfilter/vf_hqdn3d.c | 62 +++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/libavfilter/vf_hqdn3d.c b/libavfilter/vf_hqdn3d.c index bb81b79f1d..46902fa290 100644 --- a/libavfilter/vf_hqdn3d.c +++ b/libavfilter/vf_hqdn3d.c @@ -33,32 +33,32 @@ #include "video.h" typedef struct { - int coefs[4][512*16]; - uint32_t *line; + int16_t coefs[4][512*16]; + uint16_t *line; uint16_t *frame_prev[3]; int hsub, vsub; } HQDN3DContext; -static inline uint32_t lowpass(unsigned int prev, unsigned int cur, int *coef) +static inline uint32_t lowpass(int prev, int cur, int16_t *coef) { - int dmul = prev-cur; - unsigned int d = (dmul+0x10007FF)>>12; // 0x1000 to convert to unsigned, 7FF for rounding + int d = (prev-cur)>>4; return cur + coef[d]; } static void denoise_temporal(uint8_t *src, uint8_t *dst, uint16_t *frame_ant, int w, int h, int sstride, int dstride, - int *temporal) + int16_t *temporal) { long x, y; uint32_t tmp; + temporal += 0x1000; + for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { - tmp = lowpass(frame_ant[x]<<8, src[x]<<16, temporal); - frame_ant[x] = (tmp+0x7F)>>8; - dst[x] = (tmp+0x7FFF)>>16; + frame_ant[x] = tmp = lowpass(frame_ant[x], src[x]<<8, temporal); + dst[x] = (tmp+0x7F)>>8; } src += sstride; dst += dstride; @@ -67,47 +67,47 @@ static void denoise_temporal(uint8_t *src, uint8_t *dst, } static void denoise_spatial(uint8_t *src, uint8_t *dst, - uint32_t *line_ant, uint16_t *frame_ant, + uint16_t *line_ant, uint16_t *frame_ant, int w, int h, int sstride, int dstride, - int *spatial, int *temporal) + int16_t *spatial, int16_t *temporal) { long x, y; uint32_t pixel_ant; uint32_t tmp; + spatial += 0x1000; + temporal += 0x1000; + /* First line has no top neighbor. Only left one for each tmp and * last frame */ - pixel_ant = src[0]<<16; + pixel_ant = src[0]<<8; for (x = 0; x < w; x++) { - line_ant[x] = tmp = pixel_ant = lowpass(pixel_ant, src[x]<<16, spatial); - tmp = lowpass(frame_ant[x]<<8, tmp, temporal); - frame_ant[x] = (tmp+0x7F)>>8; - dst[x] = (tmp+0x7FFF)>>16; + line_ant[x] = tmp = pixel_ant = lowpass(pixel_ant, src[x]<<8, spatial); + frame_ant[x] = tmp = lowpass(frame_ant[x], tmp, temporal); + dst[x] = (tmp+0x7F)>>8; } for (y = 1; y < h; y++) { src += sstride; dst += dstride; frame_ant += w; - pixel_ant = src[0]<<16; + pixel_ant = src[0]<<8; for (x = 0; x < w-1; x++) { line_ant[x] = tmp = lowpass(line_ant[x], pixel_ant, spatial); - pixel_ant = lowpass(pixel_ant, src[x+1]<<16, spatial); - tmp = lowpass(frame_ant[x]<<8, tmp, temporal); - frame_ant[x] = (tmp+0x7F)>>8; - dst[x] = (tmp+0x7FFF)>>16; + pixel_ant = lowpass(pixel_ant, src[x+1]<<8, spatial); + frame_ant[x] = tmp = lowpass(frame_ant[x], tmp, temporal); + dst[x] = (tmp+0x7F)>>8; } line_ant[x] = tmp = lowpass(line_ant[x], pixel_ant, spatial); - tmp = lowpass(frame_ant[x]<<8, tmp, temporal); - frame_ant[x] = (tmp+0x7F)>>8; - dst[x] = (tmp+0x7FFF)>>16; + frame_ant[x] = tmp = lowpass(frame_ant[x], tmp, temporal); + dst[x] = (tmp+0x7F)>>8; } } static void denoise(uint8_t *src, uint8_t *dst, - uint32_t *line_ant, uint16_t **frame_ant_ptr, + uint16_t *line_ant, uint16_t **frame_ant_ptr, int w, int h, int sstride, int dstride, - int *spatial, int *temporal) + int16_t *spatial, int16_t *temporal) { long x, y; uint16_t *frame_ant = *frame_ant_ptr; @@ -129,16 +129,18 @@ static void denoise(uint8_t *src, uint8_t *dst, w, h, sstride, dstride, temporal); } -static void precalc_coefs(int *ct, double dist25) +static void precalc_coefs(int16_t *ct, double dist25) { int i; double gamma, simil, C; - gamma = log(0.25) / log(1.0 - dist25/255.0 - 0.00001); + gamma = log(0.25) / log(1.0 - FFMIN(dist25,252.0)/255.0 - 0.00001); for (i = -255*16; i <= 255*16; i++) { - simil = 1.0 - FFABS(i) / (16*255.0); - C = pow(simil, gamma) * 65536.0 * i / 16.0; + // lowpass() truncates (not rounds) the diff, so +15/32 for the midpoint of the bin. + double f = (i + 15.0/32.0) / 16.0; + simil = 1.0 - FFABS(f) / 255.0; + C = pow(simil, gamma) * 256.0 * f; ct[16*256+i] = lrint(C); } From 1ad715dbf3bf14505a7d713bb2ea42e5e7a63694 Mon Sep 17 00:00:00 2001 From: Loren Merritt Date: Fri, 27 Jul 2012 01:42:05 +0000 Subject: [PATCH 6/9] vf_hqdn3d: support 9 and 10bit colordepth Signed-off-by: Ronald S. Bultje --- libavfilter/vf_hqdn3d.c | 72 ++++++++++++++++++++++++++++++----------- 1 file changed, 53 insertions(+), 19 deletions(-) diff --git a/libavfilter/vf_hqdn3d.c b/libavfilter/vf_hqdn3d.c index 46902fa290..138b527a70 100644 --- a/libavfilter/vf_hqdn3d.c +++ b/libavfilter/vf_hqdn3d.c @@ -27,6 +27,7 @@ */ #include "libavutil/pixdesc.h" +#include "libavutil/intreadwrite.h" #include "avfilter.h" #include "formats.h" #include "internal.h" @@ -37,18 +38,25 @@ typedef struct { uint16_t *line; uint16_t *frame_prev[3]; int hsub, vsub; + int depth; } HQDN3DContext; +#define RIGHTSHIFT(a,b) (((a)+(((1<<(b))-1)>>1))>>(b)) +#define LOAD(x) ((depth==8 ? src[x] : AV_RN16A(src+(x)*2)) << (16-depth)) +#define STORE(x,val) (depth==8 ? dst[x] = RIGHTSHIFT(val, 16-depth)\ + : AV_WN16A(dst+(x)*2, RIGHTSHIFT(val, 16-depth))) + static inline uint32_t lowpass(int prev, int cur, int16_t *coef) { int d = (prev-cur)>>4; return cur + coef[d]; } +av_always_inline static void denoise_temporal(uint8_t *src, uint8_t *dst, uint16_t *frame_ant, int w, int h, int sstride, int dstride, - int16_t *temporal) + int16_t *temporal, int depth) { long x, y; uint32_t tmp; @@ -57,8 +65,8 @@ static void denoise_temporal(uint8_t *src, uint8_t *dst, for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { - frame_ant[x] = tmp = lowpass(frame_ant[x], src[x]<<8, temporal); - dst[x] = (tmp+0x7F)>>8; + frame_ant[x] = tmp = lowpass(frame_ant[x], LOAD(x), temporal); + STORE(x, tmp); } src += sstride; dst += dstride; @@ -66,10 +74,11 @@ static void denoise_temporal(uint8_t *src, uint8_t *dst, } } +av_always_inline static void denoise_spatial(uint8_t *src, uint8_t *dst, uint16_t *line_ant, uint16_t *frame_ant, int w, int h, int sstride, int dstride, - int16_t *spatial, int16_t *temporal) + int16_t *spatial, int16_t *temporal, int depth) { long x, y; uint32_t pixel_ant; @@ -80,34 +89,35 @@ static void denoise_spatial(uint8_t *src, uint8_t *dst, /* First line has no top neighbor. Only left one for each tmp and * last frame */ - pixel_ant = src[0]<<8; + pixel_ant = LOAD(0); for (x = 0; x < w; x++) { - line_ant[x] = tmp = pixel_ant = lowpass(pixel_ant, src[x]<<8, spatial); + line_ant[x] = tmp = pixel_ant = lowpass(pixel_ant, LOAD(x), spatial); frame_ant[x] = tmp = lowpass(frame_ant[x], tmp, temporal); - dst[x] = (tmp+0x7F)>>8; + STORE(x, tmp); } for (y = 1; y < h; y++) { src += sstride; dst += dstride; frame_ant += w; - pixel_ant = src[0]<<8; + pixel_ant = LOAD(0); for (x = 0; x < w-1; x++) { line_ant[x] = tmp = lowpass(line_ant[x], pixel_ant, spatial); - pixel_ant = lowpass(pixel_ant, src[x+1]<<8, spatial); + pixel_ant = lowpass(pixel_ant, LOAD(x+1), spatial); frame_ant[x] = tmp = lowpass(frame_ant[x], tmp, temporal); - dst[x] = (tmp+0x7F)>>8; + STORE(x, tmp); } line_ant[x] = tmp = lowpass(line_ant[x], pixel_ant, spatial); frame_ant[x] = tmp = lowpass(frame_ant[x], tmp, temporal); - dst[x] = (tmp+0x7F)>>8; + STORE(x, tmp); } } -static void denoise(uint8_t *src, uint8_t *dst, - uint16_t *line_ant, uint16_t **frame_ant_ptr, - int w, int h, int sstride, int dstride, - int16_t *spatial, int16_t *temporal) +av_always_inline +static void denoise_depth(uint8_t *src, uint8_t *dst, + uint16_t *line_ant, uint16_t **frame_ant_ptr, + int w, int h, int sstride, int dstride, + int16_t *spatial, int16_t *temporal, int depth) { long x, y; uint16_t *frame_ant = *frame_ant_ptr; @@ -116,19 +126,26 @@ static void denoise(uint8_t *src, uint8_t *dst, *frame_ant_ptr = frame_ant = av_malloc(w*h*sizeof(uint16_t)); for (y = 0; y < h; y++, src += sstride, frame_ant += w) for (x = 0; x < w; x++) - frame_ant[x] = src[x]<<8; + frame_ant[x] = LOAD(x); src = frame_src; frame_ant = *frame_ant_ptr; } if (spatial[0]) denoise_spatial(src, dst, line_ant, frame_ant, - w, h, sstride, dstride, spatial, temporal); + w, h, sstride, dstride, spatial, temporal, depth); else denoise_temporal(src, dst, frame_ant, - w, h, sstride, dstride, temporal); + w, h, sstride, dstride, temporal, depth); } +#define denoise(...) \ + switch (hqdn3d->depth) {\ + case 8: denoise_depth(__VA_ARGS__, 8); break;\ + case 9: denoise_depth(__VA_ARGS__, 9); break;\ + case 10: denoise_depth(__VA_ARGS__, 10); break;\ + } + static void precalc_coefs(int16_t *ct, double dist25) { int i; @@ -222,7 +239,23 @@ static void uninit(AVFilterContext *ctx) static int query_formats(AVFilterContext *ctx) { static const enum PixelFormat pix_fmts[] = { - PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_YUV411P, PIX_FMT_NONE + PIX_FMT_YUV420P, + PIX_FMT_YUV422P, + PIX_FMT_YUV444P, + PIX_FMT_YUV410P, + PIX_FMT_YUV411P, + PIX_FMT_YUV440P, + PIX_FMT_YUVJ420P, + PIX_FMT_YUVJ422P, + PIX_FMT_YUVJ444P, + PIX_FMT_YUVJ440P, + AV_NE( PIX_FMT_YUV420P9BE, PIX_FMT_YUV420P9LE ), + AV_NE( PIX_FMT_YUV422P9BE, PIX_FMT_YUV422P9LE ), + AV_NE( PIX_FMT_YUV444P9BE, PIX_FMT_YUV444P9LE ), + AV_NE( PIX_FMT_YUV420P10BE, PIX_FMT_YUV420P10LE ), + AV_NE( PIX_FMT_YUV422P10BE, PIX_FMT_YUV422P10LE ), + AV_NE( PIX_FMT_YUV444P10BE, PIX_FMT_YUV444P10LE ), + PIX_FMT_NONE }; ff_set_common_formats(ctx, ff_make_format_list(pix_fmts)); @@ -236,6 +269,7 @@ static int config_input(AVFilterLink *inlink) hqdn3d->hsub = av_pix_fmt_descriptors[inlink->format].log2_chroma_w; hqdn3d->vsub = av_pix_fmt_descriptors[inlink->format].log2_chroma_h; + hqdn3d->depth = av_pix_fmt_descriptors[inlink->format].comp[0].depth_minus1+1; hqdn3d->line = av_malloc(inlink->w * sizeof(*hqdn3d->line)); if (!hqdn3d->line) From d905c6440637fafca56c4cd17cbe041f2aaae9ff Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Sat, 28 Jul 2012 18:15:56 +0100 Subject: [PATCH 7/9] fate: make yadif tests consistent across systems MMX-enabled systems by default use some dsputil functions differing from the C versions. Adding these flags ensures accurate ones are used everywhere. Signed-off-by: Mans Rullgard --- tests/fate/filter.mak | 4 +- tests/ref/fate/filter-yadif-mode0 | 62 +++++++-------- tests/ref/fate/filter-yadif-mode1 | 124 +++++++++++++++--------------- 3 files changed, 95 insertions(+), 95 deletions(-) diff --git a/tests/fate/filter.mak b/tests/fate/filter.mak index a4c125b5d7..f847a6609c 100644 --- a/tests/fate/filter.mak +++ b/tests/fate/filter.mak @@ -35,10 +35,10 @@ FATE_FILTER += fate-filter-delogo FATE_SAMPLES_AVCONV += fate-filter-delogo FATE_YADIF += fate-filter-yadif-mode0 -fate-filter-yadif-mode0: CMD = framecrc -i $(SAMPLES)/mpeg2/mpeg2_field_encoding.ts -vf yadif=0 +fate-filter-yadif-mode0: CMD = framecrc -flags bitexact -idct simple -i $(SAMPLES)/mpeg2/mpeg2_field_encoding.ts -vf yadif=0 FATE_YADIF += fate-filter-yadif-mode1 -fate-filter-yadif-mode1: CMD = framecrc -i $(SAMPLES)/mpeg2/mpeg2_field_encoding.ts -vf yadif=1 +fate-filter-yadif-mode1: CMD = framecrc -flags bitexact -idct simple -i $(SAMPLES)/mpeg2/mpeg2_field_encoding.ts -vf yadif=1 FATE_FILTER += $(FATE_YADIF) FATE_SAMPLES_AVCONV += $(FATE_YADIF) diff --git a/tests/ref/fate/filter-yadif-mode0 b/tests/ref/fate/filter-yadif-mode0 index ca950d0bd1..e260977141 100644 --- a/tests/ref/fate/filter-yadif-mode0 +++ b/tests/ref/fate/filter-yadif-mode0 @@ -1,32 +1,32 @@ #tb 0: 1/180000 -0, 64800, 64800, 0, 622080, 0x1511cae9 -0, 72000, 72000, 0, 622080, 0x6e77e746 -0, 79200, 79200, 0, 622080, 0x89aac777 -0, 86400, 86400, 0, 622080, 0x7e0a9335 -0, 93600, 93600, 0, 622080, 0x5f34759b -0, 100800, 100800, 0, 622080, 0xfac498a6 -0, 108000, 108000, 0, 622080, 0xe60e7a9e -0, 115200, 115200, 0, 622080, 0x44875bbd -0, 122400, 122400, 0, 622080, 0xfa761aab -0, 129600, 129600, 0, 622080, 0x59be119c -0, 136800, 136800, 0, 622080, 0x21316b36 -0, 144000, 144000, 0, 622080, 0x929fde5b -0, 151200, 151200, 0, 622080, 0xfca8990c -0, 158400, 158400, 0, 622080, 0x1ec87d02 -0, 165600, 165600, 0, 622080, 0x5768eea0 -0, 172800, 172800, 0, 622080, 0x1a0894ab -0, 180000, 180000, 0, 622080, 0xb4e61323 -0, 187200, 187200, 0, 622080, 0xb773341a -0, 194400, 194400, 0, 622080, 0x8a914cf7 -0, 201600, 201600, 0, 622080, 0xf1cfbc7d -0, 208800, 208800, 0, 622080, 0xebaeb317 -0, 216000, 216000, 0, 622080, 0xbae9adf4 -0, 223200, 223200, 0, 622080, 0x593544fd -0, 230400, 230400, 0, 622080, 0x2cd8ec0b -0, 237600, 237600, 0, 622080, 0x8032d9d4 -0, 244800, 244800, 0, 622080, 0x5c67ace7 -0, 252000, 252000, 0, 622080, 0x95714528 -0, 259200, 259200, 0, 622080, 0xa11cbed2 -0, 266400, 266400, 0, 622080, 0x7389f8f1 -0, 273600, 273600, 0, 622080, 0xa694f3f2 -0, 280800, 280800, 0, 622080, 0xac3a3d09 +0, 64800, 64800, 0, 622080, 0x4440caef +0, 72000, 72000, 0, 622080, 0xce67e69d +0, 79200, 79200, 0, 622080, 0x1dbdc653 +0, 86400, 86400, 0, 622080, 0x82c591d1 +0, 93600, 93600, 0, 622080, 0x8193740b +0, 100800, 100800, 0, 622080, 0xcb219711 +0, 108000, 108000, 0, 622080, 0x1870783b +0, 115200, 115200, 0, 622080, 0x7080590b +0, 122400, 122400, 0, 622080, 0x6df4175d +0, 129600, 129600, 0, 622080, 0x6b530e95 +0, 136800, 136800, 0, 622080, 0x7f9d66f7 +0, 144000, 144000, 0, 622080, 0x338cda81 +0, 151200, 151200, 0, 622080, 0xb13797f8 +0, 158400, 158400, 0, 622080, 0xb51e7ca4 +0, 165600, 165600, 0, 622080, 0x353eed75 +0, 172800, 172800, 0, 622080, 0xf93e92b0 +0, 180000, 180000, 0, 622080, 0xd0811094 +0, 187200, 187200, 0, 622080, 0xb04a3141 +0, 194400, 194400, 0, 622080, 0x4ab84909 +0, 201600, 201600, 0, 622080, 0xa0fcb8fb +0, 208800, 208800, 0, 622080, 0x9003aebb +0, 216000, 216000, 0, 622080, 0x153faa3e +0, 223200, 223200, 0, 622080, 0xae724063 +0, 230400, 230400, 0, 622080, 0xeb4de77a +0, 237600, 237600, 0, 622080, 0x209ed8c7 +0, 244800, 244800, 0, 622080, 0xe2bbac96 +0, 252000, 252000, 0, 622080, 0xe945441e +0, 259200, 259200, 0, 622080, 0x8f8cbd5f +0, 266400, 266400, 0, 622080, 0xbc3cf717 +0, 273600, 273600, 0, 622080, 0x0109f125 +0, 280800, 280800, 0, 622080, 0x230c373f diff --git a/tests/ref/fate/filter-yadif-mode1 b/tests/ref/fate/filter-yadif-mode1 index 0a2f61cb29..b4981377ef 100644 --- a/tests/ref/fate/filter-yadif-mode1 +++ b/tests/ref/fate/filter-yadif-mode1 @@ -1,63 +1,63 @@ #tb 0: 1/180000 -0, 64800, 64800, 0, 622080, 0x1511cae9 -0, 68400, 68400, 0, 622080, 0xb88ca855 -0, 72000, 72000, 0, 622080, 0x6e77e746 -0, 75600, 75600, 0, 622080, 0x5da19198 -0, 79200, 79200, 0, 622080, 0x89aac777 -0, 82800, 82800, 0, 622080, 0xee31c8a8 -0, 86400, 86400, 0, 622080, 0x7e0a9335 -0, 90000, 90000, 0, 622080, 0xcbb7aac5 -0, 93600, 93600, 0, 622080, 0x5f34759b -0, 97200, 97200, 0, 622080, 0x19972f1a -0, 100800, 100800, 0, 622080, 0xfac498a6 -0, 104400, 104400, 0, 622080, 0xac7d34b9 -0, 108000, 108000, 0, 622080, 0xe60e7a9e -0, 111600, 111600, 0, 622080, 0x4adfe592 -0, 115200, 115200, 0, 622080, 0x44875bbd -0, 118800, 118800, 0, 622080, 0x5d738330 -0, 122400, 122400, 0, 622080, 0xfa761aab -0, 126000, 126000, 0, 622080, 0xb60b4447 -0, 129600, 129600, 0, 622080, 0x59be119c -0, 133200, 133200, 0, 622080, 0x1e11acf4 -0, 136800, 136800, 0, 622080, 0x21316b36 -0, 140400, 140400, 0, 622080, 0x5ed635d0 -0, 144000, 144000, 0, 622080, 0x929fde5b -0, 147600, 147600, 0, 622080, 0x939857af -0, 151200, 151200, 0, 622080, 0xfca8990c -0, 154800, 154800, 0, 622080, 0x530b28fd -0, 158400, 158400, 0, 622080, 0x1ec87d02 -0, 162000, 162000, 0, 622080, 0x3bc0d5d3 -0, 165600, 165600, 0, 622080, 0x5768eea0 -0, 169200, 169200, 0, 622080, 0x77e0fe99 -0, 172800, 172800, 0, 622080, 0x1a0894ab -0, 176400, 176400, 0, 622080, 0xd2151c1e -0, 180000, 180000, 0, 622080, 0xb4e61323 -0, 183600, 183600, 0, 622080, 0xe021a815 -0, 187200, 187200, 0, 622080, 0xb773341a -0, 190800, 190800, 0, 622080, 0xceae4f12 -0, 194400, 194400, 0, 622080, 0x8a914cf7 -0, 198000, 198000, 0, 622080, 0x4c2f3330 -0, 201600, 201600, 0, 622080, 0xf1cfbc7d -0, 205200, 205200, 0, 622080, 0xf534c392 -0, 208800, 208800, 0, 622080, 0xebaeb317 -0, 212400, 212400, 0, 622080, 0x88f01c11 -0, 216000, 216000, 0, 622080, 0xbae9adf4 -0, 219600, 219600, 0, 622080, 0x654d5df2 -0, 223200, 223200, 0, 622080, 0x593544fd -0, 226800, 226800, 0, 622080, 0x89ef6f8a -0, 230400, 230400, 0, 622080, 0x2cd8ec0b -0, 234000, 234000, 0, 622080, 0x78a7b5f1 -0, 237600, 237600, 0, 622080, 0x8032d9d4 -0, 241200, 241200, 0, 622080, 0x8152d67f -0, 244800, 244800, 0, 622080, 0x5c67ace7 -0, 248400, 248400, 0, 622080, 0x6590ff5f -0, 252000, 252000, 0, 622080, 0x95714528 -0, 255600, 255600, 0, 622080, 0x51d2be96 -0, 259200, 259200, 0, 622080, 0xa11cbed2 -0, 262800, 262800, 0, 622080, 0x483f65f7 -0, 266400, 266400, 0, 622080, 0x7389f8f1 -0, 270000, 270000, 0, 622080, 0x7a69143d -0, 273600, 273600, 0, 622080, 0xa694f3f2 -0, 277200, 277200, 0, 622080, 0xeccc58ff -0, 280800, 280800, 0, 622080, 0xac3a3d09 -0, 284400, 284400, 0, 622080, 0xc4d2c370 +0, 64800, 64800, 0, 622080, 0x4440caef +0, 68400, 68400, 0, 622080, 0xa5cea88b +0, 72000, 72000, 0, 622080, 0xce67e69d +0, 75600, 75600, 0, 622080, 0x9a57891f +0, 79200, 79200, 0, 622080, 0x1dbdc653 +0, 82800, 82800, 0, 622080, 0xc171c0c5 +0, 86400, 86400, 0, 622080, 0x82c591d1 +0, 90000, 90000, 0, 622080, 0x20db9890 +0, 93600, 93600, 0, 622080, 0x8193740b +0, 97200, 97200, 0, 622080, 0xdb181d52 +0, 100800, 100800, 0, 622080, 0xcb219711 +0, 104400, 104400, 0, 622080, 0xc2b913d1 +0, 108000, 108000, 0, 622080, 0x1870783b +0, 111600, 111600, 0, 622080, 0xf1d9c5fb +0, 115200, 115200, 0, 622080, 0x7080590b +0, 118800, 118800, 0, 622080, 0x669c5775 +0, 122400, 122400, 0, 622080, 0x6df4175d +0, 126000, 126000, 0, 622080, 0x01921a16 +0, 129600, 129600, 0, 622080, 0x6b530e95 +0, 133200, 133200, 0, 622080, 0xd5047bc9 +0, 136800, 136800, 0, 622080, 0x7f9d66f7 +0, 140400, 140400, 0, 622080, 0xa8b006eb +0, 144000, 144000, 0, 622080, 0x338cda81 +0, 147600, 147600, 0, 622080, 0xf0e125a7 +0, 151200, 151200, 0, 622080, 0xb13797f8 +0, 154800, 154800, 0, 622080, 0x4afe2976 +0, 158400, 158400, 0, 622080, 0xb51e7ca4 +0, 162000, 162000, 0, 622080, 0x637fcbfe +0, 165600, 165600, 0, 622080, 0x353eed75 +0, 169200, 169200, 0, 622080, 0xd9a8f5ac +0, 172800, 172800, 0, 622080, 0xf93e92b0 +0, 176400, 176400, 0, 622080, 0x4540039f +0, 180000, 180000, 0, 622080, 0xd0811094 +0, 183600, 183600, 0, 622080, 0x3039906f +0, 187200, 187200, 0, 622080, 0xb04a3141 +0, 190800, 190800, 0, 622080, 0x52872cf9 +0, 194400, 194400, 0, 622080, 0x4ab84909 +0, 198000, 198000, 0, 622080, 0x82de12ee +0, 201600, 201600, 0, 622080, 0xa0fcb8fb +0, 205200, 205200, 0, 622080, 0x7e849cc9 +0, 208800, 208800, 0, 622080, 0x9003aebb +0, 212400, 212400, 0, 622080, 0xffe6f770 +0, 216000, 216000, 0, 622080, 0x153faa3e +0, 219600, 219600, 0, 622080, 0xb67f3233 +0, 223200, 223200, 0, 622080, 0xae724063 +0, 226800, 226800, 0, 622080, 0x15fe44b4 +0, 230400, 230400, 0, 622080, 0xeb4de77a +0, 234000, 234000, 0, 622080, 0x380f8563 +0, 237600, 237600, 0, 622080, 0x209ed8c7 +0, 241200, 241200, 0, 622080, 0xb964d70f +0, 244800, 244800, 0, 622080, 0xe2bbac96 +0, 248400, 248400, 0, 622080, 0x4f60f7f4 +0, 252000, 252000, 0, 622080, 0xe945441e +0, 255600, 255600, 0, 622080, 0xd0afb742 +0, 259200, 259200, 0, 622080, 0x8f8cbd5f +0, 262800, 262800, 0, 622080, 0xb9a15294 +0, 266400, 266400, 0, 622080, 0xbc3cf717 +0, 270000, 270000, 0, 622080, 0xb70b01a9 +0, 273600, 273600, 0, 622080, 0x0109f125 +0, 277200, 277200, 0, 622080, 0xcb3a371f +0, 280800, 280800, 0, 622080, 0x230c373f +0, 284400, 284400, 0, 622080, 0x82dfb1f2 From 681ed0009905a088aae2a5caf2308d89aaa80562 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Thu, 26 Jul 2012 16:35:12 -0700 Subject: [PATCH 8/9] avf: introduce nobuffer option Useful in cases where a significant analyzeduration is still needed, while minimizing buffering before output. An example is processing low-latency streams where all media types won't necessarily come in if the analyzeduration is small. Additional changes by Josh Allmann Signed-off-by: Anton Khirnov --- doc/APIchanges | 3 +++ libavformat/avformat.h | 1 + libavformat/options_table.h | 1 + libavformat/utils.c | 11 ++++++++--- libavformat/version.h | 4 ++-- 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 8770b6d570..058fab6334 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,9 @@ libavutil: 2011-04-18 API changes, most recent first: +2012-07-xx - xxxxxxx - lavf 54.13.0 - avformat.h + Add AVFMT_FLAG_NOBUFFER for low latency use cases. + 2012-07-xx - xxxxxxx - lavfi 3.0.0 - avfilter.h Add avfilter_unref_bufferp(). diff --git a/libavformat/avformat.h b/libavformat/avformat.h index e292206c60..7c97ada2c8 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -887,6 +887,7 @@ typedef struct AVFormatContext { #define AVFMT_FLAG_IGNDTS 0x0008 ///< Ignore DTS on frames that contain both DTS & PTS #define AVFMT_FLAG_NOFILLIN 0x0010 ///< Do not infer any values from other values, just return what is stored in the container #define AVFMT_FLAG_NOPARSE 0x0020 ///< Do not use AVParsers, you also must set AVFMT_FLAG_NOFILLIN as the fillin code works on frames and no parsing -> no frames. Also seeking to frames can not work if parsing to find frame boundaries has been disabled +#define AVFMT_FLAG_NOBUFFER 0x0040 ///< Do not buffer frames when possible #define AVFMT_FLAG_CUSTOM_IO 0x0080 ///< The caller has supplied a custom AVIOContext, don't avio_close() it. #define AVFMT_FLAG_DISCARD_CORRUPT 0x0100 ///< Discard frames marked corrupted diff --git a/libavformat/options_table.h b/libavformat/options_table.h index 58f3dcff68..f3384cab25 100644 --- a/libavformat/options_table.h +++ b/libavformat/options_table.h @@ -40,6 +40,7 @@ static const AVOption options[]={ {"noparse", "disable AVParsers, this needs nofillin too", 0, AV_OPT_TYPE_CONST, {.dbl = AVFMT_FLAG_NOPARSE }, INT_MIN, INT_MAX, D, "fflags"}, {"igndts", "ignore dts", 0, AV_OPT_TYPE_CONST, {.dbl = AVFMT_FLAG_IGNDTS }, INT_MIN, INT_MAX, D, "fflags"}, {"discardcorrupt", "discard corrupted frames", 0, AV_OPT_TYPE_CONST, {.dbl = AVFMT_FLAG_DISCARD_CORRUPT }, INT_MIN, INT_MAX, D, "fflags"}, +{"nobuffer", "reduce the latency introduced by optional buffering", 0, AV_OPT_TYPE_CONST, {.dbl = AVFMT_FLAG_NOBUFFER }, 0, INT_MAX, D, "fflags"}, {"analyzeduration", "how many microseconds are analyzed to estimate duration", OFFSET(max_analyze_duration), AV_OPT_TYPE_INT, {.dbl = 5*AV_TIME_BASE }, 0, INT_MAX, D}, {"cryptokey", "decryption key", OFFSET(key), AV_OPT_TYPE_BINARY, {.dbl = 0}, 0, 0, D}, {"indexmem", "max memory used for timestamp index (per stream)", OFFSET(max_index_size), AV_OPT_TYPE_INT, {.dbl = 1<<20 }, 0, INT_MAX, D}, diff --git a/libavformat/utils.c b/libavformat/utils.c index 4ec70b7f51..149913cb04 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -2383,9 +2383,14 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) break; } - pkt= add_to_pktbuf(&ic->packet_buffer, &pkt1, &ic->packet_buffer_end); - if ((ret = av_dup_packet(pkt)) < 0) - goto find_stream_info_err; + if (ic->flags & AVFMT_FLAG_NOBUFFER) { + pkt = &pkt1; + } else { + pkt = add_to_pktbuf(&ic->packet_buffer, &pkt1, + &ic->packet_buffer_end); + if ((ret = av_dup_packet(pkt)) < 0) + goto find_stream_info_err; + } read_size += pkt->size; diff --git a/libavformat/version.h b/libavformat/version.h index de6da526c3..6b7ada8496 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -30,8 +30,8 @@ #include "libavutil/avutil.h" #define LIBAVFORMAT_VERSION_MAJOR 54 -#define LIBAVFORMAT_VERSION_MINOR 12 -#define LIBAVFORMAT_VERSION_MICRO 1 +#define LIBAVFORMAT_VERSION_MINOR 13 +#define LIBAVFORMAT_VERSION_MICRO 0 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ From fe1c1198e670242f3cf9e3e1eef27cff77f3ee23 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 28 Jun 2012 15:49:51 +0200 Subject: [PATCH 9/9] lavf: use dts difference instead of AVPacket.duration in find_stream_info() AVPacket.duration is mostly made up and thus completely useless, this is especially true for video streams. Therefore use dts difference for framerate estimation and the max_analyze_duration check. The asyncts test now needs -analyzeduration, because the default is 5 seconds and the audio stream in the sample appears at ~10 seconds. --- libavformat/avformat.h | 10 +++++++++- libavformat/utils.c | 38 ++++++++++++++++++++++++++++++++------ tests/fate/filter.mak | 2 +- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 7c97ada2c8..0e50487414 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -718,9 +718,17 @@ typedef struct AVStream { int64_t duration_gcd; int duration_count; double duration_error[MAX_STD_TIMEBASES]; - int64_t codec_info_duration; int nb_decoded_frames; int found_decoder; + + /** + * Those are used for average framerate estimation. + */ + int64_t fps_first_dts; + int fps_first_dts_idx; + int64_t fps_last_dts; + int fps_last_dts_idx; + } *info; int pts_wrap_bits; /**< number of bits in pts (used for wrapping control) */ diff --git a/libavformat/utils.c b/libavformat/utils.c index 149913cb04..bd94f7d7a7 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -2288,6 +2288,8 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) for (i=0; inb_streams; i++) { ic->streams[i]->info->last_dts = AV_NOPTS_VALUE; + ic->streams[i]->info->fps_first_dts = AV_NOPTS_VALUE; + ic->streams[i]->info->fps_last_dts = AV_NOPTS_VALUE; } count = 0; @@ -2395,12 +2397,31 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) read_size += pkt->size; st = ic->streams[pkt->stream_index]; - if (st->codec_info_nb_frames>1) { - if (av_rescale_q(st->info->codec_info_duration, st->time_base, AV_TIME_BASE_Q) >= ic->max_analyze_duration) { + if (pkt->dts != AV_NOPTS_VALUE && st->codec_info_nb_frames > 1) { + /* check for non-increasing dts */ + if (st->info->fps_last_dts != AV_NOPTS_VALUE && + st->info->fps_last_dts >= pkt->dts) { + av_log(ic, AV_LOG_WARNING, "Non-increasing DTS in stream %d: " + "packet %d with DTS %"PRId64", packet %d with DTS " + "%"PRId64"\n", st->index, st->info->fps_last_dts_idx, + st->info->fps_last_dts, st->codec_info_nb_frames, pkt->dts); + st->info->fps_first_dts = st->info->fps_last_dts = AV_NOPTS_VALUE; + } + + /* update stored dts values */ + if (st->info->fps_first_dts == AV_NOPTS_VALUE) { + st->info->fps_first_dts = pkt->dts; + st->info->fps_first_dts_idx = st->codec_info_nb_frames; + } + st->info->fps_last_dts = pkt->dts; + st->info->fps_last_dts_idx = st->codec_info_nb_frames; + + /* check max_analyze_duration */ + if (av_rescale_q(pkt->dts - st->info->fps_first_dts, st->time_base, + AV_TIME_BASE_Q) >= ic->max_analyze_duration) { av_log(ic, AV_LOG_WARNING, "max_analyze_duration reached\n"); break; } - st->info->codec_info_duration += pkt->duration; } { int64_t last = st->info->last_dts; @@ -2460,10 +2481,15 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) for(i=0;inb_streams;i++) { st = ic->streams[i]; if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - if (st->codec_info_nb_frames>2 && !st->avg_frame_rate.num && st->info->codec_info_duration) + /* estimate average framerate if not set by demuxer */ + if (!st->avg_frame_rate.num && st->info->fps_last_dts != st->info->fps_first_dts) { + int64_t delta_dts = st->info->fps_last_dts - st->info->fps_first_dts; + int delta_packets = st->info->fps_last_dts_idx - st->info->fps_first_dts_idx; + av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den, - (st->codec_info_nb_frames-2)*(int64_t)st->time_base.den, - st->info->codec_info_duration*(int64_t)st->time_base.num, 60000); + delta_packets*(int64_t)st->time_base.den, + delta_dts*(int64_t)st->time_base.num, 60000); + } // the check for tb_unreliable() is not completely correct, since this is not about handling // a unreliable/inexact time base, but a time base that is finer than necessary, as e.g. // ipmovie.c produces. diff --git a/tests/fate/filter.mak b/tests/fate/filter.mak index f847a6609c..7c1170f43f 100644 --- a/tests/fate/filter.mak +++ b/tests/fate/filter.mak @@ -22,7 +22,7 @@ FATE_SAMPLES_AVCONV += $(FATE_AMIX) FATE_ASYNCTS += fate-filter-asyncts fate-filter-asyncts: SRC = $(SAMPLES)/nellymoser/nellymoser-discont.flv -fate-filter-asyncts: CMD = pcm -i $(SRC) -af asyncts +fate-filter-asyncts: CMD = pcm -analyzeduration 10000000 -i $(SRC) -af asyncts fate-filter-asyncts: CMP = oneoff fate-filter-asyncts: REF = $(SAMPLES)/nellymoser/nellymoser-discont.pcm