mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
frame skip support
Originally committed as revision 3742 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
2f3eca0806
commit
bbf18b21b7
6
ffmpeg.c
6
ffmpeg.c
@ -193,6 +193,8 @@ static int video_level = FF_LEVEL_UNKNOWN;
|
||||
static int nsse_weight = 8;
|
||||
static int subpel_quality= 8;
|
||||
static int lowres= 0;
|
||||
static int frame_skip_threshold= 0;
|
||||
static int frame_skip_factor= 0;
|
||||
extern int loop_input; /* currently a hack */
|
||||
|
||||
static int gop_size = 12;
|
||||
@ -3223,6 +3225,8 @@ static void opt_output_file(const char *filename)
|
||||
video_enc->level= video_level;
|
||||
video_enc->nsse_weight= nsse_weight;
|
||||
video_enc->me_subpel_quality= subpel_quality;
|
||||
video_enc->frame_skip_threshold= frame_skip_threshold;
|
||||
video_enc->frame_skip_factor= frame_skip_factor;
|
||||
|
||||
if(packet_size){
|
||||
video_enc->rtp_mode= 1;
|
||||
@ -3949,6 +3953,8 @@ const OptionDef options[] = {
|
||||
{ "subq", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&subpel_quality}, "", "" },
|
||||
{ "lowres", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&lowres}, "", "" },
|
||||
{ "vtag", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_video_tag}, "force video tag/fourcc", "fourcc/tag" },
|
||||
{ "skip_threshold", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&frame_skip_threshold}, "frame skip threshold", "threshold" },
|
||||
{ "skip_factor", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&frame_skip_factor}, "frame skip factor", "factor" },
|
||||
|
||||
/* audio options */
|
||||
{ "ab", HAS_ARG | OPT_AUDIO, {(void*)opt_audio_bitrate}, "set audio bitrate (in kbit/s)", "bitrate", },
|
||||
|
@ -17,7 +17,7 @@ extern "C" {
|
||||
|
||||
#define FFMPEG_VERSION_INT 0x000409
|
||||
#define FFMPEG_VERSION "0.4.9-pre1"
|
||||
#define LIBAVCODEC_BUILD 4734
|
||||
#define LIBAVCODEC_BUILD 4735
|
||||
|
||||
#define LIBAVCODEC_VERSION_INT FFMPEG_VERSION_INT
|
||||
#define LIBAVCODEC_VERSION FFMPEG_VERSION
|
||||
@ -1683,12 +1683,26 @@ typedef struct AVCodecContext {
|
||||
int lowres;
|
||||
|
||||
/**
|
||||
* bistream width / height. may be different from width/height if lowres
|
||||
* bitsream width / height. may be different from width/height if lowres
|
||||
* or other things are used
|
||||
* - encoding: unused
|
||||
* - decoding: set by user before init if known, codec should override / dynamically change if needed
|
||||
*/
|
||||
int coded_width, coded_height;
|
||||
|
||||
/**
|
||||
* frame skip threshold
|
||||
* - encoding: set by user
|
||||
* - decoding: unused
|
||||
*/
|
||||
int frame_skip_threshold;
|
||||
|
||||
/**
|
||||
* frame skip factor
|
||||
* - encoding: set by user
|
||||
* - decoding: unused
|
||||
*/
|
||||
int frame_skip_factor;
|
||||
} AVCodecContext;
|
||||
|
||||
|
||||
|
@ -2018,6 +2018,44 @@ static int load_input_picture(MpegEncContext *s, AVFrame *pic_arg){
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int block_max(DCTELEM *block){
|
||||
int i, max;
|
||||
|
||||
max=0;
|
||||
for(i=0; i<64; i++){
|
||||
int v= ABS(block[i]);
|
||||
if(v>max) max= v;
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
static int skip_check(MpegEncContext *s, Picture *p, Picture *ref){
|
||||
int x, y, plane;
|
||||
int score=0;
|
||||
|
||||
for(plane=0; plane<3; plane++){
|
||||
const int stride= p->linesize[plane];
|
||||
const int bw= plane ? 1 : 2;
|
||||
for(y=0; y<s->mb_height*bw; y++){
|
||||
for(x=0; x<s->mb_width*bw; x++){
|
||||
int v;
|
||||
|
||||
s->dsp.diff_pixels(s->block[0], p->data[plane] + 8*(x + y*stride), ref->data[plane] + 8*(x + y*stride), stride);
|
||||
v= block_max(s->block[0]);
|
||||
|
||||
if(v>score)
|
||||
score=v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(score < s->avctx->frame_skip_threshold)
|
||||
return 1;
|
||||
if(score < ((s->avctx->frame_skip_factor * s->lambda)>>8))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void select_input_picture(MpegEncContext *s){
|
||||
int i;
|
||||
|
||||
@ -2033,7 +2071,26 @@ static void select_input_picture(MpegEncContext *s){
|
||||
s->reordered_input_picture[0]->coded_picture_number= s->coded_picture_number++;
|
||||
}else{
|
||||
int b_frames;
|
||||
|
||||
if(s->avctx->frame_skip_threshold || s->avctx->frame_skip_factor){
|
||||
if(skip_check(s, s->input_picture[0], s->next_picture_ptr)){
|
||||
//av_log(NULL, AV_LOG_DEBUG, "skip %p %Ld\n", s->input_picture[0]->data[0], s->input_picture[0]->pts);
|
||||
|
||||
if(s->input_picture[0]->type == FF_BUFFER_TYPE_SHARED){
|
||||
for(i=0; i<4; i++)
|
||||
s->input_picture[0]->data[i]= NULL;
|
||||
s->input_picture[0]->type= 0;
|
||||
}else{
|
||||
assert( s->input_picture[0]->type==FF_BUFFER_TYPE_USER
|
||||
|| s->input_picture[0]->type==FF_BUFFER_TYPE_INTERNAL);
|
||||
|
||||
s->avctx->release_buffer(s->avctx, (AVFrame*)s->input_picture[0]);
|
||||
}
|
||||
|
||||
goto no_output_pic;
|
||||
}
|
||||
}
|
||||
|
||||
if(s->flags&CODEC_FLAG_PASS2){
|
||||
for(i=0; i<s->max_b_frames+1; i++){
|
||||
int pict_num= s->input_picture[0]->display_picture_number + i;
|
||||
@ -2116,7 +2173,7 @@ static void select_input_picture(MpegEncContext *s){
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
no_output_pic:
|
||||
if(s->reordered_input_picture[0]){
|
||||
s->reordered_input_picture[0]->reference= s->reordered_input_picture[0]->pict_type!=B_TYPE ? 3 : 0;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user