📄 mpegvideo_enc.c
字号:
if(/*s->picture_in_gop_number >= s->gop_size ||*/ s->next_picture_ptr==NULL || s->intra_only){ s->reordered_input_picture[0]= s->input_picture[0]; s->reordered_input_picture[0]->pict_type= FF_I_TYPE; 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(s->picture_in_gop_number < s->gop_size && skip_check(s, s->input_picture[0], s->next_picture_ptr)){ //FIXME check that te gop check above is +-1 correct//av_log(NULL, AV_LOG_DEBUG, "skip %p %"PRId64"\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]); } emms_c(); ff_vbv_update(s, 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; if(pict_num >= s->rc_context.num_entries) break; if(!s->input_picture[i]){ s->rc_context.entry[pict_num-1].new_pict_type = FF_P_TYPE; break; } s->input_picture[i]->pict_type= s->rc_context.entry[pict_num].new_pict_type; } } if(s->avctx->b_frame_strategy==0){ b_frames= s->max_b_frames; while(b_frames && !s->input_picture[b_frames]) b_frames--; }else if(s->avctx->b_frame_strategy==1){ for(i=1; i<s->max_b_frames+1; i++){ if(s->input_picture[i] && s->input_picture[i]->b_frame_score==0){ s->input_picture[i]->b_frame_score= get_intra_count(s, s->input_picture[i ]->data[0], s->input_picture[i-1]->data[0], s->linesize) + 1; } } for(i=0; i<s->max_b_frames+1; i++){ if(s->input_picture[i]==NULL || s->input_picture[i]->b_frame_score - 1 > s->mb_num/s->avctx->b_sensitivity) break; } b_frames= FFMAX(0, i-1); /* reset scores */ for(i=0; i<b_frames+1; i++){ s->input_picture[i]->b_frame_score=0; } }else if(s->avctx->b_frame_strategy==2){ b_frames= estimate_best_b_count(s); }else{ av_log(s->avctx, AV_LOG_ERROR, "illegal b frame strategy\n"); b_frames=0; } emms_c();//static int b_count=0;//b_count+= b_frames;//av_log(s->avctx, AV_LOG_DEBUG, "b_frames: %d\n", b_count); for(i= b_frames - 1; i>=0; i--){ int type= s->input_picture[i]->pict_type; if(type && type != FF_B_TYPE) b_frames= i; } if(s->input_picture[b_frames]->pict_type == FF_B_TYPE && b_frames == s->max_b_frames){ av_log(s->avctx, AV_LOG_ERROR, "warning, too many b frames in a row\n"); } if(s->picture_in_gop_number + b_frames >= s->gop_size){ if((s->flags2 & CODEC_FLAG2_STRICT_GOP) && s->gop_size > s->picture_in_gop_number){ b_frames= s->gop_size - s->picture_in_gop_number - 1; }else{ if(s->flags & CODEC_FLAG_CLOSED_GOP) b_frames=0; s->input_picture[b_frames]->pict_type= FF_I_TYPE; } } if( (s->flags & CODEC_FLAG_CLOSED_GOP) && b_frames && s->input_picture[b_frames]->pict_type== FF_I_TYPE) b_frames--; s->reordered_input_picture[0]= s->input_picture[b_frames]; if(s->reordered_input_picture[0]->pict_type != FF_I_TYPE) s->reordered_input_picture[0]->pict_type= FF_P_TYPE; s->reordered_input_picture[0]->coded_picture_number= s->coded_picture_number++; for(i=0; i<b_frames; i++){ s->reordered_input_picture[i+1]= s->input_picture[i]; s->reordered_input_picture[i+1]->pict_type= FF_B_TYPE; s->reordered_input_picture[i+1]->coded_picture_number= s->coded_picture_number++; } } }no_output_pic: if(s->reordered_input_picture[0]){ s->reordered_input_picture[0]->reference= s->reordered_input_picture[0]->pict_type!=FF_B_TYPE ? 3 : 0; copy_picture(&s->new_picture, s->reordered_input_picture[0]); if(s->reordered_input_picture[0]->type == FF_BUFFER_TYPE_SHARED || s->avctx->rc_buffer_size){ // input is a shared pix, so we can't modifiy it -> alloc a new one & ensure that the shared one is reuseable int i= ff_find_unused_picture(s, 0); Picture *pic= &s->picture[i]; pic->reference = s->reordered_input_picture[0]->reference; alloc_picture(s, pic, 0); /* mark us unused / free shared pic */ if(s->reordered_input_picture[0]->type == FF_BUFFER_TYPE_INTERNAL) s->avctx->release_buffer(s->avctx, (AVFrame*)s->reordered_input_picture[0]); for(i=0; i<4; i++) s->reordered_input_picture[0]->data[i]= NULL; s->reordered_input_picture[0]->type= 0; copy_picture_attributes(s, (AVFrame*)pic, (AVFrame*)s->reordered_input_picture[0]); s->current_picture_ptr= pic; }else{ // input is not a shared pix -> reuse buffer for current_pix assert( s->reordered_input_picture[0]->type==FF_BUFFER_TYPE_USER || s->reordered_input_picture[0]->type==FF_BUFFER_TYPE_INTERNAL); s->current_picture_ptr= s->reordered_input_picture[0]; for(i=0; i<4; i++){ s->new_picture.data[i]+= INPLACE_OFFSET; } } copy_picture(&s->current_picture, s->current_picture_ptr); s->picture_number= s->new_picture.display_picture_number;//printf("dpn:%d\n", s->picture_number); }else{ memset(&s->new_picture, 0, sizeof(Picture)); }}int MPV_encode_picture(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){ MpegEncContext *s = avctx->priv_data; AVFrame *pic_arg = data; int i, stuffing_count; for(i=0; i<avctx->thread_count; i++){ int start_y= s->thread_context[i]->start_mb_y; int end_y= s->thread_context[i]-> end_mb_y; int h= s->mb_height; uint8_t *start= buf + (size_t)(((int64_t) buf_size)*start_y/h); uint8_t *end = buf + (size_t)(((int64_t) buf_size)* end_y/h); init_put_bits(&s->thread_context[i]->pb, start, end - start); } s->picture_in_gop_number++; if(load_input_picture(s, pic_arg) < 0) return -1; select_input_picture(s); /* output? */ if(s->new_picture.data[0]){ s->pict_type= s->new_picture.pict_type;//emms_c();//printf("qs:%f %f %d\n", s->new_picture.quality, s->current_picture.quality, s->qscale); MPV_frame_start(s, avctx);vbv_retry: if (encode_picture(s, s->picture_number) < 0) return -1; avctx->real_pict_num = s->picture_number; avctx->header_bits = s->header_bits; avctx->mv_bits = s->mv_bits; avctx->misc_bits = s->misc_bits; avctx->i_tex_bits = s->i_tex_bits; avctx->p_tex_bits = s->p_tex_bits; avctx->i_count = s->i_count; avctx->p_count = s->mb_num - s->i_count - s->skip_count; //FIXME f/b_count in avctx avctx->skip_count = s->skip_count; MPV_frame_end(s); if (ENABLE_MJPEG_ENCODER && s->out_format == FMT_MJPEG) ff_mjpeg_encode_picture_trailer(s); if(avctx->rc_buffer_size){ RateControlContext *rcc= &s->rc_context; int max_size= rcc->buffer_index/3; if(put_bits_count(&s->pb) > max_size && s->lambda < s->avctx->lmax){ s->next_lambda= FFMAX(s->lambda+1, s->lambda*(s->qscale+1) / s->qscale); if(s->adaptive_quant){ int i; for(i=0; i<s->mb_height*s->mb_stride; i++) s->lambda_table[i]= FFMAX(s->lambda_table[i]+1, s->lambda_table[i]*(s->qscale+1) / s->qscale); } s->mb_skipped = 0; //done in MPV_frame_start() if(s->pict_type==FF_P_TYPE){ //done in encode_picture() so we must undo it if(s->flipflop_rounding || s->codec_id == CODEC_ID_H263P || s->codec_id == CODEC_ID_MPEG4) s->no_rounding ^= 1; } if(s->pict_type!=FF_B_TYPE){ s->time_base= s->last_time_base; s->last_non_b_time= s->time - s->pp_time; }// av_log(NULL, AV_LOG_ERROR, "R:%d ", s->next_lambda); for(i=0; i<avctx->thread_count; i++){ PutBitContext *pb= &s->thread_context[i]->pb; init_put_bits(pb, pb->buf, pb->buf_end - pb->buf); } goto vbv_retry; } assert(s->avctx->rc_max_rate); } if(s->flags&CODEC_FLAG_PASS1) ff_write_pass1_stats(s); for(i=0; i<4; i++){ s->current_picture_ptr->error[i]= s->current_picture.error[i]; avctx->error[i] += s->current_picture_ptr->error[i]; } if(s->flags&CODEC_FLAG_PASS1) assert(avctx->header_bits + avctx->mv_bits + avctx->misc_bits + avctx->i_tex_bits + avctx->p_tex_bits == put_bits_count(&s->pb)); flush_put_bits(&s->pb); s->frame_bits = put_bits_count(&s->pb); stuffing_count= ff_vbv_update(s, s->frame_bits); if(stuffing_count){ if(s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < stuffing_count + 50){ av_log(s->avctx, AV_LOG_ERROR, "stuffing too large\n"); return -1; } switch(s->codec_id){ case CODEC_ID_MPEG1VIDEO: case CODEC_ID_MPEG2VIDEO: while(stuffing_count--){ put_bits(&s->pb, 8, 0); } break; case CODEC_ID_MPEG4: put_bits(&s->pb, 16, 0); put_bits(&s->pb, 16, 0x1C3); stuffing_count -= 4; while(stuffing_count--){ put_bits(&s->pb, 8, 0xFF); } break; default: av_log(s->avctx, AV_LOG_ERROR, "vbv buffer overflow\n"); } flush_put_bits(&s->pb); s->frame_bits = put_bits_count(&s->pb); } /* update mpeg1/2 vbv_delay for CBR */ if(s->avctx->rc_max_rate && s->avctx->rc_min_rate == s->avctx->rc_max_rate && s->out_format == FMT_MPEG1 && 90000LL * (avctx->rc_buffer_size-1) <= s->avctx->rc_max_rate*0xFFFFLL){ int vbv_delay; assert(s->repeat_first_field==0); vbv_delay= lrintf(90000 * s->rc_context.buffer_index / s->avctx->rc_max_rate); assert(vbv_delay < 0xFFFF); s->vbv_delay_ptr[0] &= 0xF8; s->vbv_delay_ptr[0] |= vbv_delay>>13; s->vbv_delay_ptr[1] = vbv_delay>>5; s->vbv_delay_ptr[2] &= 0x07; s->vbv_delay_ptr[2] |= vbv_delay<<3; } s->total_bits += s->frame_bits; avctx->frame_bits = s->frame_bits; }else{ assert((pbBufPtr(&s->pb) == s->pb.buf)); s->frame_bits=0; } assert((s->frame_bits&7)==0); return s->frame_bits/8;}static inline void dct_single_coeff_elimination(MpegEncContext *s, int n, int threshold){ static const char tab[64]= {3,2,2,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0}; int score=0; int run=0; int i; DCTELEM *block= s->block[n]; const int last_index= s->block_last_index[n]; int skip_dc; if(threshold<0){ skip_dc=0; threshold= -threshold; }else skip_dc=1; /* Are all we could set to zero already zero? */ if(last_index<=skip_dc - 1) return; for(i=0; i<=last_index; i++){ const int j = s->intra_scantable.permutated[i]; const int level = FFABS(block[j]); if(level==1){ if(skip_dc && i==0) continue; score+= tab[run]; run=0; }else if(level>1){ return; }else{ run++; } } if(score >= threshold) return; for(i=skip_dc; i<=last_index; i++){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -