Merge remote-tracking branch 'qatar/master'

* qatar/master:
  avprobe, cmdutils: K&R formatting cosmetics
  tests: K&R formatting cosmetics for test programs
  lavf: free packets for muxers implementing interleave_packet().
  lavf: fix and extend av_interleaved_write_frame() doxy.
  mov: Remove dead stores for spherical coordinates for channel position.
  error_resilience: K&R formatting cosmetics
  RELEASE_NOTES: mention hiding private symbols in shared builds.
  RELEASE_NOTES: mention some notable API changes in 0.8

Conflicts:
	cmdutils.h
	doc/RELEASE_NOTES
	ffprobe.c
	libavcodec/error_resilience.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
release/0.10
Michael Niedermayer 13 years ago
commit c130428ab5
  1. 18
      cmdutils.h
  2. 34
      doc/RELEASE_NOTES
  3. 9
      ffprobe.c
  4. 404
      libavcodec/error_resilience.c
  5. 15
      libavformat/avformat.h
  6. 7
      libavformat/mov.c
  7. 9
      libavformat/utils.c
  8. 3
      tests/base64.c
  9. 5
      tests/rotozoom.c
  10. 25
      tests/tiny_psnr.c
  11. 14
      tests/videogen.c

@ -105,7 +105,8 @@ int opt_timelimit(const char *opt, const char *arg);
* @param min the minimum valid accepted value * @param min the minimum valid accepted value
* @param max the maximum valid accepted value * @param max the maximum valid accepted value
*/ */
double parse_number_or_die(const char *context, const char *numstr, int type, double min, double max); double parse_number_or_die(const char *context, const char *numstr, int type,
double min, double max);
/** /**
* Parse a string specifying a time and return its corresponding * Parse a string specifying a time and return its corresponding
@ -121,7 +122,8 @@ double parse_number_or_die(const char *context, const char *numstr, int type, do
* *
* @see parse_date() * @see parse_date()
*/ */
int64_t parse_time_or_die(const char *context, const char *timestr, int is_duration); int64_t parse_time_or_die(const char *context, const char *timestr,
int is_duration);
typedef struct SpecifierOpt { typedef struct SpecifierOpt {
char *specifier; /**< stream/chapter/program/... specifier */ char *specifier; /**< stream/chapter/program/... specifier */
@ -167,7 +169,8 @@ typedef struct {
const char *argname; const char *argname;
} OptionDef; } OptionDef;
void show_help_options(const OptionDef *options, const char *msg, int mask, int value); void show_help_options(const OptionDef *options, const char *msg, int mask,
int value);
/** /**
* Show help for all options with given flags in class and all its * Show help for all options with given flags in class and all its
@ -193,7 +196,8 @@ void parse_options(void *optctx, int argc, char **argv, const OptionDef *options
* *
* @return on success 1 if arg was consumed, 0 otherwise; negative number on error * @return on success 1 if arg was consumed, 0 otherwise; negative number on error
*/ */
int parse_option(void *optctx, const char *opt, const char *arg, const OptionDef *options); int parse_option(void *optctx, const char *opt, const char *arg,
const OptionDef *options);
/** /**
* Find the '-loglevel' option in the command line args and apply it. * Find the '-loglevel' option in the command line args and apply it.
@ -221,7 +225,8 @@ int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec);
* @param st A stream from s for which the options should be filtered. * @param st A stream from s for which the options should be filtered.
* @return a pointer to the created dictionary * @return a pointer to the created dictionary
*/ */
AVDictionary *filter_codec_opts(AVDictionary *opts, AVCodec *codec, AVFormatContext *s, AVStream *st); AVDictionary *filter_codec_opts(AVDictionary *opts, AVCodec *codec,
AVFormatContext *s, AVStream *st);
/** /**
* Setup AVCodecContext options for avformat_find_stream_info(). * Setup AVCodecContext options for avformat_find_stream_info().
@ -234,7 +239,8 @@ AVDictionary *filter_codec_opts(AVDictionary *opts, AVCodec *codec, AVFormatCont
* @return pointer to the created array of dictionaries, NULL if it * @return pointer to the created array of dictionaries, NULL if it
* cannot be created * cannot be created
*/ */
AVDictionary **setup_find_stream_info_opts(AVFormatContext *s, AVDictionary *codec_opts); AVDictionary **setup_find_stream_info_opts(AVFormatContext *s,
AVDictionary *codec_opts);
/** /**
* Print an error message to stderr, indicating filename and a human * Print an error message to stderr, indicating filename and a human

@ -6,7 +6,6 @@ Release Notes
General notes General notes
------------- -------------
This release is binary compatible with 0.8. The 'ffmpeg' command-line tool has This release is binary compatible with 0.8. The 'ffmpeg' command-line tool has
been extended to also support the command line syntax and features of a tool been extended to also support the command line syntax and features of a tool
called avconv. called avconv.
@ -32,7 +31,30 @@ API changes
A number of additional APIs have been introduced and some existing A number of additional APIs have been introduced and some existing
functions have been deprecated and are scheduled for removal in the next functions have been deprecated and are scheduled for removal in the next
release. Please see the file doc/APIchanges for details along with release. Significant API changes include:
* new audio decoding API which decodes from an AVPacket to an AVFrame and
is able to use AVCodecContext.get_buffer() in the similar way as video decoding.
* new audio encoding API which encodes from an AVFrame to an AVPacket, thus
allowing it to properly output timing information and side data.
* rewritten AVOptions API with better built-in support for private options.
* private options support for demuxers [avformat_open_input()], muxers
[avformat_write_header()], encoders and decoders [avcodec_open2()].
As a result, many format- or codec-specific fields and flags in AVFormatContext
and AVCodecContext were deprecated -- notably most of CODEC_FLAG2_* and many
CODEC_FLAG_*.
* new API for custom IO interrupt callbacks.
* #include cleanup in libavutil -- libavutil/avutil.h no longer includes all
the other headers in libavutil, they must be included manually. One specific
result is that libavutil/mathematics.h is no longer included from
libavcodec/avcodec.h, which is a common source of errors.
Please see the file doc/APIchanges for details along with
similar programmer-centric information. similar programmer-centric information.
@ -40,5 +62,13 @@ similar programmer-centric information.
Other notable changes Other notable changes
--------------------- ---------------------
Libavcodec and libavformat built as shared libraries now hide non-public
symbols. This will break applications using those symbols. Possible solutions
are, in order of preference:
1) Try finding a way of accomplishing the same with public API.
2) If there is no corresponding public API, but you think there should be,
post a request on the user mailing list or IRC channel.
3) Finally if your program needs access to FFmpeg / libavcodec / libavformat
internals for some special reason then the best solution is to link statically.
Please see the Changelog file for a more detailed list of changes. Please see the Changelog file for a more detailed list of changes.

@ -1557,7 +1557,8 @@ static int open_input_file(AVFormatContext **fmt_ctx_ptr, const char *filename)
AVFormatContext *fmt_ctx = NULL; AVFormatContext *fmt_ctx = NULL;
AVDictionaryEntry *t; AVDictionaryEntry *t;
if ((err = avformat_open_input(&fmt_ctx, filename, iformat, &format_opts)) < 0) { if ((err = avformat_open_input(&fmt_ctx, filename,
iformat, &format_opts)) < 0) {
print_error(filename, err); print_error(filename, err);
return err; return err;
} }
@ -1581,7 +1582,8 @@ static int open_input_file(AVFormatContext **fmt_ctx_ptr, const char *filename)
AVCodec *codec; AVCodec *codec;
if (!(codec = avcodec_find_decoder(stream->codec->codec_id))) { if (!(codec = avcodec_find_decoder(stream->codec->codec_id))) {
av_log(NULL, AV_LOG_ERROR, "Unsupported codec with id %d for input stream %d\n", av_log(NULL, AV_LOG_ERROR,
"Unsupported codec with id %d for input stream %d\n",
stream->codec->codec_id, stream->index); stream->codec->codec_id, stream->index);
} else if (avcodec_open2(stream->codec, codec, NULL) < 0) { } else if (avcodec_open2(stream->codec, codec, NULL) < 0) {
av_log(NULL, AV_LOG_ERROR, "Error while opening codec for input stream %d\n", av_log(NULL, AV_LOG_ERROR, "Error while opening codec for input stream %d\n",
@ -1700,7 +1702,8 @@ static int opt_format(const char *opt, const char *arg)
static void opt_input_file(void *optctx, const char *arg) static void opt_input_file(void *optctx, const char *arg)
{ {
if (input_filename) { if (input_filename) {
av_log(NULL, AV_LOG_ERROR, "Argument '%s' provided as input filename, but '%s' was already specified.\n", av_log(NULL, AV_LOG_ERROR,
"Argument '%s' provided as input filename, but '%s' was already specified.\n",
arg, input_filename); arg, input_filename);
exit(1); exit(1);
} }

@ -40,7 +40,8 @@
*/ */
#undef mb_intra #undef mb_intra
static void decode_mb(MpegEncContext *s, int ref){ static void decode_mb(MpegEncContext *s, int ref)
{
s->dest[0] = s->current_picture.f.data[0] + (s->mb_y * 16 * s->linesize) + s->mb_x * 16; s->dest[0] = s->current_picture.f.data[0] + (s->mb_y * 16 * s->linesize) + s->mb_x * 16;
s->dest[1] = s->current_picture.f.data[1] + (s->mb_y * (16 >> s->chroma_y_shift) * s->uvlinesize) + s->mb_x * (16 >> s->chroma_x_shift); s->dest[1] = s->current_picture.f.data[1] + (s->mb_y * (16 >> s->chroma_y_shift) * s->uvlinesize) + s->mb_x * (16 >> s->chroma_x_shift);
s->dest[2] = s->current_picture.f.data[2] + (s->mb_y * (16 >> s->chroma_y_shift) * s->uvlinesize) + s->mb_x * (16 >> s->chroma_x_shift); s->dest[2] = s->current_picture.f.data[2] + (s->mb_y * (16 >> s->chroma_y_shift) * s->uvlinesize) + s->mb_x * (16 >> s->chroma_x_shift);
@ -56,9 +57,11 @@ static void decode_mb(MpegEncContext *s, int ref){
* practice then correct remapping should be added. */ * practice then correct remapping should be added. */
if (ref >= h->ref_count[0]) if (ref >= h->ref_count[0])
ref = 0; ref = 0;
fill_rectangle(&s->current_picture.f.ref_index[0][4*h->mb_xy], 2, 2, 2, ref, 1); fill_rectangle(&s->current_picture.f.ref_index[0][4 * h->mb_xy],
2, 2, 2, ref, 1);
fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1); fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1);
fill_rectangle(h->mv_cache[0][ scan8[0] ], 4, 4, 8, pack16to32(s->mv[0][0][0],s->mv[0][0][1]), 4); fill_rectangle(h->mv_cache[0][scan8[0]], 4, 4, 8,
pack16to32(s->mv[0][0][0], s->mv[0][0][1]), 4);
assert(!FRAME_MBAFF); assert(!FRAME_MBAFF);
ff_h264_hl_decode_mb(h); ff_h264_hl_decode_mb(h);
} else { } else {
@ -71,7 +74,8 @@ static void decode_mb(MpegEncContext *s, int ref){
* @param stride the number of MVs to get to the next row * @param stride the number of MVs to get to the next row
* @param mv_step the number of MVs per row or column in a macroblock * @param mv_step the number of MVs per row or column in a macroblock
*/ */
static void set_mv_strides(MpegEncContext *s, int *mv_step, int *stride){ static void set_mv_strides(MpegEncContext *s, int *mv_step, int *stride)
{
if (s->codec_id == CODEC_ID_H264) { if (s->codec_id == CODEC_ID_H264) {
H264Context *h = (void*)s; H264Context *h = (void*)s;
assert(s->quarter_sample); assert(s->quarter_sample);
@ -86,26 +90,32 @@ static void set_mv_strides(MpegEncContext *s, int *mv_step, int *stride){
/** /**
* Replace the current MB with a flat dc-only version. * Replace the current MB with a flat dc-only version.
*/ */
static void put_dc(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, int mb_x, int mb_y) static void put_dc(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb,
uint8_t *dest_cr, int mb_x, int mb_y)
{ {
int dc, dcu, dcv, y, i; int dc, dcu, dcv, y, i;
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
dc = s->dc_val[0][mb_x * 2 + (i & 1) + (mb_y * 2 + (i >> 1)) * s->b8_stride]; dc = s->dc_val[0][mb_x * 2 + (i & 1) + (mb_y * 2 + (i >> 1)) * s->b8_stride];
if(dc<0) dc=0; if (dc < 0)
else if(dc>2040) dc=2040; dc = 0;
else if (dc > 2040)
dc = 2040;
for (y = 0; y < 8; y++) { for (y = 0; y < 8; y++) {
int x; int x;
for(x=0; x<8; x++){ for (x = 0; x < 8; x++)
dest_y[x + (i & 1) * 8 + (y + (i >> 1) * 8) * s->linesize] = dc / 8; dest_y[x + (i & 1) * 8 + (y + (i >> 1) * 8) * s->linesize] = dc / 8;
} }
} }
}
dcu = s->dc_val[1][mb_x + mb_y * s->mb_stride]; dcu = s->dc_val[1][mb_x + mb_y * s->mb_stride];
dcv = s->dc_val[2][mb_x + mb_y * s->mb_stride]; dcv = s->dc_val[2][mb_x + mb_y * s->mb_stride];
if (dcu<0 ) dcu=0; if (dcu < 0)
else if(dcu>2040) dcu=2040; dcu = 0;
if (dcv<0 ) dcv=0; else if (dcu > 2040)
else if(dcv>2040) dcv=2040; dcu = 2040;
if (dcv < 0)
dcv = 0;
else if (dcv > 2040)
dcv = 2040;
for (y = 0; y < 8; y++) { for (y = 0; y < 8; y++) {
int x; int x;
for (x = 0; x < 8; x++) { for (x = 0; x < 8; x++) {
@ -115,7 +125,8 @@ static void put_dc(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t
} }
} }
static void filter181(int16_t *data, int width, int height, int stride){ static void filter181(int16_t *data, int width, int height, int stride)
{
int x, y; int x, y;
/* horizontal filter */ /* horizontal filter */
@ -124,10 +135,9 @@ static void filter181(int16_t *data, int width, int height, int stride){
for (x = 1; x < width - 1; x++) { for (x = 1; x < width - 1; x++) {
int dc; int dc;
dc = -prev_dc +
dc= - prev_dc data[x + y * stride] * 8 -
+ data[x + y*stride]*8 data[x + 1 + y * stride];
- data[x + 1 + y*stride];
dc = (dc * 10923 + 32768) >> 16; dc = (dc * 10923 + 32768) >> 16;
prev_dc = data[x + y * stride]; prev_dc = data[x + y * stride];
data[x + y * stride] = dc; data[x + y * stride] = dc;
@ -141,9 +151,9 @@ static void filter181(int16_t *data, int width, int height, int stride){
for (y = 1; y < height - 1; y++) { for (y = 1; y < height - 1; y++) {
int dc; int dc;
dc= - prev_dc dc = -prev_dc +
+ data[x + y *stride]*8 data[x + y * stride] * 8 -
- data[x + (y+1)*stride]; data[x + (y + 1) * stride];
dc = (dc * 10923 + 32768) >> 16; dc = (dc * 10923 + 32768) >> 16;
prev_dc = data[x + y * stride]; prev_dc = data[x + y * stride];
data[x + y * stride] = dc; data[x + y * stride] = dc;
@ -156,7 +166,9 @@ static void filter181(int16_t *data, int width, int height, int stride){
* @param w width in 8 pixel blocks * @param w width in 8 pixel blocks
* @param h height in 8 pixel blocks * @param h height in 8 pixel blocks
*/ */
static void guess_dc(MpegEncContext *s, int16_t *dc, int w, int h, int stride, int is_luma){ static void guess_dc(MpegEncContext *s, int16_t *dc, int w,
int h, int stride, int is_luma)
{
int b_x, b_y; int b_x, b_y;
int16_t (*col )[4] = av_malloc(stride*h*sizeof( int16_t)*4); int16_t (*col )[4] = av_malloc(stride*h*sizeof( int16_t)*4);
uint16_t (*dist)[4] = av_malloc(stride*h*sizeof(uint16_t)*4); uint16_t (*dist)[4] = av_malloc(stride*h*sizeof(uint16_t)*4);
@ -222,14 +234,13 @@ static void guess_dc(MpegEncContext *s, int16_t *dc, int w, int h, int stride, i
for (b_x = 0; b_x < w; b_x++) { for (b_x = 0; b_x < w; b_x++) {
int mb_index, error, j; int mb_index, error, j;
int64_t guess, weight_sum; int64_t guess, weight_sum;
mb_index = (b_x >> is_luma) + (b_y >> is_luma) * s->mb_stride; mb_index = (b_x >> is_luma) + (b_y >> is_luma) * s->mb_stride;
error = s->error_status_table[mb_index]; error = s->error_status_table[mb_index];
if(IS_INTER(s->current_picture.f.mb_type[mb_index])) continue; //inter if (IS_INTER(s->current_picture.f.mb_type[mb_index]))
if(!(error&ER_DC_ERROR)) continue; //dc-ok continue; // inter
if (!(error & ER_DC_ERROR))
continue; // dc-ok
weight_sum = 0; weight_sum = 0;
guess = 0; guess = 0;
@ -239,7 +250,6 @@ static void guess_dc(MpegEncContext *s, int16_t *dc, int w, int h, int stride, i
weight_sum += weight; weight_sum += weight;
} }
guess = (guess + weight_sum / 2) / weight_sum; guess = (guess + weight_sum / 2) / weight_sum;
dc[b_x + b_y * stride] = guess; dc[b_x + b_y * stride] = guess;
} }
} }
@ -252,7 +262,9 @@ static void guess_dc(MpegEncContext *s, int16_t *dc, int w, int h, int stride, i
* @param w width in 8 pixel blocks * @param w width in 8 pixel blocks
* @param h height in 8 pixel blocks * @param h height in 8 pixel blocks
*/ */
static void h_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int stride, int is_luma){ static void h_block_filter(MpegEncContext *s, uint8_t *dst, int w,
int h, int stride, int is_luma)
{
int b_x, b_y, mvx_stride, mvy_stride; int b_x, b_y, mvx_stride, mvy_stride;
uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
set_mv_strides(s, &mvx_stride, &mvy_stride); set_mv_strides(s, &mvx_stride, &mvy_stride);
@ -271,11 +283,12 @@ static void h_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int st
int offset = b_x * 8 + b_y * stride * 8; int offset = b_x * 8 + b_y * stride * 8;
int16_t *left_mv = s->current_picture.f.motion_val[0][mvy_stride * b_y + mvx_stride * b_x]; int16_t *left_mv = s->current_picture.f.motion_val[0][mvy_stride * b_y + mvx_stride * b_x];
int16_t *right_mv = s->current_picture.f.motion_val[0][mvy_stride * b_y + mvx_stride * (b_x + 1)]; int16_t *right_mv = s->current_picture.f.motion_val[0][mvy_stride * b_y + mvx_stride * (b_x + 1)];
if (!(left_damage || right_damage))
if(!(left_damage||right_damage)) continue; // both undamaged continue; // both undamaged
if ((!left_intra) && (!right_intra) &&
if( (!left_intra) && (!right_intra) FFABS(left_mv[0] - right_mv[0]) +
&& FFABS(left_mv[0]-right_mv[0]) + FFABS(left_mv[1]+right_mv[1]) < 2) continue; FFABS(left_mv[1] + right_mv[1]) < 2)
continue;
for (y = 0; y < 8; y++) { for (y = 0; y < 8; y++) {
int a, b, c, d; int a, b, c, d;
@ -286,9 +299,11 @@ static void h_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int st
d = FFABS(b) - ((FFABS(a) + FFABS(c) + 1) >> 1); d = FFABS(b) - ((FFABS(a) + FFABS(c) + 1) >> 1);
d = FFMAX(d, 0); d = FFMAX(d, 0);
if(b<0) d= -d; if (b < 0)
d = -d;
if(d==0) continue; if (d == 0)
continue;
if (!(left_damage && right_damage)) if (!(left_damage && right_damage))
d = d * 16 / 9; d = d * 16 / 9;
@ -315,7 +330,9 @@ static void h_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int st
* @param w width in 8 pixel blocks * @param w width in 8 pixel blocks
* @param h height in 8 pixel blocks * @param h height in 8 pixel blocks
*/ */
static void v_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int stride, int is_luma){ static void v_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h,
int stride, int is_luma)
{
int b_x, b_y, mvx_stride, mvy_stride; int b_x, b_y, mvx_stride, mvy_stride;
uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
set_mv_strides(s, &mvx_stride, &mvy_stride); set_mv_strides(s, &mvx_stride, &mvy_stride);
@ -332,13 +349,17 @@ static void v_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int st
int top_damage = top_status & ER_MB_ERROR; int top_damage = top_status & ER_MB_ERROR;
int bottom_damage = bottom_status & ER_MB_ERROR; int bottom_damage = bottom_status & ER_MB_ERROR;
int offset = b_x * 8 + b_y * stride * 8; int offset = b_x * 8 + b_y * stride * 8;
int16_t *top_mv = s->current_picture.f.motion_val[0][mvy_stride * b_y + mvx_stride * b_x]; int16_t *top_mv = s->current_picture.f.motion_val[0][mvy_stride * b_y + mvx_stride * b_x];
int16_t *bottom_mv = s->current_picture.f.motion_val[0][mvy_stride * (b_y + 1) + mvx_stride * b_x]; int16_t *bottom_mv = s->current_picture.f.motion_val[0][mvy_stride * (b_y + 1) + mvx_stride * b_x];
if(!(top_damage||bottom_damage)) continue; // both undamaged if (!(top_damage || bottom_damage))
continue; // both undamaged
if( (!top_intra) && (!bottom_intra) if ((!top_intra) && (!bottom_intra) &&
&& FFABS(top_mv[0]-bottom_mv[0]) + FFABS(top_mv[1]+bottom_mv[1]) < 2) continue; FFABS(top_mv[0] - bottom_mv[0]) +
FFABS(top_mv[1] + bottom_mv[1]) < 2)
continue;
for (x = 0; x < 8; x++) { for (x = 0; x < 8; x++) {
int a, b, c, d; int a, b, c, d;
@ -349,9 +370,11 @@ static void v_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int st
d = FFABS(b) - ((FFABS(a) + FFABS(c) + 1) >> 1); d = FFABS(b) - ((FFABS(a) + FFABS(c) + 1) >> 1);
d = FFMAX(d, 0); d = FFMAX(d, 0);
if(b<0) d= -d; if (b < 0)
d = -d;
if(d==0) continue; if (d == 0)
continue;
if (!(top_damage && bottom_damage)) if (!(top_damage && bottom_damage))
d = d * 16 / 9; d = d * 16 / 9;
@ -373,7 +396,8 @@ static void v_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int st
} }
} }
static void guess_mv(MpegEncContext *s){ static void guess_mv(MpegEncContext *s)
{
uint8_t *fixed = av_malloc(s->mb_stride * s->mb_height); uint8_t *fixed = av_malloc(s->mb_stride * s->mb_height);
#define MV_FROZEN 3 #define MV_FROZEN 3
#define MV_CHANGED 2 #define MV_CHANGED 2
@ -392,8 +416,10 @@ static void guess_mv(MpegEncContext *s){
int f = 0; int f = 0;
int error = s->error_status_table[mb_xy]; int error = s->error_status_table[mb_xy];
if(IS_INTRA(s->current_picture.f.mb_type[mb_xy])) f=MV_FROZEN; //intra //FIXME check if (IS_INTRA(s->current_picture.f.mb_type[mb_xy]))
if(!(error&ER_MV_ERROR)) f=MV_FROZEN; //inter with undamaged MV f = MV_FROZEN; // intra // FIXME check
if (!(error & ER_MV_ERROR))
f = MV_FROZEN; // inter with undamaged MV
fixed[mb_xy] = f; fixed[mb_xy] = f;
if (f == MV_FROZEN) if (f == MV_FROZEN)
@ -408,15 +434,19 @@ static void guess_mv(MpegEncContext *s){
} }
} }
if((!(s->avctx->error_concealment&FF_EC_GUESS_MVS)) || num_avail <= mb_width/2){ if ((!(s->avctx->error_concealment&FF_EC_GUESS_MVS)) ||
num_avail <= mb_width / 2) {
for (mb_y = 0; mb_y < s->mb_height; mb_y++) { for (mb_y = 0; mb_y < s->mb_height; mb_y++) {
for (mb_x = 0; mb_x < s->mb_width; mb_x++) { for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
const int mb_xy = mb_x + mb_y * s->mb_stride; const int mb_xy = mb_x + mb_y * s->mb_stride;
if(IS_INTRA(s->current_picture.f.mb_type[mb_xy])) continue; if (IS_INTRA(s->current_picture.f.mb_type[mb_xy]))
if(!(s->error_status_table[mb_xy]&ER_MV_ERROR)) continue; continue;
if (!(s->error_status_table[mb_xy] & ER_MV_ERROR))
continue;
s->mv_dir = s->last_picture.f.data[0] ? MV_DIR_FORWARD : MV_DIR_BACKWARD; s->mv_dir = s->last_picture.f.data[0] ? MV_DIR_FORWARD
: MV_DIR_BACKWARD;
s->mb_intra = 0; s->mb_intra = 0;
s->mv_type = MV_TYPE_16X16; s->mv_type = MV_TYPE_16X16;
s->mb_skipped = 0; s->mb_skipped = 0;
@ -455,53 +485,78 @@ int score_sum=0;
const int mot_index = (mb_x + mb_y * mot_stride) * mot_step; const int mot_index = (mb_x + mb_y * mot_stride) * mot_step;
int prev_x, prev_y, prev_ref; int prev_x, prev_y, prev_ref;
if((mb_x^mb_y^pass)&1) continue; if ((mb_x ^ mb_y ^ pass) & 1)
continue;
if(fixed[mb_xy]==MV_FROZEN) continue; if (fixed[mb_xy] == MV_FROZEN)
continue;
assert(!IS_INTRA(s->current_picture.f.mb_type[mb_xy])); assert(!IS_INTRA(s->current_picture.f.mb_type[mb_xy]));
assert(s->last_picture_ptr && s->last_picture_ptr->f.data[0]); assert(s->last_picture_ptr && s->last_picture_ptr->f.data[0]);
j = 0; j = 0;
if(mb_x>0 && fixed[mb_xy-1 ]==MV_FROZEN) j=1; if (mb_x > 0 && fixed[mb_xy - 1] == MV_FROZEN)
if(mb_x+1<mb_width && fixed[mb_xy+1 ]==MV_FROZEN) j=1; j = 1;
if(mb_y>0 && fixed[mb_xy-mb_stride]==MV_FROZEN) j=1; if (mb_x + 1 < mb_width && fixed[mb_xy + 1] == MV_FROZEN)
if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]==MV_FROZEN) j=1; j = 1;
if(j==0) continue; if (mb_y > 0 && fixed[mb_xy - mb_stride] == MV_FROZEN)
j = 1;
if (mb_y + 1 < mb_height && fixed[mb_xy + mb_stride] == MV_FROZEN)
j = 1;
if (j == 0)
continue;
j = 0; j = 0;
if(mb_x>0 && fixed[mb_xy-1 ]==MV_CHANGED) j=1; if (mb_x > 0 && fixed[mb_xy - 1 ] == MV_CHANGED)
if(mb_x+1<mb_width && fixed[mb_xy+1 ]==MV_CHANGED) j=1; j = 1;
if(mb_y>0 && fixed[mb_xy-mb_stride]==MV_CHANGED) j=1; if (mb_x + 1 < mb_width && fixed[mb_xy + 1 ] == MV_CHANGED)
if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]==MV_CHANGED) j=1; j = 1;
if(j==0 && pass>1) continue; if (mb_y > 0 && fixed[mb_xy - mb_stride] == MV_CHANGED)
j = 1;
if (mb_y + 1 < mb_height && fixed[mb_xy + mb_stride] == MV_CHANGED)
j = 1;
if (j == 0 && pass > 1)
continue;
none_left = 0; none_left = 0;
if (mb_x > 0 && fixed[mb_xy - 1]) { if (mb_x > 0 && fixed[mb_xy - 1]) {
mv_predictor[pred_count][0]= s->current_picture.f.motion_val[0][mot_index - mot_step][0]; mv_predictor[pred_count][0] =
mv_predictor[pred_count][1]= s->current_picture.f.motion_val[0][mot_index - mot_step][1]; s->current_picture.f.motion_val[0][mot_index - mot_step][0];
ref [pred_count] = s->current_picture.f.ref_index[0][4*(mb_xy-1)]; mv_predictor[pred_count][1] =
s->current_picture.f.motion_val[0][mot_index - mot_step][1];
ref[pred_count] =
s->current_picture.f.ref_index[0][4 * (mb_xy - 1)];
pred_count++; pred_count++;
} }
if (mb_x + 1 < mb_width && fixed[mb_xy + 1]) { if (mb_x + 1 < mb_width && fixed[mb_xy + 1]) {
mv_predictor[pred_count][0]= s->current_picture.f.motion_val[0][mot_index + mot_step][0]; mv_predictor[pred_count][0] =
mv_predictor[pred_count][1]= s->current_picture.f.motion_val[0][mot_index + mot_step][1]; s->current_picture.f.motion_val[0][mot_index + mot_step][0];
ref [pred_count] = s->current_picture.f.ref_index[0][4*(mb_xy+1)]; mv_predictor[pred_count][1] =
s->current_picture.f.motion_val[0][mot_index + mot_step][1];
ref[pred_count] =
s->current_picture.f.ref_index[0][4 * (mb_xy + 1)];
pred_count++; pred_count++;
} }
if (mb_y > 0 && fixed[mb_xy - mb_stride]) { if (mb_y > 0 && fixed[mb_xy - mb_stride]) {
mv_predictor[pred_count][0]= s->current_picture.f.motion_val[0][mot_index - mot_stride*mot_step][0]; mv_predictor[pred_count][0] =
mv_predictor[pred_count][1]= s->current_picture.f.motion_val[0][mot_index - mot_stride*mot_step][1]; s->current_picture.f.motion_val[0][mot_index - mot_stride * mot_step][0];
ref [pred_count] = s->current_picture.f.ref_index[0][4*(mb_xy-s->mb_stride)]; mv_predictor[pred_count][1] =
s->current_picture.f.motion_val[0][mot_index - mot_stride * mot_step][1];
ref[pred_count] =
s->current_picture.f.ref_index[0][4 * (mb_xy - s->mb_stride)];
pred_count++; pred_count++;
} }
if (mb_y + 1<mb_height && fixed[mb_xy + mb_stride]) { if (mb_y + 1<mb_height && fixed[mb_xy + mb_stride]) {
mv_predictor[pred_count][0]= s->current_picture.f.motion_val[0][mot_index + mot_stride*mot_step][0]; mv_predictor[pred_count][0] =
mv_predictor[pred_count][1]= s->current_picture.f.motion_val[0][mot_index + mot_stride*mot_step][1]; s->current_picture.f.motion_val[0][mot_index + mot_stride * mot_step][0];
ref [pred_count] = s->current_picture.f.ref_index[0][4*(mb_xy+s->mb_stride)]; mv_predictor[pred_count][1] =
s->current_picture.f.motion_val[0][mot_index + mot_stride * mot_step][1];
ref[pred_count] =
s->current_picture.f.ref_index[0][4 * (mb_xy + s->mb_stride)];
pred_count++; pred_count++;
} }
if(pred_count==0) continue; if (pred_count == 0)
continue;
if (pred_count > 1) { if (pred_count > 1) {
int sum_x = 0, sum_y = 0, sum_r = 0; int sum_x = 0, sum_y = 0, sum_r = 0;
@ -546,8 +601,8 @@ int score_sum=0;
} }
pred_count += 2; pred_count += 2;
} }
skip_mean_and_median:
skip_mean_and_median:
/* zero MV */ /* zero MV */
pred_count++; pred_count++;
@ -575,8 +630,8 @@ skip_mean_and_median:
mv_predictor[pred_count][1] = prev_y; mv_predictor[pred_count][1] = prev_y;
ref[pred_count] = prev_ref; ref[pred_count] = prev_ref;
pred_count++; pred_count++;
skip_last_mv:
skip_last_mv:
s->mv_dir = MV_DIR_FORWARD; s->mv_dir = MV_DIR_FORWARD;
s->mb_intra = 0; s->mb_intra = 0;
s->mv_type = MV_TYPE_16X16; s->mv_type = MV_TYPE_16X16;
@ -589,12 +644,16 @@ skip_mean_and_median:
for (j = 0; j < pred_count; j++) { for (j = 0; j < pred_count; j++) {
int score = 0; int score = 0;
uint8_t *src = s->current_picture.f.data[0] + mb_x*16 + mb_y*16*s->linesize; uint8_t *src = s->current_picture.f.data[0] +
mb_x * 16 + mb_y * 16 * s->linesize;
s->current_picture.f.motion_val[0][mot_index][0] = s->mv[0][0][0] = mv_predictor[j][0]; s->current_picture.f.motion_val[0][mot_index][0] =
s->current_picture.f.motion_val[0][mot_index][1] = s->mv[0][0][1] = mv_predictor[j][1]; s->mv[0][0][0] = mv_predictor[j][0];
s->current_picture.f.motion_val[0][mot_index][1] =
s->mv[0][0][1] = mv_predictor[j][1];
if(ref[j]<0) //predictor intra or otherwise not available // predictor intra or otherwise not available
if (ref[j] < 0)
continue; continue;
decode_mb(s, ref[j]); decode_mb(s, ref[j]);
@ -602,12 +661,14 @@ skip_mean_and_median:
if (mb_x > 0 && fixed[mb_xy - 1]) { if (mb_x > 0 && fixed[mb_xy - 1]) {
int k; int k;
for (k = 0; k < 16; k++) for (k = 0; k < 16; k++)
score += FFABS(src[k*s->linesize-1 ]-src[k*s->linesize ]); score += FFABS(src[k * s->linesize - 1] -
src[k * s->linesize]);
} }
if (mb_x + 1 < mb_width && fixed[mb_xy + 1]) { if (mb_x + 1 < mb_width && fixed[mb_xy + 1]) {
int k; int k;
for (k = 0; k < 16; k++) for (k = 0; k < 16; k++)
score += FFABS(src[k*s->linesize+15]-src[k*s->linesize+16]); score += FFABS(src[k * s->linesize + 15] -
src[k * s->linesize + 16]);
} }
if (mb_y > 0 && fixed[mb_xy - mb_stride]) { if (mb_y > 0 && fixed[mb_xy - mb_stride]) {
int k; int k;
@ -617,7 +678,8 @@ skip_mean_and_median:
if (mb_y + 1 < mb_height && fixed[mb_xy + mb_stride]) { if (mb_y + 1 < mb_height && fixed[mb_xy + mb_stride]) {
int k; int k;
for (k = 0; k < 16; k++) for (k = 0; k < 16; k++)
score += FFABS(src[k+s->linesize*15]-src[k+s->linesize*16]); score += FFABS(src[k + s->linesize * 15] -
src[k + s->linesize * 16]);
} }
if (score <= best_score) { // <= will favor the last MV if (score <= best_score) { // <= will favor the last MV
@ -663,10 +725,12 @@ end:
av_free(fixed); av_free(fixed);
} }
static int is_intra_more_likely(MpegEncContext *s){ static int is_intra_more_likely(MpegEncContext *s)
{
int is_intra_likely, i, j, undamaged_count, skip_amount, mb_x, mb_y; int is_intra_likely, i, j, undamaged_count, skip_amount, mb_x, mb_y;
if (!s->last_picture_ptr || !s->last_picture_ptr->f.data[0]) return 1; //no previous frame available -> use spatial prediction if (!s->last_picture_ptr || !s->last_picture_ptr->f.data[0])
return 1; // no previous frame available -> use spatial prediction
undamaged_count = 0; undamaged_count = 0;
for (i = 0; i < s->mb_num; i++) { for (i = 0; i < s->mb_num; i++) {
@ -678,14 +742,18 @@ static int is_intra_more_likely(MpegEncContext *s){
if (s->codec_id == CODEC_ID_H264) { if (s->codec_id == CODEC_ID_H264) {
H264Context *h = (void*) s; H264Context *h = (void*) s;
if (h->list_count <= 0 || h->ref_count[0] <= 0 || !h->ref_list[0][0].f.data[0]) if (h->list_count <= 0 || h->ref_count[0] <= 0 ||
!h->ref_list[0][0].f.data[0])
return 1; return 1;
} }
if(undamaged_count < 5) return 0; //almost all MBs damaged -> use temporal prediction if (undamaged_count < 5)
return 0; // almost all MBs damaged -> use temporal prediction
// prevent dsp.sad() check, that requires access to the image // prevent dsp.sad() check, that requires access to the image
if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration && s->pict_type == AV_PICTURE_TYPE_I) if (CONFIG_MPEG_XVMC_DECODER &&
s->avctx->xvmc_acceleration &&
s->pict_type == AV_PICTURE_TYPE_I)
return 1; return 1;
skip_amount = FFMAX(undamaged_count / 50, 1); // check only up to 50 MBs skip_amount = FFMAX(undamaged_count / 50, 1); // check only up to 50 MBs
@ -702,11 +770,15 @@ static int is_intra_more_likely(MpegEncContext *s){
continue; // skip damaged continue; // skip damaged
j++; j++;
if((j%skip_amount) != 0) continue; //skip a few to speed things up // skip a few to speed things up
if ((j % skip_amount) != 0)
continue;
if (s->pict_type == AV_PICTURE_TYPE_I) { if (s->pict_type == AV_PICTURE_TYPE_I) {
uint8_t *mb_ptr = s->current_picture.f.data[0] + mb_x*16 + mb_y*16*s->linesize; uint8_t *mb_ptr = s->current_picture.f.data[0] +
uint8_t *last_mb_ptr= s->last_picture.f.data [0] + mb_x*16 + mb_y*16*s->linesize; mb_x * 16 + mb_y * 16 * s->linesize;
uint8_t *last_mb_ptr = s->last_picture.f.data[0] +
mb_x * 16 + mb_y * 16 * s->linesize;
if (s->avctx->codec_id == CODEC_ID_H264) { if (s->avctx->codec_id == CODEC_ID_H264) {
// FIXME // FIXME
@ -729,21 +801,27 @@ static int is_intra_more_likely(MpegEncContext *s){
return is_intra_likely > 0; return is_intra_likely > 0;
} }
void ff_er_frame_start(MpegEncContext *s){ void ff_er_frame_start(MpegEncContext *s)
if(!s->err_recognition) return; {
if (!s->err_recognition)
return;
memset(s->error_status_table, ER_MB_ERROR|VP_START|ER_MB_END, s->mb_stride*s->mb_height*sizeof(uint8_t)); memset(s->error_status_table, ER_MB_ERROR | VP_START | ER_MB_END,
s->mb_stride * s->mb_height * sizeof(uint8_t));
s->error_count = 3 * s->mb_num; s->error_count = 3 * s->mb_num;
s->error_occurred = 0; s->error_occurred = 0;
} }
/** /**
* Add a slice. * Add a slice.
* @param endx x component of the last macroblock, can be -1 for the last of the previous line * @param endx x component of the last macroblock, can be -1
* @param status the status at the end (ER_MV_END, ER_AC_ERROR, ...), it is assumed that no earlier end or * for the last of the previous line
* error of the same type occurred * @param status the status at the end (ER_MV_END, ER_AC_ERROR, ...), it is
* assumed that no earlier end or error of the same type occurred
*/ */
void ff_er_add_slice(MpegEncContext *s, int startx, int starty, int endx, int endy, int status){ void ff_er_add_slice(MpegEncContext *s, int startx, int starty,
int endx, int endy, int status)
{
const int start_i = av_clip(startx + starty * s->mb_width, 0, s->mb_num - 1); const int start_i = av_clip(startx + starty * s->mb_width, 0, s->mb_num - 1);
const int end_i = av_clip(endx + endy * s->mb_width, 0, s->mb_num); const int end_i = av_clip(endx + endy * s->mb_width, 0, s->mb_num);
const int start_xy = s->mb_index2xy[start_i]; const int start_xy = s->mb_index2xy[start_i];
@ -754,11 +832,13 @@ void ff_er_add_slice(MpegEncContext *s, int startx, int starty, int endx, int en
return; return;
if (start_i > end_i || start_xy > end_xy) { if (start_i > end_i || start_xy > end_xy) {
av_log(s->avctx, AV_LOG_ERROR, "internal error, slice end before start\n"); av_log(s->avctx, AV_LOG_ERROR,
"internal error, slice end before start\n");
return; return;
} }
if(!s->err_recognition) return; if (!s->err_recognition)
return;
mask &= ~VP_START; mask &= ~VP_START;
if (status & (ER_AC_ERROR | ER_AC_END)) { if (status & (ER_AC_ERROR | ER_AC_END)) {
@ -780,13 +860,13 @@ void ff_er_add_slice(MpegEncContext *s, int startx, int starty, int endx, int en
} }
if (mask == ~0x7F) { if (mask == ~0x7F) {
memset(&s->error_status_table[start_xy], 0, (end_xy - start_xy) * sizeof(uint8_t)); memset(&s->error_status_table[start_xy], 0,
(end_xy - start_xy) * sizeof(uint8_t));
} else { } else {
int i; int i;
for(i=start_xy; i<end_xy; i++){ for (i = start_xy; i < end_xy; i++)
s->error_status_table[i] &= mask; s->error_status_table[i] &= mask;
} }
}
if (end_i == s->mb_num) if (end_i == s->mb_num)
s->error_count = INT_MAX; s->error_count = INT_MAX;
@ -797,15 +877,18 @@ void ff_er_add_slice(MpegEncContext *s, int startx, int starty, int endx, int en
s->error_status_table[start_xy] |= VP_START; s->error_status_table[start_xy] |= VP_START;
if(start_xy > 0 && s->avctx->thread_count <= 1 && s->avctx->skip_top*s->mb_width < start_i){ if (start_xy > 0 && s->avctx->thread_count <= 1 &&
s->avctx->skip_top * s->mb_width < start_i) {
int prev_status = s->error_status_table[s->mb_index2xy[start_i - 1]]; int prev_status = s->error_status_table[s->mb_index2xy[start_i - 1]];
prev_status &= ~ VP_START; prev_status &= ~ VP_START;
if(prev_status != (ER_MV_END|ER_DC_END|ER_AC_END)) s->error_count= INT_MAX; if (prev_status != (ER_MV_END | ER_DC_END | ER_AC_END))
s->error_count = INT_MAX;
} }
} }
void ff_er_frame_end(MpegEncContext *s){ void ff_er_frame_end(MpegEncContext *s)
{
int i, mb_x, mb_y, error, error_type, dc_error, mv_error, ac_error; int i, mb_x, mb_y, error, error_type, dc_error, mv_error, ac_error;
int distance; int distance;
int threshold_part[4] = { 100, 100, 100 }; int threshold_part[4] = { 100, 100, 100 };
@ -814,11 +897,16 @@ void ff_er_frame_end(MpegEncContext *s){
int size = s->b8_stride * 2 * s->mb_height; int size = s->b8_stride * 2 * s->mb_height;
Picture *pic = s->current_picture_ptr; Picture *pic = s->current_picture_ptr;
/* We do not support ER of field pictures yet,
* though it should not crash if enabled. */
if (!s->err_recognition || s->error_count == 0 || s->avctx->lowres || if (!s->err_recognition || s->error_count == 0 || s->avctx->lowres ||
s->avctx->hwaccel || s->avctx->hwaccel ||
s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU || s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU ||
s->picture_structure != PICT_FRAME || // we do not support ER of field pictures yet, though it should not crash if enabled s->picture_structure != PICT_FRAME ||
s->error_count==3*s->mb_width*(s->avctx->skip_top + s->avctx->skip_bottom)) return; s->error_count == 3 * s->mb_width *
(s->avctx->skip_top + s->avctx->skip_bottom)) {
return;
};
if (s->current_picture.f.motion_val[0] == NULL) { if (s->current_picture.f.motion_val[0] == NULL) {
av_log(s->avctx, AV_LOG_ERROR, "Warning MVs not available\n"); av_log(s->avctx, AV_LOG_ERROR, "Warning MVs not available\n");
@ -876,7 +964,9 @@ void ff_er_frame_end(MpegEncContext *s){
if (error & ER_AC_END) if (error & ER_AC_END)
end_ok = 0; end_ok = 0;
if((error&ER_MV_END) || (error&ER_DC_END) || (error&ER_AC_ERROR)) if ((error & ER_MV_END) ||
(error & ER_DC_END) ||
(error & ER_AC_ERROR))
end_ok = 1; end_ok = 1;
if (!end_ok) if (!end_ok)
@ -891,7 +981,8 @@ void ff_er_frame_end(MpegEncContext *s){
if (s->err_recognition & AV_EF_EXPLODE) { if (s->err_recognition & AV_EF_EXPLODE) {
int end_ok = 1; int end_ok = 1;
for(i=s->mb_num-2; i>=s->mb_width+100; i--){ //FIXME +100 hack // FIXME + 100 hack
for (i = s->mb_num - 2; i >= s->mb_width + 100; i--) {
const int mb_xy = s->mb_index2xy[i]; const int mb_xy = s->mb_index2xy[i];
int error1 = s->error_status_table[mb_xy]; int error1 = s->error_status_table[mb_xy];
int error2 = s->error_status_table[s->mb_index2xy[i + 1]]; int error2 = s->error_status_table[s->mb_index2xy[i + 1]];
@ -899,9 +990,11 @@ void ff_er_frame_end(MpegEncContext *s){
if (error1 & VP_START) if (error1 & VP_START)
end_ok = 1; end_ok = 1;
if( error2==(VP_START|ER_MB_ERROR|ER_MB_END) if (error2 == (VP_START | ER_MB_ERROR | ER_MB_END) &&
&& error1!=(VP_START|ER_MB_ERROR|ER_MB_END) error1 != (VP_START | ER_MB_ERROR | ER_MB_END) &&
&& ((error1&ER_AC_END) || (error1&ER_DC_END) || (error1&ER_MV_END))){ //end & uninit ((error1 & ER_AC_END) || (error1 & ER_DC_END) ||
(error1 & ER_MV_END))) {
// end & uninit
end_ok = 0; end_ok = 0;
} }
@ -943,9 +1036,9 @@ void ff_er_frame_end(MpegEncContext *s){
const int mb_xy = s->mb_index2xy[i]; const int mb_xy = s->mb_index2xy[i];
int old_error = s->error_status_table[mb_xy]; int old_error = s->error_status_table[mb_xy];
if(old_error&VP_START) if (old_error & VP_START) {
error = old_error & ER_MB_ERROR; error = old_error & ER_MB_ERROR;
else{ } else {
error |= old_error & ER_MB_ERROR; error |= old_error & ER_MB_ERROR;
s->error_status_table[mb_xy] |= error; s->error_status_table[mb_xy] |= error;
} }
@ -967,11 +1060,15 @@ void ff_er_frame_end(MpegEncContext *s){
for (i = 0; i < s->mb_num; i++) { for (i = 0; i < s->mb_num; i++) {
const int mb_xy = s->mb_index2xy[i]; const int mb_xy = s->mb_index2xy[i];
error = s->error_status_table[mb_xy]; error = s->error_status_table[mb_xy];
if(error&ER_DC_ERROR) dc_error ++; if (error & ER_DC_ERROR)
if(error&ER_AC_ERROR) ac_error ++; dc_error++;
if(error&ER_MV_ERROR) mv_error ++; if (error & ER_AC_ERROR)
ac_error++;
if (error & ER_MV_ERROR)
mv_error++;
} }
av_log(s->avctx, AV_LOG_INFO, "concealing %d DC, %d AC, %d MV errors\n", dc_error, ac_error, mv_error); av_log(s->avctx, AV_LOG_INFO, "concealing %d DC, %d AC, %d MV errors\n",
dc_error, ac_error, mv_error);
is_intra_likely = is_intra_more_likely(s); is_intra_likely = is_intra_more_likely(s);
@ -1002,11 +1099,15 @@ void ff_er_frame_end(MpegEncContext *s){
const int mb_xy = mb_x + mb_y * s->mb_stride; const int mb_xy = mb_x + mb_y * s->mb_stride;
const int mb_type = s->current_picture.f.mb_type[mb_xy]; const int mb_type = s->current_picture.f.mb_type[mb_xy];
int dir = !s->last_picture.f.data[0]; int dir = !s->last_picture.f.data[0];
error = s->error_status_table[mb_xy]; error = s->error_status_table[mb_xy];
if(IS_INTRA(mb_type)) continue; //intra if (IS_INTRA(mb_type))
if(error&ER_MV_ERROR) continue; //inter with damaged MV continue; // intra
if(!(error&ER_AC_ERROR)) continue; //undamaged inter if (error & ER_MV_ERROR)
continue; // inter with damaged MV
if (!(error & ER_AC_ERROR))
continue; // undamaged inter
s->mv_dir = dir ? MV_DIR_BACKWARD : MV_DIR_FORWARD; s->mv_dir = dir ? MV_DIR_BACKWARD : MV_DIR_FORWARD;
s->mb_intra = 0; s->mb_intra = 0;
@ -1040,15 +1141,21 @@ void ff_er_frame_end(MpegEncContext *s){
int xy = mb_x * 2 + mb_y * 2 * s->b8_stride; int xy = mb_x * 2 + mb_y * 2 * s->b8_stride;
const int mb_xy = mb_x + mb_y * s->mb_stride; const int mb_xy = mb_x + mb_y * s->mb_stride;
const int mb_type = s->current_picture.f.mb_type[mb_xy]; const int mb_type = s->current_picture.f.mb_type[mb_xy];
error = s->error_status_table[mb_xy]; error = s->error_status_table[mb_xy];
if(IS_INTRA(mb_type)) continue; if (IS_INTRA(mb_type))
if(!(error&ER_MV_ERROR)) continue; //inter with undamaged MV continue;
if(!(error&ER_AC_ERROR)) continue; //undamaged inter if (!(error & ER_MV_ERROR))
continue; // inter with undamaged MV
if (!(error & ER_AC_ERROR))
continue; // undamaged inter
s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD; s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD;
if(!s->last_picture.f.data[0]) s->mv_dir &= ~MV_DIR_FORWARD; if (!s->last_picture.f.data[0])
if(!s->next_picture.f.data[0]) s->mv_dir &= ~MV_DIR_BACKWARD; s->mv_dir &= ~MV_DIR_FORWARD;
if (!s->next_picture.f.data[0])
s->mv_dir &= ~MV_DIR_BACKWARD;
s->mb_intra = 0; s->mb_intra = 0;
s->mv_type = MV_TYPE_16X16; s->mv_type = MV_TYPE_16X16;
s->mb_skipped = 0; s->mb_skipped = 0;
@ -1060,8 +1167,7 @@ void ff_er_frame_end(MpegEncContext *s){
if (s->avctx->codec_id == CODEC_ID_H264) { if (s->avctx->codec_id == CODEC_ID_H264) {
// FIXME // FIXME
} else { } else {
ff_thread_await_progress((AVFrame *) s->next_picture_ptr, ff_thread_await_progress((AVFrame *) s->next_picture_ptr, mb_y, 0);
mb_y, 0);
} }
s->mv[0][0][0] = s->next_picture.f.motion_val[0][xy][0] * time_pb / time_pp; s->mv[0][0][0] = s->next_picture.f.motion_val[0][xy][0] * time_pb / time_pp;
s->mv[0][0][1] = s->next_picture.f.motion_val[0][xy][1] * time_pb / time_pp; s->mv[0][0][1] = s->next_picture.f.motion_val[0][xy][1] * time_pb / time_pp;
@ -1097,8 +1203,10 @@ void ff_er_frame_end(MpegEncContext *s){
error = s->error_status_table[mb_xy]; error = s->error_status_table[mb_xy];
if(IS_INTRA(mb_type) && s->partitioned_frame) continue; if (IS_INTRA(mb_type) && s->partitioned_frame)
// if(error&ER_MV_ERROR) continue; //inter data damaged FIXME is this good? continue;
// if (error & ER_MV_ERROR)
// continue; // inter data damaged FIXME is this good?
dest_y = s->current_picture.f.data[0] + mb_x * 16 + mb_y * 16 * s->linesize; dest_y = s->current_picture.f.data[0] + mb_x * 16 + mb_y * 16 * s->linesize;
dest_cb = s->current_picture.f.data[1] + mb_x * 8 + mb_y * 8 * s->uvlinesize; dest_cb = s->current_picture.f.data[1] + mb_x * 8 + mb_y * 8 * s->uvlinesize;
@ -1109,9 +1217,9 @@ void ff_er_frame_end(MpegEncContext *s){
dc = 0; dc = 0;
for (y = 0; y < 8; y++) { for (y = 0; y < 8; y++) {
int x; int x;
for(x=0; x<8; x++){ for (x = 0; x < 8; x++)
dc+= dest_y[x + (n&1)*8 + (y + (n>>1)*8)*s->linesize]; dc += dest_y[x + (n & 1) * 8 +
} (y + (n >> 1) * 8) * s->linesize];
} }
dc_ptr[(n & 1) + (n >> 1) * s->b8_stride] = (dc + 4) >> 3; dc_ptr[(n & 1) + (n >> 1) * s->b8_stride] = (dc + 4) >> 3;
} }
@ -1134,6 +1242,7 @@ void ff_er_frame_end(MpegEncContext *s){
guess_dc(s, s->dc_val[1], s->mb_width , s->mb_height , s->mb_stride, 0); guess_dc(s, s->dc_val[1], s->mb_width , s->mb_height , s->mb_stride, 0);
guess_dc(s, s->dc_val[2], s->mb_width , s->mb_height , s->mb_stride, 0); guess_dc(s, s->dc_val[2], s->mb_width , s->mb_height , s->mb_stride, 0);
#endif #endif
/* filter luma DC */ /* filter luma DC */
filter181(s->dc_val[0], s->mb_width * 2, s->mb_height * 2, s->b8_stride); filter181(s->dc_val[0], s->mb_width * 2, s->mb_height * 2, s->b8_stride);
@ -1147,8 +1256,10 @@ void ff_er_frame_end(MpegEncContext *s){
error = s->error_status_table[mb_xy]; error = s->error_status_table[mb_xy];
if(IS_INTER(mb_type)) continue; if (IS_INTER(mb_type))
if(!(error&ER_AC_ERROR)) continue; //undamaged continue;
if (!(error & ER_AC_ERROR))
continue; // undamaged
dest_y = s->current_picture.f.data[0] + mb_x * 16 + mb_y * 16 * s->linesize; dest_y = s->current_picture.f.data[0] + mb_x * 16 + mb_y * 16 * s->linesize;
dest_cb = s->current_picture.f.data[1] + mb_x * 8 + mb_y * 8 * s->uvlinesize; dest_cb = s->current_picture.f.data[1] + mb_x * 8 + mb_y * 8 * s->uvlinesize;
@ -1161,14 +1272,20 @@ void ff_er_frame_end(MpegEncContext *s){
if (s->avctx->error_concealment & FF_EC_DEBLOCK) { if (s->avctx->error_concealment & FF_EC_DEBLOCK) {
/* filter horizontal block boundaries */ /* filter horizontal block boundaries */
h_block_filter(s, s->current_picture.f.data[0], s->mb_width*2, s->mb_height*2, s->linesize , 1); h_block_filter(s, s->current_picture.f.data[0], s->mb_width * 2,
h_block_filter(s, s->current_picture.f.data[1], s->mb_width , s->mb_height , s->uvlinesize, 0); s->mb_height * 2, s->linesize, 1);
h_block_filter(s, s->current_picture.f.data[2], s->mb_width , s->mb_height , s->uvlinesize, 0); h_block_filter(s, s->current_picture.f.data[1], s->mb_width,
s->mb_height , s->uvlinesize, 0);
h_block_filter(s, s->current_picture.f.data[2], s->mb_width,
s->mb_height , s->uvlinesize, 0);
/* filter vertical block boundaries */ /* filter vertical block boundaries */
v_block_filter(s, s->current_picture.f.data[0], s->mb_width*2, s->mb_height*2, s->linesize , 1); v_block_filter(s, s->current_picture.f.data[0], s->mb_width * 2,
v_block_filter(s, s->current_picture.f.data[1], s->mb_width , s->mb_height , s->uvlinesize, 0); s->mb_height * 2, s->linesize, 1);
v_block_filter(s, s->current_picture.f.data[2], s->mb_width , s->mb_height , s->uvlinesize, 0); v_block_filter(s, s->current_picture.f.data[1], s->mb_width,
s->mb_height , s->uvlinesize, 0);
v_block_filter(s, s->current_picture.f.data[2], s->mb_width,
s->mb_height , s->uvlinesize, 0);
} }
ec_clean: ec_clean:
@ -1177,7 +1294,8 @@ ec_clean:
const int mb_xy = s->mb_index2xy[i]; const int mb_xy = s->mb_index2xy[i];
int error = s->error_status_table[mb_xy]; int error = s->error_status_table[mb_xy];
if(s->pict_type!=AV_PICTURE_TYPE_B && (error&(ER_DC_ERROR|ER_MV_ERROR|ER_AC_ERROR))){ if (s->pict_type != AV_PICTURE_TYPE_B &&
(error & (ER_DC_ERROR | ER_MV_ERROR | ER_AC_ERROR))) {
s->mbskip_table[mb_xy] = 0; s->mbskip_table[mb_xy] = 0;
} }
s->mbintra_table[mb_xy] = 1; s->mbintra_table[mb_xy] = 1;

@ -1819,9 +1819,18 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt);
* demuxer level. * demuxer level.
* *
* @param s media file handle * @param s media file handle
* @param pkt The packet, which contains the stream_index, buf/buf_size, * @param pkt The packet containing the data to be written. Libavformat takes
dts/pts, ... * ownership of the data and will free it when it sees fit using the packet's
* @return < 0 on error, = 0 if OK, 1 if end of stream wanted * @ref AVPacket.destruct "destruct" field. The caller must not access the data
* after this function returns, as it may already be freed.
* Packet's @ref AVPacket.stream_index "stream_index" field must be set to the
* index of the corresponding stream in @ref AVFormatContext.streams
* "s.streams".
* It is very strongly recommended that timing information (@ref AVPacket.pts
* "pts", @ref AVPacket.dts "dts" @ref AVPacket.duration "duration") is set to
* correct values.
*
* @return 0 on success, a negative AVERROR on error.
*/ */
int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt); int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt);

@ -602,12 +602,11 @@ static int mov_read_chan(MOVContext *c, AVIOContext *pb, MOVAtom atom)
label_mask = 0; label_mask = 0;
for (i = 0; i < num_descr; i++) { for (i = 0; i < num_descr; i++) {
uint32_t label, cflags; uint32_t label, cflags;
float coords[3];
label = avio_rb32(pb); // mChannelLabel label = avio_rb32(pb); // mChannelLabel
cflags = avio_rb32(pb); // mChannelFlags cflags = avio_rb32(pb); // mChannelFlags
AV_WN32(&coords[0], avio_rl32(pb)); // mCoordinates[0] avio_rl32(pb); // mCoordinates[0]
AV_WN32(&coords[1], avio_rl32(pb)); // mCoordinates[1] avio_rl32(pb); // mCoordinates[1]
AV_WN32(&coords[2], avio_rl32(pb)); // mCoordinates[2] avio_rl32(pb); // mCoordinates[2]
if (layout_tag == 0) { if (layout_tag == 0) {
uint32_t mask_incr = ff_mov_get_channel_label(label); uint32_t mask_incr = ff_mov_get_channel_label(label);
if (mask_incr == 0) { if (mask_incr == 0) {

@ -3492,9 +3492,12 @@ int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pk
* < 0 if an error occurred * < 0 if an error occurred
*/ */
static int interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *in, int flush){ static int interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *in, int flush){
if(s->oformat->interleave_packet) if (s->oformat->interleave_packet) {
return s->oformat->interleave_packet(s, out, in, flush); int ret = s->oformat->interleave_packet(s, out, in, flush);
else if (in)
av_free_packet(in);
return ret;
} else
return av_interleave_packet_per_dts(s, out, in, flush); return av_interleave_packet_per_dts(s, out, in, flush);
} }

@ -31,7 +31,8 @@ int main(void)
int out_len = 0; int out_len = 0;
int in; int in;
#define putb64() do { \ #define putb64() \
do { \
putchar(b64[(i_bits << 6 >> i_shift) & 0x3f]); \ putchar(b64[(i_bits << 6 >> i_shift) & 0x3f]); \
out_len++; \ out_len++; \
i_shift -= 6; \ i_shift -= 6; \

@ -226,7 +226,10 @@ static void gen_image(int num, int w, int h)
for (i = 0; i < w; i++) { for (i = 0; i < w; i++) {
x += c; x += c;
y -= s; y -= s;
put_pixel(i, j, ipol(tab_r, x, y), ipol(tab_g, x, y), ipol(tab_b, x, y)); put_pixel(i, j,
ipol(tab_r, x, y),
ipol(tab_g, x, y),
ipol(tab_b, x, y));
} }
} }
} }

@ -68,7 +68,8 @@ static unsigned int exp16(unsigned int a){
#endif #endif
// 16.16 fixpoint log() // 16.16 fixpoint log()
static int64_t log16(uint64_t a){ static int64_t log16(uint64_t a)
{
int i; int i;
int out = 0; int out = 0;
@ -78,7 +79,8 @@ static int64_t log16(uint64_t a){
for (i = 20; i >= 0; i--) { for (i = 20; i >= 0; i--) {
int64_t b = exp16_table[i]; int64_t b = exp16_table[i];
if(a<(b<<16)) continue; if (a < (b << 16))
continue;
out |= 1 << i; out |= 1 << i;
a = ((a / b) << 16) + (((a % b) << 16) + b / 2) / b; a = ((a / b) << 16) + (((a % b) << 16) + b / 2) / b;
} }
@ -88,8 +90,8 @@ static int64_t log16(uint64_t a){
static uint64_t int_sqrt(uint64_t a) static uint64_t int_sqrt(uint64_t a)
{ {
uint64_t ret = 0; uint64_t ret = 0;
int s;
uint64_t ret_sq = 0; uint64_t ret_sq = 0;
int s;
for (s = 31; s >= 0; s--) { for (s = 31; s >= 0; s--) {
uint64_t b = ret_sq + (1ULL << (s * 2)) + (ret << s) * 2; uint64_t b = ret_sq + (1ULL << (s * 2)) + (ret << s) * 2;
@ -101,7 +103,8 @@ static uint64_t int_sqrt(uint64_t a)
return ret; return ret;
} }
int main(int argc,char* argv[]){ int main(int argc, char *argv[])
{
int i, j; int i, j;
uint64_t sse = 0; uint64_t sse = 0;
uint64_t dev; uint64_t dev;
@ -167,7 +170,8 @@ int main(int argc,char* argv[]){
} }
sse += (a - b) * (a - b); sse += (a - b) * (a - b);
dist = abs(a - b); dist = abs(a - b);
if (dist > maxdist) maxdist = dist; if (dist > maxdist)
maxdist = dist;
} }
size0 += s0; size0 += s0;
size1 += s1; size1 += s1;
@ -176,19 +180,18 @@ int main(int argc,char* argv[]){
} }
i = FFMIN(size0, size1) / len; i = FFMIN(size0, size1) / len;
if(!i) i=1; if (!i)
i = 1;
dev = int_sqrt(((sse / i) * F * F) + (((sse % i) * F * F) + i / 2) / i); dev = int_sqrt(((sse / i) * F * F) + (((sse % i) * F * F) + i / 2) / i);
if (sse) if (sse)
psnr= ((2*log16(max<<16) + log16(i) - log16(sse))*284619LL*F + (1LL<<31)) / (1LL<<32); psnr = ((2 * log16(max << 16) + log16(i) - log16(sse)) *
284619LL * F + (1LL << 31)) / (1LL << 32);
else else
psnr = 1000 * F - 1; // floating point free infinity :) psnr = 1000 * F - 1; // floating point free infinity :)
printf("stddev:%5d.%02d PSNR:%3d.%02d MAXDIFF:%5d bytes:%9d/%9d\n", printf("stddev:%5d.%02d PSNR:%3d.%02d MAXDIFF:%5d bytes:%9d/%9d\n",
(int)(dev / F), (int)(dev % F), (int)(dev / F), (int)(dev % F),
(int)(psnr / F), (int)(psnr % F), (int)(psnr / F), (int)(psnr % F),
maxdist, maxdist, size0, size1);
size0, size1);
return 0; return 0;
} }

@ -77,10 +77,16 @@ static void rgb24_to_yuv420p(uint8_t *lum, uint8_t *cb, uint8_t *cr,
lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + cb[0] = 128 + ((- FIX(0.16874) * r1 -
FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128; FIX(0.33126) * g1 +
cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - FIX(0.50000) * b1 +
FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128; 4 * ONE_HALF - 1)
>> (SCALEBITS + 2));
cr[0] = 128 + ((FIX(0.50000) * r1 -
FIX(0.41869) * g1 -
FIX(0.08131) * b1 +
4 * ONE_HALF - 1)
>> (SCALEBITS + 2));
cb++; cb++;
cr++; cr++;

Loading…
Cancel
Save