Commit c130428a authored by Michael Niedermayer's avatar Michael Niedermayer

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: 's avatarMichael Niedermayer <michaelni@gmx.at>
parents 6fd4b8a6 0184bbe2
...@@ -105,7 +105,8 @@ int opt_timelimit(const char *opt, const char *arg); ...@@ -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 ...@@ -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 { ...@@ -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 ...@@ -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); ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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. ...@@ -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.
...@@ -109,13 +109,13 @@ static char *value_string(char *buf, int buf_size, struct unit_value uv) ...@@ -109,13 +109,13 @@ static char *value_string(char *buf, int buf_size, struct unit_value uv)
if (uv.unit == unit_byte_str && use_byte_value_binary_prefix) { if (uv.unit == unit_byte_str && use_byte_value_binary_prefix) {
index = (long long int) (log(vald)/log(2)) / 10; index = (long long int) (log(vald)/log(2)) / 10;
index = av_clip(index, 0, FF_ARRAY_ELEMS(binary_unit_prefixes) -1); index = av_clip(index, 0, FF_ARRAY_ELEMS(binary_unit_prefixes) - 1);
vald /= pow(2, index*10); vald /= pow(2, index * 10);
prefix_string = binary_unit_prefixes[index]; prefix_string = binary_unit_prefixes[index];
} else { } else {
index = (long long int) (log10(vald)) / 3; index = (long long int) (log10(vald)) / 3;
index = av_clip(index, 0, FF_ARRAY_ELEMS(decimal_unit_prefixes) -1); index = av_clip(index, 0, FF_ARRAY_ELEMS(decimal_unit_prefixes) - 1);
vald /= pow(10, index*3); vald /= pow(10, index * 3);
prefix_string = decimal_unit_prefixes[index]; prefix_string = decimal_unit_prefixes[index];
} }
...@@ -1557,7 +1557,8 @@ static int open_input_file(AVFormatContext **fmt_ctx_ptr, const char *filename) ...@@ -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,8 +1582,9 @@ static int open_input_file(AVFormatContext **fmt_ctx_ptr, const char *filename) ...@@ -1581,8 +1582,9 @@ 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,
stream->codec->codec_id, stream->index); "Unsupported codec with id %d for input stream %d\n",
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",
stream->index); stream->index);
...@@ -1700,8 +1702,9 @@ static int opt_format(const char *opt, const char *arg) ...@@ -1700,8 +1702,9 @@ 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,
arg, input_filename); "Argument '%s' provided as input filename, but '%s' was already specified.\n",
arg, input_filename);
exit(1); exit(1);
} }
if (!strcmp(arg, "-")) if (!strcmp(arg, "-"))
......
...@@ -40,30 +40,33 @@ ...@@ -40,30 +40,33 @@
*/ */
#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);
if(CONFIG_H264_DECODER && s->codec_id == CODEC_ID_H264){ if (CONFIG_H264_DECODER && s->codec_id == CODEC_ID_H264) {
H264Context *h= (void*)s; H264Context *h = (void*)s;
h->mb_xy= s->mb_x + s->mb_y*s->mb_stride; h->mb_xy = s->mb_x + s->mb_y * s->mb_stride;
memset(h->non_zero_count_cache, 0, sizeof(h->non_zero_count_cache)); memset(h->non_zero_count_cache, 0, sizeof(h->non_zero_count_cache));
assert(ref>=0); assert(ref >= 0);
/* FIXME: It is possible albeit uncommon that slice references /* FIXME: It is possible albeit uncommon that slice references
* differ between slices. We take the easy approach and ignore * differ between slices. We take the easy approach and ignore
* it for now. If this turns out to have any relevance in * it for now. If this turns out to have any relevance in
* 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 {
assert(ref==0); assert(ref == 0);
MPV_decode_mb(s, s->block); MPV_decode_mb(s, s->block);
} }
} }
...@@ -71,82 +74,89 @@ static void decode_mb(MpegEncContext *s, int ref){ ...@@ -71,82 +74,89 @@ 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){ {
H264Context *h= (void*)s; if (s->codec_id == CODEC_ID_H264) {
H264Context *h = (void*)s;
assert(s->quarter_sample); assert(s->quarter_sample);
*mv_step= 4; *mv_step = 4;
*stride= h->b_stride; *stride = h->b_stride;
}else{ } else {
*mv_step= 2; *mv_step = 2;
*stride= s->b8_stride; *stride = s->b8_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;
for(y=0; y<8; y++){ else if (dc > 2040)
dc = 2040;
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;
for(y=0; y<8; y++){ if (dcv < 0)
dcv = 0;
else if (dcv > 2040)
dcv = 2040;
for (y = 0; y < 8; y++) {
int x; int x;
for(x=0; x<8; x++){ for (x = 0; x < 8; x++) {
dest_cb[x + y * s->uvlinesize] = dcu / 8; dest_cb[x + y * s->uvlinesize] = dcu / 8;
dest_cr[x + y * s->uvlinesize] = dcv / 8; dest_cr[x + y * s->uvlinesize] = dcv / 8;
} }
} }
} }
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 */
for(y=1; y<height-1; y++){ for (y = 1; y < height - 1; y++) {
int prev_dc= data[0 + y*stride]; int prev_dc = data[0 + y * 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;
} }
} }
/* vertical filter */ /* vertical filter */
for(x=1; x<width-1; x++){ for (x = 1; x < width - 1; x++) {
int prev_dc= data[x]; int prev_dc = data[x];
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){ ...@@ -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);
...@@ -218,29 +230,27 @@ static void guess_dc(MpegEncContext *s, int16_t *dc, int w, int h, int stride, i ...@@ -218,29 +230,27 @@ static void guess_dc(MpegEncContext *s, int16_t *dc, int w, int h, int stride, i
} }
} }
for(b_y=0; b_y<h; b_y++){ for (b_y = 0; b_y < h; b_y++) {
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])) continue; //inter if (!(error & ER_DC_ERROR))
if(!(error&ER_DC_ERROR)) continue; //dc-ok continue; // dc-ok
weight_sum = 0;
weight_sum=0; guess = 0;
guess=0; for (j = 0; j < 4; j++) {
for(j=0; j<4; j++){ int64_t weight = 256 * 256 * 256 * 16 / dist[b_x + b_y*stride][j];
int64_t weight= 256*256*256*16/dist[b_x + b_y*stride][j]; guess += weight*(int64_t)col[b_x + b_y*stride][j];
guess+= weight*(int64_t)col[b_x + b_y*stride][j]; 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;
} }
} }
av_freep(&col); av_freep(&col);
...@@ -252,58 +262,63 @@ static void guess_dc(MpegEncContext *s, int16_t *dc, int w, int h, int stride, i ...@@ -252,58 +262,63 @@ 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);
mvx_stride >>= is_luma; mvx_stride >>= is_luma;
mvy_stride *= mvx_stride; mvy_stride *= mvx_stride;
for(b_y=0; b_y<h; b_y++){ for (b_y = 0; b_y < h; b_y++) {
for(b_x=0; b_x<w-1; b_x++){ for (b_x = 0; b_x < w - 1; b_x++) {
int y; int y;
int left_status = s->error_status_table[( b_x >>is_luma) + (b_y>>is_luma)*s->mb_stride]; int left_status = s->error_status_table[( b_x >> is_luma) + (b_y >> is_luma) * s->mb_stride];
int right_status= s->error_status_table[((b_x+1)>>is_luma) + (b_y>>is_luma)*s->mb_stride]; int right_status = s->error_status_table[((b_x + 1) >> is_luma) + (b_y >> is_luma) * s->mb_stride];
int left_intra = IS_INTRA(s->current_picture.f.mb_type[( b_x >> is_luma) + (b_y >> is_luma) * s->mb_stride]); int left_intra = IS_INTRA(s->current_picture.f.mb_type[( b_x >> is_luma) + (b_y >> is_luma) * s->mb_stride]);
int right_intra = IS_INTRA(s->current_picture.f.mb_type[((b_x + 1) >> is_luma) + (b_y >> is_luma) * s->mb_stride]); int right_intra = IS_INTRA(s->current_picture.f.mb_type[((b_x + 1) >> is_luma) + (b_y >> is_luma) * s->mb_stride]);
int left_damage = left_status&ER_MB_ERROR; int left_damage = left_status & ER_MB_ERROR;
int right_damage= right_status&ER_MB_ERROR; int right_damage = right_status & ER_MB_ERROR;
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++){
int a,b,c,d; for (y = 0; y < 8; y++) {
int a, b, c, d;
a= dst[offset + 7 + y*stride] - dst[offset + 6 + y*stride];
b= dst[offset + 8 + y*stride] - dst[offset + 7 + y*stride]; a = dst[offset + 7 + y * stride] - dst[offset + 6 + y * stride];
c= dst[offset + 9 + y*stride] - dst[offset + 8 + y*stride]; b = dst[offset + 8 + y * stride] - dst[offset + 7 + y * stride];
c = dst[offset + 9 + y * stride] - dst[offset + 8 + y * stride];
d= FFABS(b) - ((FFABS(a) + FFABS(c) + 1)>>1);
d= FFMAX(d, 0); d = FFABS(b) - ((FFABS(a) + FFABS(c) + 1) >> 1);
if(b<0) d= -d; d = FFMAX(d, 0);
if (b < 0)
if(d==0) continue; d = -d;
if(!(left_damage && right_damage)) if (d == 0)
d= d*16/9; continue;
if(left_damage){ if (!(left_damage && right_damage))
dst[offset + 7 + y*stride] = cm[dst[offset + 7 + y*stride] + ((d*7)>>4)]; d = d * 16 / 9;
dst[offset + 6 + y*stride] = cm[dst[offset + 6 + y*stride] + ((d*5)>>4)];
dst[offset + 5 + y*stride] = cm[dst[offset + 5 + y*stride] + ((d*3)>>4)]; if (left_damage) {
dst[offset + 4 + y*stride] = cm[dst[offset + 4 + y*stride] + ((d*1)>>4)]; dst[offset + 7 + y * stride] = cm[dst[offset + 7 + y * stride] + ((d * 7) >> 4)];
dst[offset + 6 + y * stride] = cm[dst[offset + 6 + y * stride] + ((d * 5) >> 4)];
dst[offset + 5 + y * stride] = cm[dst[offset + 5 + y * stride] + ((d * 3) >> 4)];
dst[offset + 4 + y * stride] = cm[dst[offset + 4 + y * stride] + ((d * 1) >> 4)];
} }
if(right_damage){ if (right_damage) {
dst[offset + 8 + y*stride] = cm[dst[offset + 8 + y*stride] - ((d*7)>>4)]; dst[offset + 8 + y * stride] = cm[dst[offset + 8 + y * stride] - ((d * 7) >> 4)];
dst[offset + 9 + y*stride] = cm[dst[offset + 9 + y*stride] - ((d*5)>>4)]; dst[offset + 9 + y * stride] = cm[dst[offset + 9 + y * stride] - ((d * 5) >> 4)];
dst[offset + 10+ y*stride] = cm[dst[offset +10 + y*stride] - ((d*3)>>4)]; dst[offset + 10+ y * stride] = cm[dst[offset + 10 + y * stride] - ((d * 3) >> 4)];
dst[offset + 11+ y*stride] = cm[dst[offset +11 + y*stride] - ((d*1)>>4)]; dst[offset + 11+ y * stride] = cm[dst[offset + 11 + y * stride] - ((d * 1) >> 4)];
} }
} }
} }
...@@ -315,88 +330,99 @@ static void h_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int st ...@@ -315,88 +330,99 @@ 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);
mvx_stride >>= is_luma; mvx_stride >>= is_luma;
mvy_stride *= mvx_stride; mvy_stride *= mvx_stride;
for(b_y=0; b_y<h-1; b_y++){ for (b_y = 0; b_y < h - 1; b_y++) {
for(b_x=0; b_x<w; b_x++){ for (b_x = 0; b_x < w; b_x++) {
int x; int x;
int top_status = s->error_status_table[(b_x>>is_luma) + ( b_y >>is_luma)*s->mb_stride]; int top_status = s->error_status_table[(b_x >> is_luma) + (b_y >> is_luma) * s->mb_stride];
int bottom_status= s->error_status_table[(b_x>>is_luma) + ((b_y+1)>>is_luma)*s->mb_stride]; int bottom_status = s->error_status_table[(b_x >> is_luma) + ((b_y + 1) >> is_luma) * s->mb_stride];
int top_intra = IS_INTRA(s->current_picture.f.mb_type[(b_x >> is_luma) + ( b_y >> is_luma) * s->mb_stride]); int top_intra = IS_INTRA(s->current_picture.f.mb_type[(b_x >> is_luma) + ( b_y >> is_luma) * s->mb_stride]);
int bottom_intra = IS_INTRA(s->current_picture.f.mb_type[(b_x >> is_luma) + ((b_y + 1) >> is_luma) * s->mb_stride]); int bottom_intra = IS_INTRA(s->current_picture.f.mb_type[(b_x >> is_luma) + ((b_y + 1) >> is_luma) * s->mb_stride]);
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;
a= dst[offset + x + 7*stride] - dst[offset + x + 6*stride]; a = dst[offset + x + 7 * stride] - dst[offset + x + 6 * stride];
b= dst[offset + x + 8*stride] - dst[offset + x + 7*stride]; b = dst[offset + x + 8 * stride] - dst[offset + x + 7 * stride];
c= dst[offset + x + 9*stride] - dst[offset + x + 8*stride]; c = dst[offset + x + 9 * stride] - dst[offset + x + 8 * stride];
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;
if(top_damage){ if (top_damage) {
dst[offset + x + 7*stride] = cm[dst[offset + x + 7*stride] + ((d*7)>>4)]; dst[offset + x + 7 * stride] = cm[dst[offset + x + 7 * stride] + ((d * 7) >> 4)];
dst[offset + x + 6*stride] = cm[dst[offset + x + 6*stride] + ((d*5)>>4)]; dst[offset + x + 6 * stride] = cm[dst[offset + x + 6 * stride] + ((d * 5) >> 4)];
dst[offset + x + 5*stride] = cm[dst[offset + x + 5*stride] + ((d*3)>>4)]; dst[offset + x + 5 * stride] = cm[dst[offset + x + 5 * stride] + ((d * 3) >> 4)];
dst[offset + x + 4*stride] = cm[dst[offset + x + 4*stride] + ((d*1)>>4)]; dst[offset + x + 4 * stride] = cm[dst[offset + x + 4 * stride] + ((d * 1) >> 4)];
} }
if(bottom_damage){ if (bottom_damage) {
dst[offset + x + 8*stride] = cm[dst[offset + x + 8*stride] - ((d*7)>>4)]; dst[offset + x + 8 * stride] = cm[dst[offset + x + 8 * stride] - ((d * 7) >> 4)];
dst[offset + x + 9*stride] = cm[dst[offset + x + 9*stride] - ((d*5)>>4)]; dst[offset + x + 9 * stride] = cm[dst[offset + x + 9 * stride] - ((d * 5) >> 4)];
dst[offset + x + 10*stride] = cm[dst[offset + x + 10*stride] - ((d*3)>>4)]; dst[offset + x + 10 * stride] = cm[dst[offset + x + 10 * stride] - ((d * 3) >> 4)];
dst[offset + x + 11*stride] = cm[dst[offset + x + 11*stride] - ((d*1)>>4)]; dst[offset + x + 11 * stride] = cm[dst[offset + x + 11 * stride] - ((d * 1) >> 4)];
} }
} }
} }
} }
} }
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
#define MV_UNCHANGED 1 #define MV_UNCHANGED 1
const int mb_stride = s->mb_stride; const int mb_stride = s->mb_stride;
const int mb_width = s->mb_width; const int mb_width = s->mb_width;
const int mb_height= s->mb_height; const int mb_height = s->mb_height;
int i, depth, num_avail; int i, depth, num_avail;
int mb_x, mb_y, mot_step, mot_stride; int mb_x, mb_y, mot_step, mot_stride;
set_mv_strides(s, &mot_step, &mot_stride); set_mv_strides(s, &mot_step, &mot_stride);
num_avail=0; num_avail = 0;
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];
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)
num_avail++; num_avail++;
else if(s->last_picture.f.data[0] && s->last_picture.f.motion_val[0]){ else if(s->last_picture.f.data[0] && s->last_picture.f.motion_val[0]){
const int mb_y= mb_xy / s->mb_stride; const int mb_y= mb_xy / s->mb_stride;
...@@ -408,146 +434,175 @@ static void guess_mv(MpegEncContext *s){ ...@@ -408,146 +434,175 @@ 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)) ||
for(mb_y=0; mb_y<s->mb_height; mb_y++){ num_avail <= mb_width / 2) {
for(mb_x=0; mb_x<s->mb_width; mb_x++){ for (mb_y = 0; mb_y < s->mb_height; mb_y++) {
const int mb_xy= mb_x + mb_y*s->mb_stride; for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
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
s->mb_intra=0; : MV_DIR_BACKWARD;
s->mv_type = MV_TYPE_16X16; s->mb_intra = 0;
s->mb_skipped=0; s->mv_type = MV_TYPE_16X16;
s->mb_skipped = 0;
s->dsp.clear_blocks(s->block[0]); s->dsp.clear_blocks(s->block[0]);
s->mb_x= mb_x; s->mb_x = mb_x;
s->mb_y= mb_y; s->mb_y = mb_y;
s->mv[0][0][0]= 0; s->mv[0][0][0] = 0;
s->mv[0][0][1]= 0; s->mv[0][0][1] = 0;
decode_mb(s, 0); decode_mb(s, 0);
} }
} }
goto end; goto end;
} }
for(depth=0;; depth++){ for (depth = 0; ; depth++) {
int changed, pass, none_left; int changed, pass, none_left;
none_left=1; none_left = 1;
changed=1; changed = 1;
for(pass=0; (changed || pass<2) && pass<10; pass++){ for (pass = 0; (changed || pass < 2) && pass < 10; pass++) {
int mb_x, mb_y; int mb_x, mb_y;
int score_sum=0; int score_sum = 0;
changed=0; changed = 0;
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;
int mv_predictor[8][2]={{0}}; int mv_predictor[8][2] = { { 0 } };
int ref[8]={0}; int ref[8] = { 0 };
int pred_count=0; int pred_count = 0;
int j; int j;
int best_score=256*256*256*64; int best_score = 256 * 256 * 256 * 64;
int best_pred=0; int best_pred = 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;
j=0; if (mb_y + 1 < mb_height && fixed[mb_xy + mb_stride] == MV_FROZEN)
if(mb_x>0 && fixed[mb_xy-1 ]==MV_CHANGED) j=1; j = 1;
if(mb_x+1<mb_width && fixed[mb_xy+1 ]==MV_CHANGED) j=1; if (j == 0)
if(mb_y>0 && fixed[mb_xy-mb_stride]==MV_CHANGED) j=1; continue;
if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]==MV_CHANGED) j=1;
if(j==0 && pass>1) continue; j = 0;
if (mb_x > 0 && fixed[mb_xy - 1 ] == MV_CHANGED)
none_left=0; j = 1;
if (mb_x + 1 < mb_width && fixed[mb_xy + 1 ] == MV_CHANGED)
if(mb_x>0 && fixed[mb_xy-1]){ j = 1;
mv_predictor[pred_count][0]= s->current_picture.f.motion_val[0][mot_index - mot_step][0]; if (mb_y > 0 && fixed[mb_xy - mb_stride] == MV_CHANGED)
mv_predictor[pred_count][1]= s->current_picture.f.motion_val[0][mot_index - mot_step][1]; j = 1;
ref [pred_count] = s->current_picture.f.ref_index[0][4*(mb_xy-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;
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][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;
int max_x, max_y, min_x, min_y, max_r, min_r; int max_x, max_y, min_x, min_y, max_r, min_r;
for(j=0; j<pred_count; j++){ for (j = 0; j < pred_count; j++) {
sum_x+= mv_predictor[j][0]; sum_x += mv_predictor[j][0];
sum_y+= mv_predictor[j][1]; sum_y += mv_predictor[j][1];
sum_r+= ref[j]; sum_r += ref[j];
if(j && ref[j] != ref[j-1]) if (j && ref[j] != ref[j - 1])
goto skip_mean_and_median; goto skip_mean_and_median;
} }
/* mean */ /* mean */
mv_predictor[pred_count][0] = sum_x/j; mv_predictor[pred_count][0] = sum_x / j;
mv_predictor[pred_count][1] = sum_y/j; mv_predictor[pred_count][1] = sum_y / j;
ref [pred_count] = sum_r/j; ref[pred_count] = sum_r / j;
/* median */ /* median */
if(pred_count>=3){ if (pred_count >= 3) {
min_y= min_x= min_r= 99999; min_y = min_x = min_r = 99999;
max_y= max_x= max_r=-99999; max_y = max_x = max_r = -99999;
}else{ } else {
min_x=min_y=max_x=max_y=min_r=max_r=0; min_x = min_y = max_x = max_y = min_r = max_r = 0;
} }
for(j=0; j<pred_count; j++){ for (j = 0; j < pred_count; j++) {
max_x= FFMAX(max_x, mv_predictor[j][0]); max_x = FFMAX(max_x, mv_predictor[j][0]);
max_y= FFMAX(max_y, mv_predictor[j][1]); max_y = FFMAX(max_y, mv_predictor[j][1]);
max_r= FFMAX(max_r, ref[j]); max_r = FFMAX(max_r, ref[j]);
min_x= FFMIN(min_x, mv_predictor[j][0]); min_x = FFMIN(min_x, mv_predictor[j][0]);
min_y= FFMIN(min_y, mv_predictor[j][1]); min_y = FFMIN(min_y, mv_predictor[j][1]);
min_r= FFMIN(min_r, ref[j]); min_r = FFMIN(min_r, ref[j]);
} }
mv_predictor[pred_count+1][0] = sum_x - max_x - min_x; mv_predictor[pred_count + 1][0] = sum_x - max_x - min_x;
mv_predictor[pred_count+1][1] = sum_y - max_y - min_y; mv_predictor[pred_count + 1][1] = sum_y - max_y - min_y;
ref [pred_count+1] = sum_r - max_r - min_r; ref[pred_count + 1] = sum_r - max_r - min_r;
if(pred_count==4){ if (pred_count == 4) {
mv_predictor[pred_count+1][0] /= 2; mv_predictor[pred_count + 1][0] /= 2;
mv_predictor[pred_count+1][1] /= 2; mv_predictor[pred_count + 1][1] /= 2;
ref [pred_count+1] /= 2; ref[pred_count + 1] /= 2;
} }
pred_count+=2; pred_count += 2;
} }
skip_mean_and_median:
skip_mean_and_median:
/* zero MV */ /* zero MV */
pred_count++; pred_count++;
...@@ -561,76 +616,83 @@ skip_mean_and_median: ...@@ -561,76 +616,83 @@ skip_mean_and_median:
if (!s->last_picture.f.motion_val[0] || if (!s->last_picture.f.motion_val[0] ||
!s->last_picture.f.ref_index[0]) !s->last_picture.f.ref_index[0])
goto skip_last_mv; goto skip_last_mv;
prev_x = s->last_picture.f.motion_val[0][mot_index][0]; prev_x = s->last_picture.f.motion_val[0][mot_index][0];
prev_y = s->last_picture.f.motion_val[0][mot_index][1]; prev_y = s->last_picture.f.motion_val[0][mot_index][1];
prev_ref = s->last_picture.f.ref_index[0][4*mb_xy]; prev_ref = s->last_picture.f.ref_index[0][4 * mb_xy];
} else { } else {
prev_x = s->current_picture.f.motion_val[0][mot_index][0]; prev_x = s->current_picture.f.motion_val[0][mot_index][0];
prev_y = s->current_picture.f.motion_val[0][mot_index][1]; prev_y = s->current_picture.f.motion_val[0][mot_index][1];
prev_ref = s->current_picture.f.ref_index[0][4*mb_xy]; prev_ref = s->current_picture.f.ref_index[0][4 * mb_xy];
} }
/* last MV */ /* last MV */
mv_predictor[pred_count][0]= prev_x; mv_predictor[pred_count][0] = prev_x;
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:
s->mv_dir = MV_DIR_FORWARD; skip_last_mv:
s->mb_intra=0; s->mv_dir = MV_DIR_FORWARD;
s->mv_type = MV_TYPE_16X16; s->mb_intra = 0;
s->mb_skipped=0; s->mv_type = MV_TYPE_16X16;
s->mb_skipped = 0;
s->dsp.clear_blocks(s->block[0]); s->dsp.clear_blocks(s->block[0]);
s->mb_x= mb_x; s->mb_x = mb_x;
s->mb_y= mb_y; s->mb_y = mb_y;
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]);
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;
for(k=0; k<16; k++) for (k = 0; k < 16; k++)
score += FFABS(src[k-s->linesize ]-src[k ]); score += FFABS(src[k - s->linesize] - src[k]);
} }
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
best_score= score; best_score = score;
best_pred= j; best_pred = j;
} }
} }
score_sum+= best_score; score_sum += best_score;
s->mv[0][0][0]= mv_predictor[best_pred][0]; s->mv[0][0][0] = mv_predictor[best_pred][0];
s->mv[0][0][1]= mv_predictor[best_pred][1]; s->mv[0][0][1] = mv_predictor[best_pred][1];
for(i=0; i<mot_step; i++) for (i = 0; i < mot_step; i++)
for(j=0; j<mot_step; j++){ for (j = 0; j < mot_step; j++) {
s->current_picture.f.motion_val[0][mot_index + i + j * mot_stride][0] = s->mv[0][0][0]; s->current_picture.f.motion_val[0][mot_index + i + j * mot_stride][0] = s->mv[0][0][0];
s->current_picture.f.motion_val[0][mot_index + i + j * mot_stride][1] = s->mv[0][0][1]; s->current_picture.f.motion_val[0][mot_index + i + j * mot_stride][1] = s->mv[0][0][1];
} }
...@@ -638,75 +700,85 @@ score_sum+= best_score; ...@@ -638,75 +700,85 @@ score_sum+= best_score;
decode_mb(s, ref[best_pred]); decode_mb(s, ref[best_pred]);
if(s->mv[0][0][0] != prev_x || s->mv[0][0][1] != prev_y){ if (s->mv[0][0][0] != prev_x || s->mv[0][0][1] != prev_y) {
fixed[mb_xy]=MV_CHANGED; fixed[mb_xy] = MV_CHANGED;
changed++; changed++;
}else } else
fixed[mb_xy]=MV_UNCHANGED; fixed[mb_xy] = MV_UNCHANGED;
} }
} }
// printf(".%d/%d", changed, score_sum); fflush(stdout); // printf(".%d/%d", changed, score_sum); fflush(stdout);
} }
if(none_left) if (none_left)
goto end; goto end;
for(i=0; i<s->mb_num; i++){ for (i = 0; i < s->mb_num; i++) {
int mb_xy= s->mb_index2xy[i]; int mb_xy = s->mb_index2xy[i];
if(fixed[mb_xy]) if (fixed[mb_xy])
fixed[mb_xy]=MV_FROZEN; fixed[mb_xy] = MV_FROZEN;
} }
// printf(":"); fflush(stdout); // printf(":"); fflush(stdout);
} }
end: 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++) {
const int mb_xy= s->mb_index2xy[i]; const int mb_xy = s->mb_index2xy[i];
const int error= s->error_status_table[mb_xy]; const int error = s->error_status_table[mb_xy];
if(!((error&ER_DC_ERROR) && (error&ER_MV_ERROR))) if (!((error & ER_DC_ERROR) && (error & ER_MV_ERROR)))
undamaged_count++; undamaged_count++;
} }
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
is_intra_likely=0; is_intra_likely = 0;
j=0; j = 0;
for(mb_y= 0; mb_y<s->mb_height-1; mb_y++){ for (mb_y = 0; mb_y < s->mb_height - 1; mb_y++) {
for(mb_x= 0; mb_x<s->mb_width; mb_x++){ for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
int error; int error;
const int mb_xy= mb_x + mb_y*s->mb_stride; const int mb_xy = mb_x + mb_y * s->mb_stride;
error= s->error_status_table[mb_xy]; error = s->error_status_table[mb_xy];
if((error&ER_DC_ERROR) && (error&ER_MV_ERROR)) if ((error & ER_DC_ERROR) && (error & ER_MV_ERROR))
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
...@@ -717,7 +789,7 @@ static int is_intra_more_likely(MpegEncContext *s){ ...@@ -717,7 +789,7 @@ static int is_intra_more_likely(MpegEncContext *s){
is_intra_likely += s->dsp.sad[0](NULL, last_mb_ptr, mb_ptr , s->linesize, 16); is_intra_likely += s->dsp.sad[0](NULL, last_mb_ptr, mb_ptr , s->linesize, 16);
// FIXME need await_progress() here // FIXME need await_progress() here
is_intra_likely -= s->dsp.sad[0](NULL, last_mb_ptr, last_mb_ptr+s->linesize*16, s->linesize, 16); is_intra_likely -= s->dsp.sad[0](NULL, last_mb_ptr, last_mb_ptr+s->linesize*16, s->linesize, 16);
}else{ } else {
if (IS_INTRA(s->current_picture.f.mb_type[mb_xy])) if (IS_INTRA(s->current_picture.f.mb_type[mb_xy]))
is_intra_likely++; is_intra_likely++;
else else
...@@ -725,117 +797,133 @@ static int is_intra_more_likely(MpegEncContext *s){ ...@@ -725,117 +797,133 @@ static int is_intra_more_likely(MpegEncContext *s){
} }
} }
} }
//printf("is_intra_likely: %d type:%d\n", is_intra_likely, s->pict_type); // printf("is_intra_likely: %d type:%d\n", is_intra_likely, s->pict_type);
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->error_count= 3*s->mb_num; s->mb_stride * s->mb_height * sizeof(uint8_t));
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,
const int start_i= av_clip(startx + starty * s->mb_width , 0, s->mb_num-1); int endx, int endy, int status)
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_i = av_clip(startx + starty * s->mb_width, 0, s->mb_num - 1);
const int end_xy = s->mb_index2xy[end_i]; const int end_i = av_clip(endx + endy * s->mb_width, 0, s->mb_num);
int mask= -1; const int start_xy = s->mb_index2xy[start_i];
const int end_xy = s->mb_index2xy[end_i];
if(s->avctx->hwaccel) int mask = -1;
if (s->avctx->hwaccel)
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)) {
mask &= ~(ER_AC_ERROR|ER_AC_END); mask &= ~(ER_AC_ERROR | ER_AC_END);
s->error_count -= end_i - start_i + 1; s->error_count -= end_i - start_i + 1;
} }
if(status & (ER_DC_ERROR|ER_DC_END)){ if (status & (ER_DC_ERROR | ER_DC_END)) {
mask &= ~(ER_DC_ERROR|ER_DC_END); mask &= ~(ER_DC_ERROR | ER_DC_END);
s->error_count -= end_i - start_i + 1; s->error_count -= end_i - start_i + 1;
} }
if(status & (ER_MV_ERROR|ER_MV_END)){ if (status & (ER_MV_ERROR | ER_MV_END)) {
mask &= ~(ER_MV_ERROR|ER_MV_END); mask &= ~(ER_MV_ERROR | ER_MV_END);
s->error_count -= end_i - start_i + 1; s->error_count -= end_i - start_i + 1;
} }
if(status & ER_MB_ERROR) { if (status & ER_MB_ERROR) {
s->error_occurred = 1; s->error_occurred = 1;
s->error_count= INT_MAX; s->error_count = INT_MAX;
} }
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,
}else{ (end_xy - start_xy) * sizeof(uint8_t));
} 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;
else{ else {
s->error_status_table[end_xy] &= mask; s->error_status_table[end_xy] &= mask;
s->error_status_table[end_xy] |= status; s->error_status_table[end_xy] |= status;
} }
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 &&
int prev_status= s->error_status_table[ s->mb_index2xy[start_i - 1] ]; s->avctx->skip_top * s->mb_width < start_i) {
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 };
int threshold= 50; int threshold = 50;
int is_intra_likely; int is_intra_likely;
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;
if(!s->err_recognition || s->error_count==0 || s->avctx->lowres || /* We do not support ER of field pictures yet,
s->avctx->hwaccel || * though it should not crash if enabled. */
s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU || if (!s->err_recognition || s->error_count == 0 || s->avctx->lowres ||
s->picture_structure != PICT_FRAME || // we do not support ER of field pictures yet, though it should not crash if enabled s->avctx->hwaccel ||
s->error_count==3*s->mb_width*(s->avctx->skip_top + s->avctx->skip_bottom)) return; s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU ||
s->picture_structure != PICT_FRAME ||
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");
for(i=0; i<2; i++){ for (i = 0; i < 2; i++) {
pic->f.ref_index[i] = av_mallocz(s->mb_stride * s->mb_height * 4 * sizeof(uint8_t)); pic->f.ref_index[i] = av_mallocz(s->mb_stride * s->mb_height * 4 * sizeof(uint8_t));
pic->motion_val_base[i]= av_mallocz((size+4) * 2 * sizeof(uint16_t)); pic->motion_val_base[i] = av_mallocz((size + 4) * 2 * sizeof(uint16_t));
pic->f.motion_val[i] = pic->motion_val_base[i] + 4; pic->f.motion_val[i] = pic->motion_val_base[i] + 4;
} }
pic->f.motion_subsample_log2 = 3; pic->f.motion_subsample_log2 = 3;
s->current_picture= *s->current_picture_ptr; s->current_picture = *s->current_picture_ptr;
} }
if(s->avctx->debug&FF_DEBUG_ER){ if (s->avctx->debug & FF_DEBUG_ER) {
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++) {
int status= s->error_status_table[mb_x + mb_y*s->mb_stride]; int status = s->error_status_table[mb_x + mb_y * s->mb_stride];
av_log(s->avctx, AV_LOG_DEBUG, "%2X ", status); av_log(s->avctx, AV_LOG_DEBUG, "%2X ", status);
} }
...@@ -845,144 +933,153 @@ void ff_er_frame_end(MpegEncContext *s){ ...@@ -845,144 +933,153 @@ void ff_er_frame_end(MpegEncContext *s){
#if 1 #if 1
/* handle overlapping slices */ /* handle overlapping slices */
for(error_type=1; error_type<=3; error_type++){ for (error_type = 1; error_type <= 3; error_type++) {
int end_ok=0; int end_ok = 0;
for(i=s->mb_num-1; i>=0; i--){ for (i = s->mb_num - 1; i >= 0; i--) {
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(error&(1<<error_type)) if (error & (1 << error_type))
end_ok=1; end_ok = 1;
if(error&(8<<error_type)) if (error & (8 << error_type))
end_ok=1; end_ok = 1;
if(!end_ok) if (!end_ok)
s->error_status_table[mb_xy]|= 1<<error_type; s->error_status_table[mb_xy] |= 1 << error_type;
if(error&VP_START) if (error & VP_START)
end_ok=0; end_ok = 0;
} }
} }
#endif #endif
#if 1 #if 1
/* handle slices with partitions of different length */ /* handle slices with partitions of different length */
if(s->partitioned_frame){ if (s->partitioned_frame) {
int end_ok=0; int end_ok = 0;
for(i=s->mb_num-1; i>=0; i--){ for (i = s->mb_num - 1; i >= 0; i--) {
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(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) ||
end_ok=1; (error & ER_DC_END) ||
(error & ER_AC_ERROR))
end_ok = 1;
if(!end_ok) if (!end_ok)
s->error_status_table[mb_xy]|= ER_AC_ERROR; s->error_status_table[mb_xy]|= ER_AC_ERROR;
if(error&VP_START) if (error & VP_START)
end_ok=0; end_ok = 0;
} }
} }
#endif #endif
/* handle missing slices */ /* handle missing slices */
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
const int mb_xy= s->mb_index2xy[i]; for (i = s->mb_num - 2; i >= s->mb_width + 100; i--) {
int error1= s->error_status_table[mb_xy ]; const int mb_xy = s->mb_index2xy[i];
int error2= s->error_status_table[s->mb_index2xy[i+1]]; int error1 = s->error_status_table[mb_xy];
int error2 = s->error_status_table[s->mb_index2xy[i + 1]];
if(error1&VP_START)
end_ok=1; if (error1 & VP_START)
end_ok = 1;
if( error2==(VP_START|ER_MB_ERROR|ER_MB_END)
&& error1!=(VP_START|ER_MB_ERROR|ER_MB_END) if (error2 == (VP_START | ER_MB_ERROR | ER_MB_END) &&
&& ((error1&ER_AC_END) || (error1&ER_DC_END) || (error1&ER_MV_END))){ //end & uninit error1 != (VP_START | ER_MB_ERROR | ER_MB_END) &&
end_ok=0; ((error1 & ER_AC_END) || (error1 & ER_DC_END) ||
(error1 & ER_MV_END))) {
// end & uninit
end_ok = 0;
} }
if(!end_ok) if (!end_ok)
s->error_status_table[mb_xy]|= ER_MB_ERROR; s->error_status_table[mb_xy] |= ER_MB_ERROR;
} }
} }
#if 1 #if 1
/* backward mark errors */ /* backward mark errors */
distance=9999999; distance = 9999999;
for(error_type=1; error_type<=3; error_type++){ for (error_type = 1; error_type <= 3; error_type++) {
for(i=s->mb_num-1; i>=0; i--){ for (i = s->mb_num - 1; i >= 0; i--) {
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->mbskip_table[mb_xy]) //FIXME partition specific if (!s->mbskip_table[mb_xy]) // FIXME partition specific
distance++; distance++;
if(error&(1<<error_type)) if (error & (1 << error_type))
distance= 0; distance = 0;
if(s->partitioned_frame){ if (s->partitioned_frame) {
if(distance < threshold_part[error_type-1]) if (distance < threshold_part[error_type - 1])
s->error_status_table[mb_xy]|= 1<<error_type; s->error_status_table[mb_xy] |= 1 << error_type;
}else{ } else {
if(distance < threshold) if (distance < threshold)
s->error_status_table[mb_xy]|= 1<<error_type; s->error_status_table[mb_xy] |= 1 << error_type;
} }
if(error&VP_START) if (error & VP_START)
distance= 9999999; distance = 9999999;
} }
} }
#endif #endif
/* forward mark errors */ /* forward mark errors */
error=0; error = 0;
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];
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;
} }
} }
#if 1 #if 1
/* handle not partitioned case */ /* handle not partitioned case */
if(!s->partitioned_frame){ if (!s->partitioned_frame) {
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_MB_ERROR) if (error & ER_MB_ERROR)
error|= ER_MB_ERROR; error |= ER_MB_ERROR;
s->error_status_table[mb_xy]= error; s->error_status_table[mb_xy] = error;
} }
} }
#endif #endif
dc_error= ac_error= mv_error=0; dc_error = ac_error = mv_error = 0;
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);
/* set unknown mb-type to most likely */ /* set unknown mb-type to most likely */
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) && (error&ER_MV_ERROR))) if (!((error & ER_DC_ERROR) && (error & ER_MV_ERROR)))
continue; continue;
if(is_intra_likely) if (is_intra_likely)
s->current_picture.f.mb_type[mb_xy] = MB_TYPE_INTRA4x4; s->current_picture.f.mb_type[mb_xy] = MB_TYPE_INTRA4x4;
else else
s->current_picture.f.mb_type[mb_xy] = MB_TYPE_16x16 | MB_TYPE_L0; s->current_picture.f.mb_type[mb_xy] = MB_TYPE_16x16 | MB_TYPE_L0;
...@@ -990,142 +1087,153 @@ void ff_er_frame_end(MpegEncContext *s){ ...@@ -990,142 +1087,153 @@ void ff_er_frame_end(MpegEncContext *s){
// change inter to intra blocks if no reference frames are available // change inter to intra blocks if no reference frames are available
if (!s->last_picture.f.data[0] && !s->next_picture.f.data[0]) if (!s->last_picture.f.data[0] && !s->next_picture.f.data[0])
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];
if (!IS_INTRA(s->current_picture.f.mb_type[mb_xy])) if (!IS_INTRA(s->current_picture.f.mb_type[mb_xy]))
s->current_picture.f.mb_type[mb_xy] = MB_TYPE_INTRA4x4; s->current_picture.f.mb_type[mb_xy] = MB_TYPE_INTRA4x4;
} }
/* handle inter blocks with damaged AC */ /* handle inter blocks with damaged AC */
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;
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(error&ER_MV_ERROR) continue; //inter with damaged MV if (IS_INTRA(mb_type))
if(!(error&ER_AC_ERROR)) continue; //undamaged inter continue; // intra
if (error & ER_MV_ERROR)
s->mv_dir = dir ? MV_DIR_BACKWARD : MV_DIR_FORWARD; continue; // inter with damaged MV
s->mb_intra=0; if (!(error & ER_AC_ERROR))
s->mb_skipped=0; continue; // undamaged inter
if(IS_8X8(mb_type)){
int mb_index= mb_x*2 + mb_y*2*s->b8_stride; s->mv_dir = dir ? MV_DIR_BACKWARD : MV_DIR_FORWARD;
s->mb_intra = 0;
s->mb_skipped = 0;
if (IS_8X8(mb_type)) {
int mb_index = mb_x * 2 + mb_y * 2 * s->b8_stride;
int j; int j;
s->mv_type = MV_TYPE_8X8; s->mv_type = MV_TYPE_8X8;
for(j=0; j<4; j++){ for (j = 0; j < 4; j++) {
s->mv[0][j][0] = s->current_picture.f.motion_val[dir][mb_index + (j & 1) + (j >> 1) * s->b8_stride][0]; s->mv[0][j][0] = s->current_picture.f.motion_val[dir][mb_index + (j & 1) + (j >> 1) * s->b8_stride][0];
s->mv[0][j][1] = s->current_picture.f.motion_val[dir][mb_index + (j & 1) + (j >> 1) * s->b8_stride][1]; s->mv[0][j][1] = s->current_picture.f.motion_val[dir][mb_index + (j & 1) + (j >> 1) * s->b8_stride][1];
} }
}else{ } else {
s->mv_type = MV_TYPE_16X16; s->mv_type = MV_TYPE_16X16;
s->mv[0][0][0] = s->current_picture.f.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][0]; s->mv[0][0][0] = s->current_picture.f.motion_val[dir][mb_x * 2 + mb_y * 2 * s->b8_stride][0];
s->mv[0][0][1] = s->current_picture.f.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][1]; s->mv[0][0][1] = s->current_picture.f.motion_val[dir][mb_x * 2 + mb_y * 2 * s->b8_stride][1];
} }
s->dsp.clear_blocks(s->block[0]); s->dsp.clear_blocks(s->block[0]);
s->mb_x= mb_x; s->mb_x = mb_x;
s->mb_y= mb_y; s->mb_y = mb_y;
decode_mb(s, 0/*FIXME h264 partitioned slices need this set*/); decode_mb(s, 0 /* FIXME h264 partitioned slices need this set */);
} }
} }
/* guess MVs */ /* guess MVs */
if(s->pict_type==AV_PICTURE_TYPE_B){ if (s->pict_type == AV_PICTURE_TYPE_B) {
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++) {
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(!(error&ER_MV_ERROR)) continue; //inter with undamaged MV if (IS_INTRA(mb_type))
if(!(error&ER_AC_ERROR)) continue; //undamaged inter continue;
if (!(error & ER_MV_ERROR))
s->mv_dir = MV_DIR_FORWARD|MV_DIR_BACKWARD; continue; // inter with undamaged MV
if(!s->last_picture.f.data[0]) s->mv_dir &= ~MV_DIR_FORWARD; if (!(error & ER_AC_ERROR))
if(!s->next_picture.f.data[0]) s->mv_dir &= ~MV_DIR_BACKWARD; continue; // undamaged inter
s->mb_intra=0;
s->mv_type = MV_TYPE_16X16; s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD;
s->mb_skipped=0; if (!s->last_picture.f.data[0])
s->mv_dir &= ~MV_DIR_FORWARD;
if(s->pp_time){ if (!s->next_picture.f.data[0])
int time_pp= s->pp_time; s->mv_dir &= ~MV_DIR_BACKWARD;
int time_pb= s->pb_time; s->mb_intra = 0;
s->mv_type = MV_TYPE_16X16;
s->mb_skipped = 0;
if (s->pp_time) {
int time_pp = s->pp_time;
int time_pb = s->pb_time;
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;
s->mv[1][0][0] = s->next_picture.f.motion_val[0][xy][0] * (time_pb - time_pp) / time_pp; s->mv[1][0][0] = s->next_picture.f.motion_val[0][xy][0] * (time_pb - time_pp) / time_pp;
s->mv[1][0][1] = s->next_picture.f.motion_val[0][xy][1] * (time_pb - time_pp) / time_pp; s->mv[1][0][1] = s->next_picture.f.motion_val[0][xy][1] * (time_pb - time_pp) / time_pp;
}else{ } else {
s->mv[0][0][0]= 0; s->mv[0][0][0] = 0;
s->mv[0][0][1]= 0; s->mv[0][0][1] = 0;
s->mv[1][0][0]= 0; s->mv[1][0][0] = 0;
s->mv[1][0][1]= 0; s->mv[1][0][1] = 0;
} }
s->dsp.clear_blocks(s->block[0]); s->dsp.clear_blocks(s->block[0]);
s->mb_x= mb_x; s->mb_x = mb_x;
s->mb_y= mb_y; s->mb_y = mb_y;
decode_mb(s, 0); decode_mb(s, 0);
} }
} }
}else } else
guess_mv(s); guess_mv(s);
/* the filters below are not XvMC compatible, skip them */ /* the filters below are not XvMC compatible, skip them */
if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration) if (CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration)
goto ec_clean; goto ec_clean;
/* fill DC for inter blocks */ /* fill DC for inter blocks */
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++) {
int dc, dcu, dcv, y, n; int dc, dcu, dcv, y, n;
int16_t *dc_ptr; int16_t *dc_ptr;
uint8_t *dest_y, *dest_cb, *dest_cr; uint8_t *dest_y, *dest_cb, *dest_cr;
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) && 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;
dest_cr = s->current_picture.f.data[2] + mb_x * 8 + mb_y * 8 * s->uvlinesize; dest_cr = s->current_picture.f.data[2] + mb_x * 8 + mb_y * 8 * s->uvlinesize;
dc_ptr= &s->dc_val[0][mb_x*2 + mb_y*2*s->b8_stride]; dc_ptr = &s->dc_val[0][mb_x * 2 + mb_y * 2 * s->b8_stride];
for(n=0; n<4; n++){ for (n = 0; n < 4; n++) {
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;
} }
dcu=dcv=0; dcu = dcv = 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++) {
dcu += dest_cb[x + y * s->uvlinesize]; dcu += dest_cb[x + y * s->uvlinesize];
dcv += dest_cr[x + y * s->uvlinesize]; dcv += dest_cr[x + y * s->uvlinesize];
} }
} }
s->dc_val[1][mb_x + mb_y*s->mb_stride]= (dcu+4)>>3; s->dc_val[1][mb_x + mb_y * s->mb_stride] = (dcu + 4) >> 3;
s->dc_val[2][mb_x + mb_y*s->mb_stride]= (dcv+4)>>3; s->dc_val[2][mb_x + mb_y * s->mb_stride] = (dcv + 4) >> 3;
} }
} }
#if 1 #if 1
...@@ -1134,21 +1242,24 @@ void ff_er_frame_end(MpegEncContext *s){ ...@@ -1134,21 +1242,24 @@ 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);
#if 1 #if 1
/* render DC only intra */ /* render DC only intra */
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++) {
uint8_t *dest_y, *dest_cb, *dest_cr; uint8_t *dest_y, *dest_cb, *dest_cr;
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_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;
...@@ -1159,27 +1270,34 @@ void ff_er_frame_end(MpegEncContext *s){ ...@@ -1159,27 +1270,34 @@ void ff_er_frame_end(MpegEncContext *s){
} }
#endif #endif
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:
/* clean a few tables */ /* clean a few tables */
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];
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 &&
s->mbskip_table[mb_xy]=0; (error & (ER_DC_ERROR | ER_MV_ERROR | ER_AC_ERROR))) {
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); ...@@ -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) ...@@ -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 ...@@ -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);
} }
......
...@@ -48,23 +48,23 @@ static unsigned int myrnd(unsigned int *seed_ptr, int n) ...@@ -48,23 +48,23 @@ static unsigned int myrnd(unsigned int *seed_ptr, int n)
/* integer cosinus */ /* integer cosinus */
static const unsigned short cos_table[(1 << COS_TABLE_BITS) + 2] = { static const unsigned short cos_table[(1 << COS_TABLE_BITS) + 2] = {
0x8000, 0x7ffe, 0x7ff6, 0x7fea, 0x7fd9, 0x7fc2, 0x7fa7, 0x7f87, 0x8000, 0x7ffe, 0x7ff6, 0x7fea, 0x7fd9, 0x7fc2, 0x7fa7, 0x7f87,
0x7f62, 0x7f38, 0x7f0a, 0x7ed6, 0x7e9d, 0x7e60, 0x7e1e, 0x7dd6, 0x7f62, 0x7f38, 0x7f0a, 0x7ed6, 0x7e9d, 0x7e60, 0x7e1e, 0x7dd6,
0x7d8a, 0x7d3a, 0x7ce4, 0x7c89, 0x7c2a, 0x7bc6, 0x7b5d, 0x7aef, 0x7d8a, 0x7d3a, 0x7ce4, 0x7c89, 0x7c2a, 0x7bc6, 0x7b5d, 0x7aef,
0x7a7d, 0x7a06, 0x798a, 0x790a, 0x7885, 0x77fb, 0x776c, 0x76d9, 0x7a7d, 0x7a06, 0x798a, 0x790a, 0x7885, 0x77fb, 0x776c, 0x76d9,
0x7642, 0x75a6, 0x7505, 0x7460, 0x73b6, 0x7308, 0x7255, 0x719e, 0x7642, 0x75a6, 0x7505, 0x7460, 0x73b6, 0x7308, 0x7255, 0x719e,
0x70e3, 0x7023, 0x6f5f, 0x6e97, 0x6dca, 0x6cf9, 0x6c24, 0x6b4b, 0x70e3, 0x7023, 0x6f5f, 0x6e97, 0x6dca, 0x6cf9, 0x6c24, 0x6b4b,
0x6a6e, 0x698c, 0x68a7, 0x67bd, 0x66d0, 0x65de, 0x64e9, 0x63ef, 0x6a6e, 0x698c, 0x68a7, 0x67bd, 0x66d0, 0x65de, 0x64e9, 0x63ef,
0x62f2, 0x61f1, 0x60ec, 0x5fe4, 0x5ed7, 0x5dc8, 0x5cb4, 0x5b9d, 0x62f2, 0x61f1, 0x60ec, 0x5fe4, 0x5ed7, 0x5dc8, 0x5cb4, 0x5b9d,
0x5a82, 0x5964, 0x5843, 0x571e, 0x55f6, 0x54ca, 0x539b, 0x5269, 0x5a82, 0x5964, 0x5843, 0x571e, 0x55f6, 0x54ca, 0x539b, 0x5269,
0x5134, 0x4ffb, 0x4ec0, 0x4d81, 0x4c40, 0x4afb, 0x49b4, 0x486a, 0x5134, 0x4ffb, 0x4ec0, 0x4d81, 0x4c40, 0x4afb, 0x49b4, 0x486a,
0x471d, 0x45cd, 0x447b, 0x4326, 0x41ce, 0x4074, 0x3f17, 0x3db8, 0x471d, 0x45cd, 0x447b, 0x4326, 0x41ce, 0x4074, 0x3f17, 0x3db8,
0x3c57, 0x3af3, 0x398d, 0x3825, 0x36ba, 0x354e, 0x33df, 0x326e, 0x3c57, 0x3af3, 0x398d, 0x3825, 0x36ba, 0x354e, 0x33df, 0x326e,
0x30fc, 0x2f87, 0x2e11, 0x2c99, 0x2b1f, 0x29a4, 0x2827, 0x26a8, 0x30fc, 0x2f87, 0x2e11, 0x2c99, 0x2b1f, 0x29a4, 0x2827, 0x26a8,
0x2528, 0x23a7, 0x2224, 0x209f, 0x1f1a, 0x1d93, 0x1c0c, 0x1a83, 0x2528, 0x23a7, 0x2224, 0x209f, 0x1f1a, 0x1d93, 0x1c0c, 0x1a83,
0x18f9, 0x176e, 0x15e2, 0x1455, 0x12c8, 0x113a, 0x0fab, 0x0e1c, 0x18f9, 0x176e, 0x15e2, 0x1455, 0x12c8, 0x113a, 0x0fab, 0x0e1c,
0x0c8c, 0x0afb, 0x096b, 0x07d9, 0x0648, 0x04b6, 0x0324, 0x0192, 0x0c8c, 0x0afb, 0x096b, 0x07d9, 0x0648, 0x04b6, 0x0324, 0x0192,
0x0000, 0x0000, 0x0000, 0x0000,
}; };
#define CSHIFT (FRAC_BITS - COS_TABLE_BITS - 2) #define CSHIFT (FRAC_BITS - COS_TABLE_BITS - 2)
...@@ -80,7 +80,7 @@ static int int_cos(int a) ...@@ -80,7 +80,7 @@ static int int_cos(int a)
neg = 0; neg = 0;
if (a > (FRAC_ONE / 4)) { if (a > (FRAC_ONE / 4)) {
neg = -1; neg = -1;
a = (FRAC_ONE / 2) - a; a = (FRAC_ONE / 2) - a;
} }
p = cos_table + (a >> CSHIFT); p = cos_table + (a >> CSHIFT);
/* linear interpolation */ /* linear interpolation */
...@@ -139,63 +139,63 @@ int main(int argc, char **argv) ...@@ -139,63 +139,63 @@ int main(int argc, char **argv)
/* 1 second of single freq sinus at 1000 Hz */ /* 1 second of single freq sinus at 1000 Hz */
a = 0; a = 0;
for(i=0;i<1 * sample_rate;i++) { for (i = 0; i < 1 * sample_rate; i++) {
v = (int_cos(a) * 10000) >> FRAC_BITS; v = (int_cos(a) * 10000) >> FRAC_BITS;
for(j=0;j<nb_channels;j++) for (j = 0; j < nb_channels; j++)
put_sample(v); put_sample(v);
a += (1000 * FRAC_ONE) / sample_rate; a += (1000 * FRAC_ONE) / sample_rate;
} }
/* 1 second of varing frequency between 100 and 10000 Hz */ /* 1 second of varing frequency between 100 and 10000 Hz */
a = 0; a = 0;
for(i=0;i<1 * sample_rate;i++) { for (i = 0; i < 1 * sample_rate; i++) {
v = (int_cos(a) * 10000) >> FRAC_BITS; v = (int_cos(a) * 10000) >> FRAC_BITS;
for(j=0;j<nb_channels;j++) for (j = 0; j < nb_channels; j++)
put_sample(v); put_sample(v);
f = 100 + (((10000 - 100) * i) / sample_rate); f = 100 + (((10000 - 100) * i) / sample_rate);
a += (f * FRAC_ONE) / sample_rate; a += (f * FRAC_ONE) / sample_rate;
} }
/* 0.5 second of low amplitude white noise */ /* 0.5 second of low amplitude white noise */
for(i=0;i<sample_rate / 2;i++) { for (i = 0; i < sample_rate / 2; i++) {
v = myrnd(&seed, 20000) - 10000; v = myrnd(&seed, 20000) - 10000;
for(j=0;j<nb_channels;j++) for (j = 0; j < nb_channels; j++)
put_sample(v); put_sample(v);
} }
/* 0.5 second of high amplitude white noise */ /* 0.5 second of high amplitude white noise */
for(i=0;i<sample_rate / 2;i++) { for (i = 0; i < sample_rate / 2; i++) {
v = myrnd(&seed, 65535) - 32768; v = myrnd(&seed, 65535) - 32768;
for(j=0;j<nb_channels;j++) for (j = 0; j < nb_channels; j++)
put_sample(v); put_sample(v);
} }
/* 1 second of unrelated ramps for each channel */ /* 1 second of unrelated ramps for each channel */
for(j=0;j<nb_channels;j++) { for (j = 0; j < nb_channels; j++) {
taba[j] = 0; taba[j] = 0;
tabf1[j] = 100 + myrnd(&seed, 5000); tabf1[j] = 100 + myrnd(&seed, 5000);
tabf2[j] = 100 + myrnd(&seed, 5000); tabf2[j] = 100 + myrnd(&seed, 5000);
} }
for(i=0;i<1 * sample_rate;i++) { for (i = 0; i < 1 * sample_rate; i++) {
for(j=0;j<nb_channels;j++) { for (j = 0; j < nb_channels; j++) {
v = (int_cos(taba[j]) * 10000) >> FRAC_BITS; v = (int_cos(taba[j]) * 10000) >> FRAC_BITS;
put_sample(v); put_sample(v);
f = tabf1[j] + (((tabf2[j] - tabf1[j]) * i) / sample_rate); f = tabf1[j] + (((tabf2[j] - tabf1[j]) * i) / sample_rate);
taba[j] += (f * FRAC_ONE) / sample_rate; taba[j] += (f * FRAC_ONE) / sample_rate;
} }
} }
/* 2 seconds of 500 Hz with varying volume */ /* 2 seconds of 500 Hz with varying volume */
a = 0; a = 0;
ampa = 0; ampa = 0;
for(i=0;i<2 * sample_rate;i++) { for (i = 0; i < 2 * sample_rate; i++) {
for(j=0;j<nb_channels;j++) { for (j = 0; j < nb_channels; j++) {
amp = ((FRAC_ONE + int_cos(ampa)) * 5000) >> FRAC_BITS; amp = ((FRAC_ONE + int_cos(ampa)) * 5000) >> FRAC_BITS;
if (j & 1) if (j & 1)
amp = 10000 - amp; amp = 10000 - amp;
v = (int_cos(a) * amp) >> FRAC_BITS; v = (int_cos(a) * amp) >> FRAC_BITS;
put_sample(v); put_sample(v);
a += (500 * FRAC_ONE) / sample_rate; a += (500 * FRAC_ONE) / sample_rate;
ampa += (2 * FRAC_ONE) / sample_rate; ampa += (2 * FRAC_ONE) / sample_rate;
} }
} }
......
...@@ -27,18 +27,19 @@ int main(void) ...@@ -27,18 +27,19 @@ int main(void)
static const char b64[] = static const char b64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
unsigned i_bits = 0; unsigned i_bits = 0;
int i_shift = 0; int i_shift = 0;
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; \
} while (0) } while (0)
while ((in = getchar()) != EOF) { while ((in = getchar()) != EOF) {
i_bits = (i_bits << 8) + in; i_bits = (i_bits << 8) + in;
i_shift += 8; i_shift += 8;
while (i_shift > 6) while (i_shift > 6)
putb64(); putb64();
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include <inttypes.h> #include <inttypes.h>
#define FIXP (1 << 16) #define FIXP (1 << 16)
#define MY_PI 205887 //(M_PI * FIX) #define MY_PI 205887 // (M_PI * FIX)
static int64_t int_pow(int64_t a, int p) static int64_t int_pow(int64_t a, int p)
{ {
...@@ -47,7 +47,7 @@ static int64_t int_sin(int64_t a) ...@@ -47,7 +47,7 @@ static int64_t int_sin(int64_t a)
if (a >= MY_PI * 3 / 2) if (a >= MY_PI * 3 / 2)
a -= 2 * MY_PI; // -PI / 2 .. 3PI / 2 a -= 2 * MY_PI; // -PI / 2 .. 3PI / 2
if (a >= MY_PI /2) if (a >= MY_PI / 2)
a = MY_PI - a; // -PI / 2 .. PI / 2 a = MY_PI - a; // -PI / 2 .. PI / 2
return a - int_pow(a, 3) / 6 + int_pow(a, 5) / 120 - int_pow(a, 7) / 5040; return a - int_pow(a, 3) / 6 + int_pow(a, 5) / 120 - int_pow(a, 7) / 5040;
...@@ -67,49 +67,49 @@ static void rgb24_to_yuv420p(unsigned char *lum, unsigned char *cb, ...@@ -67,49 +67,49 @@ static void rgb24_to_yuv420p(unsigned char *lum, unsigned char *cb,
wrap = width; wrap = width;
wrap3 = width * 3; wrap3 = width * 3;
p = src; p = src;
for (y = 0; y < height; y += 2) { for (y = 0; y < height; y += 2) {
for (x = 0; x < width; x += 2) { for (x = 0; x < width; x += 2) {
r = p[0]; r = p[0];
g = p[1]; g = p[1];
b = p[2]; b = p[2];
r1 = r; r1 = r;
g1 = g; g1 = g;
b1 = b; b1 = b;
lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
r = p[3]; r = p[3];
g = p[4]; g = p[4];
b = p[5]; b = p[5];
r1 += r; r1 += r;
g1 += g; g1 += g;
b1 += b; b1 += b;
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;
p += wrap3; p += wrap3;
lum += wrap; lum += wrap;
r = p[0]; r = p[0];
g = p[1]; g = p[1];
b = p[2]; b = p[2];
r1 += r; r1 += r;
g1 += g; g1 += g;
b1 += b; b1 += b;
lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
r = p[3]; r = p[3];
g = p[4]; g = p[4];
b = p[5]; b = p[5];
r1 += r; r1 += r;
g1 += g; g1 += g;
b1 += b; b1 += b;
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] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 +
FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128; FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 -
FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128; FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
cb++; cb++;
cr++; cr++;
...@@ -171,7 +171,7 @@ static void put_pixel(int x, int y, int r, int g, int b) ...@@ -171,7 +171,7 @@ static void put_pixel(int x, int y, int r, int g, int b)
y < 0 || y >= height) y < 0 || y >= height)
return; return;
p = rgb_tab + y * wrap + x * 3; p = rgb_tab + y * wrap + x * 3;
p[0] = r; p[0] = r;
p[1] = g; p[1] = g;
p[2] = b; p[2] = b;
...@@ -181,8 +181,8 @@ unsigned char tab_r[256 * 256]; ...@@ -181,8 +181,8 @@ unsigned char tab_r[256 * 256];
unsigned char tab_g[256 * 256]; unsigned char tab_g[256 * 256];
unsigned char tab_b[256 * 256]; unsigned char tab_b[256 * 256];
int h_cos [360]; int h_cos[360];
int h_sin [360]; int h_sin[360];
static int ipol(uint8_t *src, int x, int y) static int ipol(uint8_t *src, int x, int y)
{ {
...@@ -202,8 +202,8 @@ static int ipol(uint8_t *src, int x, int y) ...@@ -202,8 +202,8 @@ static int ipol(uint8_t *src, int x, int y)
static void gen_image(int num, int w, int h) static void gen_image(int num, int w, int h)
{ {
const int c = h_cos [num % 360]; const int c = h_cos[num % 360];
const int s = h_sin [num % 360]; const int s = h_sin[num % 360];
const int xi = -(w / 2) * c; const int xi = -(w / 2) * c;
const int yi = (w / 2) * s; const int yi = (w / 2) * s;
...@@ -217,16 +217,19 @@ static void gen_image(int num, int w, int h) ...@@ -217,16 +217,19 @@ static void gen_image(int num, int w, int h)
int yprime = yj; int yprime = yj;
for (j = 0; j < h; j++) { for (j = 0; j < h; j++) {
x = xprime + xi + FIXP * w / 2; x = xprime + xi + FIXP * w / 2;
xprime += s; xprime += s;
y = yprime + yi + FIXP * h / 2; y = yprime + yi + FIXP * h / 2;
yprime += c; yprime += c;
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));
} }
} }
} }
...@@ -264,13 +267,13 @@ static int init_demo(const char *filename) ...@@ -264,13 +267,13 @@ static int init_demo(const char *filename)
/* tables sin/cos */ /* tables sin/cos */
for (i = 0; i < 360; i++) { for (i = 0; i < 360; i++) {
radian = 2 * i * MY_PI / 360; radian = 2 * i * MY_PI / 360;
h = 2 * FIXP + int_sin (radian); h = 2 * FIXP + int_sin(radian);
h_cos[i] = h * int_sin(radian + MY_PI / 2) / 2 / FIXP; h_cos[i] = h * int_sin(radian + MY_PI / 2) / 2 / FIXP;
h_sin[i] = h * int_sin(radian) / 2 / FIXP; h_sin[i] = h * int_sin(radian) / 2 / FIXP;
} }
return 0; return 0;
} }
int main(int argc, char **argv) int main(int argc, char **argv)
......
...@@ -24,32 +24,32 @@ ...@@ -24,32 +24,32 @@
#include <inttypes.h> #include <inttypes.h>
#include <assert.h> #include <assert.h>
#define FFMIN(a,b) ((a) > (b) ? (b) : (a)) #define FFMIN(a, b) ((a) > (b) ? (b) : (a))
#define F 100 #define F 100
#define SIZE 2048 #define SIZE 2048
uint64_t exp16_table[21]={ uint64_t exp16_table[21] = {
65537, 65537,
65538, 65538,
65540, 65540,
65544, 65544,
65552, 65552,
65568, 65568,
65600, 65600,
65664, 65664,
65793, 65793,
66050, 66050,
66568, 66568,
67616, 67616,
69763, 69763,
74262, 74262,
84150, 84150,
108051, 108051,
178145, 178145,
484249, 484249,
3578144, 3578144,
195360063, 195360063,
582360139072LL, 582360139072LL,
}; };
#if 0 #if 0
...@@ -68,63 +68,66 @@ static unsigned int exp16(unsigned int a){ ...@@ -68,63 +68,66 @@ 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;
if(a < 1<<16) if (a < 1 << 16)
return -log16((1LL<<32) / a); return -log16((1LL << 32) / a);
a<<=16; a <<= 16;
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))
out |= 1<<i; continue;
a = ((a/b)<<16) + (((a%b)<<16) + b/2)/b; out |= 1 << i;
a = ((a / b) << 16) + (((a % b) << 16) + b / 2) / b;
} }
return out; return out;
} }
static uint64_t int_sqrt(uint64_t a) static uint64_t int_sqrt(uint64_t a)
{ {
uint64_t ret=0; uint64_t ret = 0;
uint64_t ret_sq = 0;
int s; int s;
uint64_t ret_sq=0;
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;
if(b<=a){ if (b <= a) {
ret_sq=b; ret_sq = b;
ret+= 1ULL<<s; ret += 1ULL << s;
} }
} }
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;
FILE *f[2]; FILE *f[2];
uint8_t buf[2][SIZE]; uint8_t buf[2][SIZE];
uint64_t psnr; uint64_t psnr;
int len= argc<4 ? 1 : atoi(argv[3]); int len = argc < 4 ? 1 : atoi(argv[3]);
int64_t max= (1<<(8*len))-1; int64_t max = (1 << (8 * len)) - 1;
int shift= argc<5 ? 0 : atoi(argv[4]); int shift = argc < 5 ? 0 : atoi(argv[4]);
int skip_bytes = argc<6 ? 0 : atoi(argv[5]); int skip_bytes = argc < 6 ? 0 : atoi(argv[5]);
int size0=0; int size0 = 0;
int size1=0; int size1 = 0;
int maxdist = 0; int maxdist = 0;
if(argc<3){ if (argc < 3) {
printf("tiny_psnr <file1> <file2> [<elem size> [<shift> [<skip bytes>]]]\n"); printf("tiny_psnr <file1> <file2> [<elem size> [<shift> [<skip bytes>]]]\n");
printf("WAV headers are skipped automatically.\n"); printf("WAV headers are skipped automatically.\n");
return 1; return 1;
} }
f[0]= fopen(argv[1], "rb"); f[0] = fopen(argv[1], "rb");
f[1]= fopen(argv[2], "rb"); f[1] = fopen(argv[2], "rb");
if(!f[0] || !f[1]){ if (!f[0] || !f[1]) {
fprintf(stderr, "Could not open input files.\n"); fprintf(stderr, "Could not open input files.\n");
return 1; return 1;
} }
...@@ -133,12 +136,12 @@ int main(int argc,char* argv[]){ ...@@ -133,12 +136,12 @@ int main(int argc,char* argv[]){
uint8_t *p = buf[i]; uint8_t *p = buf[i];
if (fread(p, 1, 12, f[i]) != 12) if (fread(p, 1, 12, f[i]) != 12)
return 1; return 1;
if (!memcmp(p, "RIFF", 4) && if (!memcmp(p, "RIFF", 4) &&
!memcmp(p+8, "WAVE", 4)) { !memcmp(p + 8, "WAVE", 4)) {
if (fread(p, 1, 8, f[i]) != 8) if (fread(p, 1, 8, f[i]) != 8)
return 1; return 1;
while (memcmp(p, "data", 4)) { while (memcmp(p, "data", 4)) {
int s = p[4] | p[5]<<8 | p[6]<<16 | p[7]<<24; int s = p[4] | p[5] << 8 | p[6] << 16 | p[7] << 24;
fseek(f[i], s, SEEK_CUR); fseek(f[i], s, SEEK_CUR);
if (fread(p, 1, 8, f[i]) != 8) if (fread(p, 1, 8, f[i]) != 8)
return 1; return 1;
...@@ -148,47 +151,47 @@ int main(int argc,char* argv[]){ ...@@ -148,47 +151,47 @@ int main(int argc,char* argv[]){
} }
} }
fseek(f[shift<0], abs(shift), SEEK_CUR); fseek(f[shift < 0], abs(shift), SEEK_CUR);
fseek(f[0],skip_bytes,SEEK_CUR); fseek(f[0], skip_bytes, SEEK_CUR);
fseek(f[1],skip_bytes,SEEK_CUR); fseek(f[1], skip_bytes, SEEK_CUR);
for(;;){ for (;;) {
int s0= fread(buf[0], 1, SIZE, f[0]); int s0 = fread(buf[0], 1, SIZE, f[0]);
int s1= fread(buf[1], 1, SIZE, f[1]); int s1 = fread(buf[1], 1, SIZE, f[1]);
for(j=0; j<FFMIN(s0,s1); j++){ for (j = 0; j < FFMIN(s0, s1); j++) {
int64_t a= buf[0][j]; int64_t a = buf[0][j];
int64_t b= buf[1][j]; int64_t b = buf[1][j];
int dist; int dist;
if(len==2){ if (len == 2) {
a= (int16_t)(a | (buf[0][++j]<<8)); a = (int16_t)(a | (buf[0][++j] << 8));
b= (int16_t)(b | (buf[1][ j]<<8)); b = (int16_t)(b | (buf[1][ j] << 8));
} }
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;
if(s0+s1<=0) if (s0 + s1 <= 0)
break; break;
} }
i= FFMIN(size0,size1)/len; i = FFMIN(size0, size1) / len;
if(!i) i=1; if (!i)
dev= int_sqrt( ((sse/i)*F*F) + (((sse%i)*F*F) + i/2)/i ); i = 1;
if(sse) dev = int_sqrt(((sse / i) * F * F) + (((sse % i) * F * F) + i / 2) / i);
psnr= ((2*log16(max<<16) + log16(i) - log16(sse))*284619LL*F + (1LL<<31)) / (1LL<<32); if (sse)
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;
} }
...@@ -27,67 +27,73 @@ ...@@ -27,67 +27,73 @@
#define SCALEBITS 8 #define SCALEBITS 8
#define ONE_HALF (1 << (SCALEBITS - 1)) #define ONE_HALF (1 << (SCALEBITS - 1))
#define FIX(x) ((int) ((x) * (1L<<SCALEBITS) + 0.5)) #define FIX(x) ((int) ((x) * (1L << SCALEBITS) + 0.5))
static void rgb24_to_yuv420p(uint8_t *lum, uint8_t *cb, uint8_t *cr, static void rgb24_to_yuv420p(uint8_t *lum, uint8_t *cb, uint8_t *cr,
uint8_t *src, int width, int height) uint8_t *src, int width, int height)
{ {
int wrap, wrap3, x, y; int wrap, wrap3, x, y;
int r, g, b, r1, g1, b1; int r, g, b, r1, g1, b1;
uint8_t *p; uint8_t *p;
wrap = width; wrap = width;
wrap3 = width * 3; wrap3 = width * 3;
p = src; p = src;
for(y=0;y<height;y+=2) { for (y = 0; y < height; y += 2) {
for(x=0;x<width;x+=2) { for (x = 0; x < width; x += 2) {
r = p[0]; r = p[0];
g = p[1]; g = p[1];
b = p[2]; b = p[2];
r1 = r; r1 = r;
g1 = g; g1 = g;
b1 = b; b1 = b;
lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
r = p[3]; r = p[3];
g = p[4]; g = p[4];
b = p[5]; b = p[5];
r1 += r; r1 += r;
g1 += g; g1 += g;
b1 += b; b1 += b;
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;
p += wrap3; p += wrap3;
lum += wrap; lum += wrap;
r = p[0]; r = p[0];
g = p[1]; g = p[1];
b = p[2]; b = p[2];
r1 += r; r1 += r;
g1 += g; g1 += g;
b1 += b; b1 += b;
lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
r = p[3]; r = p[3];
g = p[4]; g = p[4];
b = p[5]; b = p[5];
r1 += r; r1 += r;
g1 += g; g1 += g;
b1 += b; b1 += b;
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++;
p += -wrap3 + 2 * 3; p += -wrap3 + 2 * 3;
lum += -wrap + 2; lum += -wrap + 2;
} }
p += wrap3; p += wrap3;
lum += wrap; lum += wrap;
} }
} }
...@@ -106,19 +112,19 @@ static void pgmyuv_save(const char *filename, int w, int h, ...@@ -106,19 +112,19 @@ static void pgmyuv_save(const char *filename, int w, int h,
unsigned char *lum_tab, *cb_tab, *cr_tab; unsigned char *lum_tab, *cb_tab, *cr_tab;
lum_tab = malloc(w * h); lum_tab = malloc(w * h);
cb_tab = malloc((w * h) / 4); cb_tab = malloc((w * h) / 4);
cr_tab = malloc((w * h) / 4); cr_tab = malloc((w * h) / 4);
rgb24_to_yuv420p(lum_tab, cb_tab, cr_tab, rgb_tab, w, h); rgb24_to_yuv420p(lum_tab, cb_tab, cr_tab, rgb_tab, w, h);
f = fopen(filename,"wb"); f = fopen(filename, "wb");
fprintf(f, "P5\n%d %d\n%d\n", w, (h * 3) / 2, 255); fprintf(f, "P5\n%d %d\n%d\n", w, (h * 3) / 2, 255);
fwrite(lum_tab, 1, w * h, f); fwrite(lum_tab, 1, w * h, f);
h2 = h / 2; h2 = h / 2;
w2 = w / 2; w2 = w / 2;
cb = cb_tab; cb = cb_tab;
cr = cr_tab; cr = cr_tab;
for(i=0;i<h2;i++) { for (i = 0; i < h2; i++) {
fwrite(cb, 1, w2, f); fwrite(cb, 1, w2, f);
fwrite(cr, 1, w2, f); fwrite(cr, 1, w2, f);
cb += w2; cb += w2;
...@@ -142,7 +148,7 @@ static void put_pixel(int x, int y, int r, int g, int b) ...@@ -142,7 +148,7 @@ static void put_pixel(int x, int y, int r, int g, int b)
y < 0 || y >= height) y < 0 || y >= height)
return; return;
p = rgb_tab + y * wrap + x * 3; p = rgb_tab + y * wrap + x * 3;
p[0] = r; p[0] = r;
p[1] = g; p[1] = g;
p[2] = b; p[2] = b;
...@@ -180,7 +186,7 @@ static int int_cos(int a) ...@@ -180,7 +186,7 @@ static int int_cos(int a)
neg = 0; neg = 0;
if (a > (FRAC_ONE / 4)) { if (a > (FRAC_ONE / 4)) {
neg = -1; neg = -1;
a = (FRAC_ONE / 2) - a; a = (FRAC_ONE / 2) - a;
} }
v = FRAC_ONE - ((a * a) >> 4); v = FRAC_ONE - ((a * a) >> 4);
v = (v ^ neg) - neg; v = (v ^ neg) - neg;
...@@ -204,7 +210,7 @@ static void gen_image(int num, int w, int h) ...@@ -204,7 +210,7 @@ static void gen_image(int num, int w, int h)
unsigned int seed1; unsigned int seed1;
if (num == 0) { if (num == 0) {
for(i=0;i<NB_OBJS;i++) { for (i = 0; i < NB_OBJS; i++) {
objs[i].x = myrnd(&seed, w); objs[i].x = myrnd(&seed, w);
objs[i].y = myrnd(&seed, h); objs[i].y = myrnd(&seed, h);
objs[i].w = myrnd(&seed, w / 4) + 10; objs[i].w = myrnd(&seed, w / 4) + 10;
...@@ -219,21 +225,21 @@ static void gen_image(int num, int w, int h) ...@@ -219,21 +225,21 @@ static void gen_image(int num, int w, int h)
/* test motion estimation */ /* test motion estimation */
dx = int_cos(num * FRAC_ONE / 50) * 35; dx = int_cos(num * FRAC_ONE / 50) * 35;
dy = int_cos(num * FRAC_ONE / 50 + FRAC_ONE / 10) * 30; dy = int_cos(num * FRAC_ONE / 50 + FRAC_ONE / 10) * 30;
for(y=0;y<h;y++) { for (y = 0; y < h; y++) {
for(x=0;x<w;x++) { for (x = 0; x < w; x++) {
x1 = (x << FRAC_BITS) + dx; x1 = (x << FRAC_BITS) + dx;
y1 = (y << FRAC_BITS) + dy; y1 = (y << FRAC_BITS) + dy;
r = ((y1 * 7) >> FRAC_BITS) & 0xff; r = ((y1 * 7) >> FRAC_BITS) & 0xff;
g = (((x1 + y1) * 9) >> FRAC_BITS) & 0xff; g = (((x1 + y1) * 9) >> FRAC_BITS) & 0xff;
b = ((x1 * 5) >> FRAC_BITS) & 0xff; b = ((x1 * 5) >> FRAC_BITS) & 0xff;
put_pixel(x, y, r, g, b); put_pixel(x, y, r, g, b);
} }
} }
/* then some noise with very high intensity to test saturation */ /* then some noise with very high intensity to test saturation */
seed1 = num; seed1 = num;
for(y=0;y<NOISE_W;y++) { for (y = 0; y < NOISE_W; y++) {
for(x=0;x<NOISE_W;x++) { for (x = 0; x < NOISE_W; x++) {
r = myrnd(&seed1, 256); r = myrnd(&seed1, 256);
g = myrnd(&seed1, 256); g = myrnd(&seed1, 256);
b = myrnd(&seed1, 256); b = myrnd(&seed1, 256);
...@@ -242,11 +248,11 @@ static void gen_image(int num, int w, int h) ...@@ -242,11 +248,11 @@ static void gen_image(int num, int w, int h)
} }
/* then moving objects */ /* then moving objects */
for(i=0;i<NB_OBJS;i++) { for (i = 0; i < NB_OBJS; i++) {
VObj *p = &objs[i]; VObj *p = &objs[i];
seed1 = i; seed1 = i;
for(y=0;y<p->h;y++) { for (y = 0; y < p->h; y++) {
for(x=0;x<p->w;x++) { for (x = 0; x < p->w; x++) {
r = p->r; r = p->r;
g = p->g; g = p->g;
b = p->b; b = p->b;
...@@ -277,11 +283,11 @@ int main(int argc, char **argv) ...@@ -277,11 +283,11 @@ int main(int argc, char **argv)
h = DEFAULT_HEIGHT; h = DEFAULT_HEIGHT;
rgb_tab = malloc(w * h * 3); rgb_tab = malloc(w * h * 3);
wrap = w * 3; wrap = w * 3;
width = w; width = w;
height = h; height = h;
for(i=0;i<DEFAULT_NB_PICT;i++) { for (i = 0; i < DEFAULT_NB_PICT; i++) {
snprintf(buf, sizeof(buf), "%s%02d.pgm", argv[1], i); snprintf(buf, sizeof(buf), "%s%02d.pgm", argv[1], i);
gen_image(i, w, h); gen_image(i, w, h);
pgmyuv_save(buf, w, h, rgb_tab); pgmyuv_save(buf, w, h, rgb_tab);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment