Mercurial > libavcodec.hg
view mpeg12enc.c @ 11816:7c2369ec6faa libavcodec
ARM: check struct offsets only when they are used
The offsets differ depending on configuration, so only check them when
they will actually be used. Presently, this is when NEON is enabled.
author | mru |
---|---|
date | Wed, 02 Jun 2010 22:05:25 +0000 |
parents | 7dd2a45249a9 |
children | b6cf19580e47 |
line wrap: on
line source
/* * MPEG1/2 encoder * Copyright (c) 2000,2001 Fabrice Bellard * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at> * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** * @file * MPEG1/2 encoder */ #include "avcodec.h" #include "dsputil.h" #include "mpegvideo.h" #include "mpeg12.h" #include "mpeg12data.h" #include "bytestream.h" static const uint8_t inv_non_linear_qscale[13] = { 0, 2, 4, 6, 8, 9,10,11,12,13,14,15,16, }; static const uint8_t svcd_scan_offset_placeholder[14] = { 0x10, 0x0E, 0x00, 0x80, 0x81, 0x00, 0x80, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; static void mpeg1_encode_block(MpegEncContext *s, DCTELEM *block, int component); static void mpeg1_encode_motion(MpegEncContext *s, int val, int f_or_b_code); // RAL: f_code parameter added static uint8_t mv_penalty[MAX_FCODE+1][MAX_MV*2+1]; static uint8_t fcode_tab[MAX_MV*2+1]; static uint8_t uni_mpeg1_ac_vlc_len [64*64*2]; static uint8_t uni_mpeg2_ac_vlc_len [64*64*2]; /* simple include everything table for dc, first byte is bits number next 3 are code*/ static uint32_t mpeg1_lum_dc_uni[512]; static uint32_t mpeg1_chr_dc_uni[512]; static uint8_t mpeg1_index_run[2][64]; static int8_t mpeg1_max_level[2][64]; static void init_uni_ac_vlc(RLTable *rl, uint8_t *uni_ac_vlc_len){ int i; for(i=0; i<128; i++){ int level= i-64; int run; for(run=0; run<64; run++){ int len, bits, code; int alevel= FFABS(level); int sign= (level>>31)&1; if (alevel > rl->max_level[0][run]) code= 111; /*rl->n*/ else code= rl->index_run[0][run] + alevel - 1; if (code < 111 /* rl->n */) { /* store the vlc & sign at once */ len= rl->table_vlc[code][1]+1; bits= (rl->table_vlc[code][0]<<1) + sign; } else { len= rl->table_vlc[111/*rl->n*/][1]+6; bits= rl->table_vlc[111/*rl->n*/][0]<<6; bits|= run; if (alevel < 128) { bits<<=8; len+=8; bits|= level & 0xff; } else { bits<<=16; len+=16; bits|= level & 0xff; if (level < 0) { bits|= 0x8001 + level + 255; } else { bits|= level & 0xffff; } } } uni_ac_vlc_len [UNI_AC_ENC_INDEX(run, i)]= len; } } } static int find_frame_rate_index(MpegEncContext *s){ int i; int64_t dmin= INT64_MAX; int64_t d; for(i=1;i<14;i++) { int64_t n0= 1001LL/ff_frame_rate_tab[i].den*ff_frame_rate_tab[i].num*s->avctx->time_base.num; int64_t n1= 1001LL*s->avctx->time_base.den; if(s->avctx->strict_std_compliance > FF_COMPLIANCE_INOFFICIAL && i>=9) break; d = FFABS(n0 - n1); if(d < dmin){ dmin=d; s->frame_rate_index= i; } } if(dmin) return -1; else return 0; } static av_cold int encode_init(AVCodecContext *avctx) { MpegEncContext *s = avctx->priv_data; if(MPV_encode_init(avctx) < 0) return -1; if(find_frame_rate_index(s) < 0){ if(s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL){ av_log(avctx, AV_LOG_ERROR, "MPEG1/2 does not support %d/%d fps\n", avctx->time_base.den, avctx->time_base.num); return -1; }else{ av_log(avctx, AV_LOG_INFO, "MPEG1/2 does not support %d/%d fps, there may be AV sync issues\n", avctx->time_base.den, avctx->time_base.num); } } if(avctx->profile == FF_PROFILE_UNKNOWN){ if(avctx->level != FF_LEVEL_UNKNOWN){ av_log(avctx, AV_LOG_ERROR, "Set profile and level\n"); return -1; } avctx->profile = s->chroma_format == CHROMA_420 ? 4 : 0; /* Main or 4:2:2 */ } if(avctx->level == FF_LEVEL_UNKNOWN){ if(avctx->profile == 0){ /* 4:2:2 */ if(avctx->width <= 720 && avctx->height <= 608) avctx->level = 5; /* Main */ else avctx->level = 2; /* High */ }else{ if(avctx->profile != 1 && s->chroma_format != CHROMA_420){ av_log(avctx, AV_LOG_ERROR, "Only High(1) and 4:2:2(0) profiles support 4:2:2 color sampling\n"); return -1; } if(avctx->width <= 720 && avctx->height <= 576) avctx->level = 8; /* Main */ else if(avctx->width <= 1440) avctx->level = 6; /* High 1440 */ else avctx->level = 4; /* High */ } } if((avctx->flags2 & CODEC_FLAG2_DROP_FRAME_TIMECODE) && s->frame_rate_index != 4){ av_log(avctx, AV_LOG_ERROR, "Drop frame time code only allowed with 1001/30000 fps\n"); return -1; } return 0; } static void put_header(MpegEncContext *s, int header) { align_put_bits(&s->pb); put_bits(&s->pb, 16, header>>16); put_sbits(&s->pb, 16, header); } /* put sequence header if needed */ static void mpeg1_encode_sequence_header(MpegEncContext *s) { unsigned int vbv_buffer_size; unsigned int fps, v; int i; uint64_t time_code; float best_aspect_error= 1E10; float aspect_ratio= av_q2d(s->avctx->sample_aspect_ratio); int constraint_parameter_flag; if(aspect_ratio==0.0) aspect_ratio= 1.0; //pixel aspect 1:1 (VGA) if (s->current_picture.key_frame) { AVRational framerate= ff_frame_rate_tab[s->frame_rate_index]; /* mpeg1 header repeated every gop */ put_header(s, SEQ_START_CODE); put_sbits(&s->pb, 12, s->width ); put_sbits(&s->pb, 12, s->height); for(i=1; i<15; i++){ float error= aspect_ratio; if(s->codec_id == CODEC_ID_MPEG1VIDEO || i <=1) error-= 1.0/ff_mpeg1_aspect[i]; else error-= av_q2d(ff_mpeg2_aspect[i])*s->height/s->width; error= FFABS(error); if(error < best_aspect_error){ best_aspect_error= error; s->aspect_ratio_info= i; } } put_bits(&s->pb, 4, s->aspect_ratio_info); put_bits(&s->pb, 4, s->frame_rate_index); if(s->avctx->rc_max_rate){ v = (s->avctx->rc_max_rate + 399) / 400; if (v > 0x3ffff && s->codec_id == CODEC_ID_MPEG1VIDEO) v = 0x3ffff; }else{ v= 0x3FFFF; } if(s->avctx->rc_buffer_size) vbv_buffer_size = s->avctx->rc_buffer_size; else /* VBV calculation: Scaled so that a VCD has the proper VBV size of 40 kilobytes */ vbv_buffer_size = (( 20 * s->bit_rate) / (1151929 / 2)) * 8 * 1024; vbv_buffer_size= (vbv_buffer_size + 16383) / 16384; put_sbits(&s->pb, 18, v); put_bits(&s->pb, 1, 1); /* marker */ put_sbits(&s->pb, 10, vbv_buffer_size); constraint_parameter_flag= s->width <= 768 && s->height <= 576 && s->mb_width * s->mb_height <= 396 && s->mb_width * s->mb_height * framerate.num <= framerate.den*396*25 && framerate.num <= framerate.den*30 && s->avctx->me_range && s->avctx->me_range < 128 && vbv_buffer_size <= 20 && v <= 1856000/400 && s->codec_id == CODEC_ID_MPEG1VIDEO; put_bits(&s->pb, 1, constraint_parameter_flag); ff_write_quant_matrix(&s->pb, s->avctx->intra_matrix); ff_write_quant_matrix(&s->pb, s->avctx->inter_matrix); if(s->codec_id == CODEC_ID_MPEG2VIDEO){ put_header(s, EXT_START_CODE); put_bits(&s->pb, 4, 1); //seq ext put_bits(&s->pb, 1, s->avctx->profile == 0); //escx 1 for 4:2:2 profile */ put_bits(&s->pb, 3, s->avctx->profile); //profile put_bits(&s->pb, 4, s->avctx->level); //level put_bits(&s->pb, 1, s->progressive_sequence); put_bits(&s->pb, 2, s->chroma_format); put_bits(&s->pb, 2, s->width >>12); put_bits(&s->pb, 2, s->height>>12); put_bits(&s->pb, 12, v>>18); //bitrate ext put_bits(&s->pb, 1, 1); //marker put_bits(&s->pb, 8, vbv_buffer_size >>10); //vbv buffer ext put_bits(&s->pb, 1, s->low_delay); put_bits(&s->pb, 2, 0); // frame_rate_ext_n put_bits(&s->pb, 5, 0); // frame_rate_ext_d } put_header(s, GOP_START_CODE); put_bits(&s->pb, 1, !!(s->avctx->flags2 & CODEC_FLAG2_DROP_FRAME_TIMECODE)); /* drop frame flag */ /* time code : we must convert from the real frame rate to a fake mpeg frame rate in case of low frame rate */ fps = (framerate.num + framerate.den/2)/ framerate.den; time_code = s->current_picture_ptr->coded_picture_number + s->avctx->timecode_frame_start; s->gop_picture_number = s->current_picture_ptr->coded_picture_number; if (s->avctx->flags2 & CODEC_FLAG2_DROP_FRAME_TIMECODE) { /* only works for NTSC 29.97 */ int d = time_code / 17982; int m = time_code % 17982; //if (m < 2) m += 2; /* not needed since -2,-1 / 1798 in C returns 0 */ time_code += 18 * d + 2 * ((m - 2) / 1798); } put_bits(&s->pb, 5, (uint32_t)((time_code / (fps * 3600)) % 24)); put_bits(&s->pb, 6, (uint32_t)((time_code / (fps * 60)) % 60)); put_bits(&s->pb, 1, 1); put_bits(&s->pb, 6, (uint32_t)((time_code / fps) % 60)); put_bits(&s->pb, 6, (uint32_t)((time_code % fps))); put_bits(&s->pb, 1, !!(s->flags & CODEC_FLAG_CLOSED_GOP)); put_bits(&s->pb, 1, 0); /* broken link */ } } static inline void encode_mb_skip_run(MpegEncContext *s, int run){ while (run >= 33) { put_bits(&s->pb, 11, 0x008); run -= 33; } put_bits(&s->pb, ff_mpeg12_mbAddrIncrTable[run][1], ff_mpeg12_mbAddrIncrTable[run][0]); } static av_always_inline void put_qscale(MpegEncContext *s) { if(s->q_scale_type){ assert(s->qscale>=1 && s->qscale <=12); put_bits(&s->pb, 5, inv_non_linear_qscale[s->qscale]); }else{ put_bits(&s->pb, 5, s->qscale); } } void ff_mpeg1_encode_slice_header(MpegEncContext *s){ if (s->height > 2800) { put_header(s, SLICE_MIN_START_CODE + (s->mb_y & 127)); put_bits(&s->pb, 3, s->mb_y >> 7); /* slice_vertical_position_extension */ } else { put_header(s, SLICE_MIN_START_CODE + s->mb_y); } put_qscale(s); put_bits(&s->pb, 1, 0); /* slice extra information */ } void mpeg1_encode_picture_header(MpegEncContext *s, int picture_number) { mpeg1_encode_sequence_header(s); /* mpeg1 picture header */ put_header(s, PICTURE_START_CODE); /* temporal reference */ // RAL: s->picture_number instead of s->fake_picture_number put_bits(&s->pb, 10, (s->picture_number - s->gop_picture_number) & 0x3ff); put_bits(&s->pb, 3, s->pict_type); s->vbv_delay_ptr= s->pb.buf + put_bits_count(&s->pb)/8; put_bits(&s->pb, 16, 0xFFFF); /* vbv_delay */ // RAL: Forward f_code also needed for B frames if (s->pict_type == FF_P_TYPE || s->pict_type == FF_B_TYPE) { put_bits(&s->pb, 1, 0); /* half pel coordinates */ if(s->codec_id == CODEC_ID_MPEG1VIDEO) put_bits(&s->pb, 3, s->f_code); /* forward_f_code */ else put_bits(&s->pb, 3, 7); /* forward_f_code */ } // RAL: Backward f_code necessary for B frames if (s->pict_type == FF_B_TYPE) { put_bits(&s->pb, 1, 0); /* half pel coordinates */ if(s->codec_id == CODEC_ID_MPEG1VIDEO) put_bits(&s->pb, 3, s->b_code); /* backward_f_code */ else put_bits(&s->pb, 3, 7); /* backward_f_code */ } put_bits(&s->pb, 1, 0); /* extra bit picture */ s->frame_pred_frame_dct = 1; if(s->codec_id == CODEC_ID_MPEG2VIDEO){ put_header(s, EXT_START_CODE); put_bits(&s->pb, 4, 8); //pic ext if (s->pict_type == FF_P_TYPE || s->pict_type == FF_B_TYPE) { put_bits(&s->pb, 4, s->f_code); put_bits(&s->pb, 4, s->f_code); }else{ put_bits(&s->pb, 8, 255); } if (s->pict_type == FF_B_TYPE) { put_bits(&s->pb, 4, s->b_code); put_bits(&s->pb, 4, s->b_code); }else{ put_bits(&s->pb, 8, 255); } put_bits(&s->pb, 2, s->intra_dc_precision); assert(s->picture_structure == PICT_FRAME); put_bits(&s->pb, 2, s->picture_structure); if (s->progressive_sequence) { put_bits(&s->pb, 1, 0); /* no repeat */ } else { put_bits(&s->pb, 1, s->current_picture_ptr->top_field_first); } /* XXX: optimize the generation of this flag with entropy measures */ s->frame_pred_frame_dct = s->progressive_sequence; put_bits(&s->pb, 1, s->frame_pred_frame_dct); put_bits(&s->pb, 1, s->concealment_motion_vectors); put_bits(&s->pb, 1, s->q_scale_type); put_bits(&s->pb, 1, s->intra_vlc_format); put_bits(&s->pb, 1, s->alternate_scan); put_bits(&s->pb, 1, s->repeat_first_field); s->progressive_frame = s->progressive_sequence; put_bits(&s->pb, 1, s->chroma_format == CHROMA_420 ? s->progressive_frame : 0); /* chroma_420_type */ put_bits(&s->pb, 1, s->progressive_frame); put_bits(&s->pb, 1, 0); //composite_display_flag } if(s->flags & CODEC_FLAG_SVCD_SCAN_OFFSET){ int i; put_header(s, USER_START_CODE); for(i=0; i<sizeof(svcd_scan_offset_placeholder); i++){ put_bits(&s->pb, 8, svcd_scan_offset_placeholder[i]); } } s->mb_y=0; ff_mpeg1_encode_slice_header(s); } static inline void put_mb_modes(MpegEncContext *s, int n, int bits, int has_mv, int field_motion) { put_bits(&s->pb, n, bits); if (!s->frame_pred_frame_dct) { if (has_mv) put_bits(&s->pb, 2, 2 - field_motion); /* motion_type: frame/field */ put_bits(&s->pb, 1, s->interlaced_dct); } } static av_always_inline void mpeg1_encode_mb_internal(MpegEncContext *s, DCTELEM block[6][64], int motion_x, int motion_y, int mb_block_count) { int i, cbp; const int mb_x = s->mb_x; const int mb_y = s->mb_y; const int first_mb= mb_x == s->resync_mb_x && mb_y == s->resync_mb_y; /* compute cbp */ cbp = 0; for(i=0;i<mb_block_count;i++) { if (s->block_last_index[i] >= 0) cbp |= 1 << (mb_block_count - 1 - i); } if (cbp == 0 && !first_mb && s->mv_type == MV_TYPE_16X16 && (mb_x != s->mb_width - 1 || (mb_y != s->mb_height - 1 && s->codec_id == CODEC_ID_MPEG1VIDEO)) && ((s->pict_type == FF_P_TYPE && (motion_x | motion_y) == 0) || (s->pict_type == FF_B_TYPE && s->mv_dir == s->last_mv_dir && (((s->mv_dir & MV_DIR_FORWARD) ? ((s->mv[0][0][0] - s->last_mv[0][0][0])|(s->mv[0][0][1] - s->last_mv[0][0][1])) : 0) | ((s->mv_dir & MV_DIR_BACKWARD) ? ((s->mv[1][0][0] - s->last_mv[1][0][0])|(s->mv[1][0][1] - s->last_mv[1][0][1])) : 0)) == 0))) { s->mb_skip_run++; s->qscale -= s->dquant; s->skip_count++; s->misc_bits++; s->last_bits++; if(s->pict_type == FF_P_TYPE){ s->last_mv[0][1][0]= s->last_mv[0][0][0]= s->last_mv[0][1][1]= s->last_mv[0][0][1]= 0; } } else { if(first_mb){ assert(s->mb_skip_run == 0); encode_mb_skip_run(s, s->mb_x); }else{ encode_mb_skip_run(s, s->mb_skip_run); } if (s->pict_type == FF_I_TYPE) { if(s->dquant && cbp){ put_mb_modes(s, 2, 1, 0, 0); /* macroblock_type : macroblock_quant = 1 */ put_qscale(s); }else{ put_mb_modes(s, 1, 1, 0, 0); /* macroblock_type : macroblock_quant = 0 */ s->qscale -= s->dquant; } s->misc_bits+= get_bits_diff(s); s->i_count++; } else if (s->mb_intra) { if(s->dquant && cbp){ put_mb_modes(s, 6, 0x01, 0, 0); put_qscale(s); }else{ put_mb_modes(s, 5, 0x03, 0, 0); s->qscale -= s->dquant; } s->misc_bits+= get_bits_diff(s); s->i_count++; memset(s->last_mv, 0, sizeof(s->last_mv)); } else if (s->pict_type == FF_P_TYPE) { if(s->mv_type == MV_TYPE_16X16){ if (cbp != 0) { if ((motion_x|motion_y) == 0) { if(s->dquant){ put_mb_modes(s, 5, 1, 0, 0); /* macroblock_pattern & quant */ put_qscale(s); }else{ put_mb_modes(s, 2, 1, 0, 0); /* macroblock_pattern only */ } s->misc_bits+= get_bits_diff(s); } else { if(s->dquant){ put_mb_modes(s, 5, 2, 1, 0); /* motion + cbp */ put_qscale(s); }else{ put_mb_modes(s, 1, 1, 1, 0); /* motion + cbp */ } s->misc_bits+= get_bits_diff(s); mpeg1_encode_motion(s, motion_x - s->last_mv[0][0][0], s->f_code); // RAL: f_code parameter added mpeg1_encode_motion(s, motion_y - s->last_mv[0][0][1], s->f_code); // RAL: f_code parameter added s->mv_bits+= get_bits_diff(s); } } else { put_bits(&s->pb, 3, 1); /* motion only */ if (!s->frame_pred_frame_dct) put_bits(&s->pb, 2, 2); /* motion_type: frame */ s->misc_bits+= get_bits_diff(s); mpeg1_encode_motion(s, motion_x - s->last_mv[0][0][0], s->f_code); // RAL: f_code parameter added mpeg1_encode_motion(s, motion_y - s->last_mv[0][0][1], s->f_code); // RAL: f_code parameter added s->qscale -= s->dquant; s->mv_bits+= get_bits_diff(s); } s->last_mv[0][1][0]= s->last_mv[0][0][0]= motion_x; s->last_mv[0][1][1]= s->last_mv[0][0][1]= motion_y; }else{ assert(!s->frame_pred_frame_dct && s->mv_type == MV_TYPE_FIELD); if (cbp) { if(s->dquant){ put_mb_modes(s, 5, 2, 1, 1); /* motion + cbp */ put_qscale(s); }else{ put_mb_modes(s, 1, 1, 1, 1); /* motion + cbp */ } } else { put_bits(&s->pb, 3, 1); /* motion only */ put_bits(&s->pb, 2, 1); /* motion_type: field */ s->qscale -= s->dquant; } s->misc_bits+= get_bits_diff(s); for(i=0; i<2; i++){ put_bits(&s->pb, 1, s->field_select[0][i]); mpeg1_encode_motion(s, s->mv[0][i][0] - s->last_mv[0][i][0] , s->f_code); mpeg1_encode_motion(s, s->mv[0][i][1] - (s->last_mv[0][i][1]>>1), s->f_code); s->last_mv[0][i][0]= s->mv[0][i][0]; s->last_mv[0][i][1]= 2*s->mv[0][i][1]; } s->mv_bits+= get_bits_diff(s); } if(cbp) { if (s->chroma_y_shift) { put_bits(&s->pb, ff_mpeg12_mbPatTable[cbp][1], ff_mpeg12_mbPatTable[cbp][0]); } else { put_bits(&s->pb, ff_mpeg12_mbPatTable[cbp>>2][1], ff_mpeg12_mbPatTable[cbp>>2][0]); put_sbits(&s->pb, 2, cbp); } } s->f_count++; } else{ if(s->mv_type == MV_TYPE_16X16){ if (cbp){ // With coded bloc pattern if (s->dquant) { if(s->mv_dir == MV_DIR_FORWARD) put_mb_modes(s, 6, 3, 1, 0); else put_mb_modes(s, 8-s->mv_dir, 2, 1, 0); put_qscale(s); } else { put_mb_modes(s, 5-s->mv_dir, 3, 1, 0); } }else{ // No coded bloc pattern put_bits(&s->pb, 5-s->mv_dir, 2); if (!s->frame_pred_frame_dct) put_bits(&s->pb, 2, 2); /* motion_type: frame */ s->qscale -= s->dquant; } s->misc_bits += get_bits_diff(s); if (s->mv_dir&MV_DIR_FORWARD){ mpeg1_encode_motion(s, s->mv[0][0][0] - s->last_mv[0][0][0], s->f_code); mpeg1_encode_motion(s, s->mv[0][0][1] - s->last_mv[0][0][1], s->f_code); s->last_mv[0][0][0]=s->last_mv[0][1][0]= s->mv[0][0][0]; s->last_mv[0][0][1]=s->last_mv[0][1][1]= s->mv[0][0][1]; s->f_count++; } if (s->mv_dir&MV_DIR_BACKWARD){ mpeg1_encode_motion(s, s->mv[1][0][0] - s->last_mv[1][0][0], s->b_code); mpeg1_encode_motion(s, s->mv[1][0][1] - s->last_mv[1][0][1], s->b_code); s->last_mv[1][0][0]=s->last_mv[1][1][0]= s->mv[1][0][0]; s->last_mv[1][0][1]=s->last_mv[1][1][1]= s->mv[1][0][1]; s->b_count++; } }else{ assert(s->mv_type == MV_TYPE_FIELD); assert(!s->frame_pred_frame_dct); if (cbp){ // With coded bloc pattern if (s->dquant) { if(s->mv_dir == MV_DIR_FORWARD) put_mb_modes(s, 6, 3, 1, 1); else put_mb_modes(s, 8-s->mv_dir, 2, 1, 1); put_qscale(s); } else { put_mb_modes(s, 5-s->mv_dir, 3, 1, 1); } }else{ // No coded bloc pattern put_bits(&s->pb, 5-s->mv_dir, 2); put_bits(&s->pb, 2, 1); /* motion_type: field */ s->qscale -= s->dquant; } s->misc_bits += get_bits_diff(s); if (s->mv_dir&MV_DIR_FORWARD){ for(i=0; i<2; i++){ put_bits(&s->pb, 1, s->field_select[0][i]); mpeg1_encode_motion(s, s->mv[0][i][0] - s->last_mv[0][i][0] , s->f_code); mpeg1_encode_motion(s, s->mv[0][i][1] - (s->last_mv[0][i][1]>>1), s->f_code); s->last_mv[0][i][0]= s->mv[0][i][0]; s->last_mv[0][i][1]= 2*s->mv[0][i][1]; } s->f_count++; } if (s->mv_dir&MV_DIR_BACKWARD){ for(i=0; i<2; i++){ put_bits(&s->pb, 1, s->field_select[1][i]); mpeg1_encode_motion(s, s->mv[1][i][0] - s->last_mv[1][i][0] , s->b_code); mpeg1_encode_motion(s, s->mv[1][i][1] - (s->last_mv[1][i][1]>>1), s->b_code); s->last_mv[1][i][0]= s->mv[1][i][0]; s->last_mv[1][i][1]= 2*s->mv[1][i][1]; } s->b_count++; } } s->mv_bits += get_bits_diff(s); if(cbp) { if (s->chroma_y_shift) { put_bits(&s->pb, ff_mpeg12_mbPatTable[cbp][1], ff_mpeg12_mbPatTable[cbp][0]); } else { put_bits(&s->pb, ff_mpeg12_mbPatTable[cbp>>2][1], ff_mpeg12_mbPatTable[cbp>>2][0]); put_sbits(&s->pb, 2, cbp); } } } for(i=0;i<mb_block_count;i++) { if (cbp & (1 << (mb_block_count - 1 - i))) { mpeg1_encode_block(s, block[i], i); } } s->mb_skip_run = 0; if(s->mb_intra) s->i_tex_bits+= get_bits_diff(s); else s->p_tex_bits+= get_bits_diff(s); } } void mpeg1_encode_mb(MpegEncContext *s, DCTELEM block[6][64], int motion_x, int motion_y) { if (s->chroma_format == CHROMA_420) mpeg1_encode_mb_internal(s, block, motion_x, motion_y, 6); else mpeg1_encode_mb_internal(s, block, motion_x, motion_y, 8); } // RAL: Parameter added: f_or_b_code static void mpeg1_encode_motion(MpegEncContext *s, int val, int f_or_b_code) { if (val == 0) { /* zero vector */ put_bits(&s->pb, ff_mpeg12_mbMotionVectorTable[0][1], ff_mpeg12_mbMotionVectorTable[0][0]); } else { int code, sign, bits; int bit_size = f_or_b_code - 1; int range = 1 << bit_size; /* modulo encoding */ int l= INT_BIT - 5 - bit_size; val= (val<<l)>>l; if (val >= 0) { val--; code = (val >> bit_size) + 1; bits = val & (range - 1); sign = 0; } else { val = -val; val--; code = (val >> bit_size) + 1; bits = val & (range - 1); sign = 1; } assert(code > 0 && code <= 16); put_bits(&s->pb, ff_mpeg12_mbMotionVectorTable[code][1], ff_mpeg12_mbMotionVectorTable[code][0]); put_bits(&s->pb, 1, sign); if (bit_size > 0) { put_bits(&s->pb, bit_size, bits); } } } void ff_mpeg1_encode_init(MpegEncContext *s) { static int done=0; ff_mpeg12_common_init(s); if(!done){ int f_code; int mv; int i; done=1; init_rl(&ff_rl_mpeg1, ff_mpeg12_static_rl_table_store[0]); init_rl(&ff_rl_mpeg2, ff_mpeg12_static_rl_table_store[1]); for(i=0; i<64; i++) { mpeg1_max_level[0][i]= ff_rl_mpeg1.max_level[0][i]; mpeg1_index_run[0][i]= ff_rl_mpeg1.index_run[0][i]; } init_uni_ac_vlc(&ff_rl_mpeg1, uni_mpeg1_ac_vlc_len); if(s->intra_vlc_format) init_uni_ac_vlc(&ff_rl_mpeg2, uni_mpeg2_ac_vlc_len); /* build unified dc encoding tables */ for(i=-255; i<256; i++) { int adiff, index; int bits, code; int diff=i; adiff = FFABS(diff); if(diff<0) diff--; index = av_log2(2*adiff); bits= ff_mpeg12_vlc_dc_lum_bits[index] + index; code= (ff_mpeg12_vlc_dc_lum_code[index]<<index) + (diff & ((1 << index) - 1)); mpeg1_lum_dc_uni[i+255]= bits + (code<<8); bits= ff_mpeg12_vlc_dc_chroma_bits[index] + index; code= (ff_mpeg12_vlc_dc_chroma_code[index]<<index) + (diff & ((1 << index) - 1)); mpeg1_chr_dc_uni[i+255]= bits + (code<<8); } for(f_code=1; f_code<=MAX_FCODE; f_code++){ for(mv=-MAX_MV; mv<=MAX_MV; mv++){ int len; if(mv==0) len= ff_mpeg12_mbMotionVectorTable[0][1]; else{ int val, bit_size, range, code; bit_size = f_code - 1; range = 1 << bit_size; val=mv; if (val < 0) val = -val; val--; code = (val >> bit_size) + 1; if(code<17){ len= ff_mpeg12_mbMotionVectorTable[code][1] + 1 + bit_size; }else{ len= ff_mpeg12_mbMotionVectorTable[16][1] + 2 + bit_size; } } mv_penalty[f_code][mv+MAX_MV]= len; } } for(f_code=MAX_FCODE; f_code>0; f_code--){ for(mv=-(8<<f_code); mv<(8<<f_code); mv++){ fcode_tab[mv+MAX_MV]= f_code; } } } s->me.mv_penalty= mv_penalty; s->fcode_tab= fcode_tab; if(s->codec_id == CODEC_ID_MPEG1VIDEO){ s->min_qcoeff=-255; s->max_qcoeff= 255; }else{ s->min_qcoeff=-2047; s->max_qcoeff= 2047; } if (s->intra_vlc_format) { s->intra_ac_vlc_length= s->intra_ac_vlc_last_length= uni_mpeg2_ac_vlc_len; } else { s->intra_ac_vlc_length= s->intra_ac_vlc_last_length= uni_mpeg1_ac_vlc_len; } s->inter_ac_vlc_length= s->inter_ac_vlc_last_length= uni_mpeg1_ac_vlc_len; } static inline void encode_dc(MpegEncContext *s, int diff, int component) { if(((unsigned) (diff+255)) >= 511){ int index; if(diff<0){ index= av_log2_16bit(-2*diff); diff--; }else{ index= av_log2_16bit(2*diff); } if (component == 0) { put_bits( &s->pb, ff_mpeg12_vlc_dc_lum_bits[index] + index, (ff_mpeg12_vlc_dc_lum_code[index]<<index) + (diff & ((1 << index) - 1))); }else{ put_bits( &s->pb, ff_mpeg12_vlc_dc_chroma_bits[index] + index, (ff_mpeg12_vlc_dc_chroma_code[index]<<index) + (diff & ((1 << index) - 1))); } }else{ if (component == 0) { put_bits( &s->pb, mpeg1_lum_dc_uni[diff+255]&0xFF, mpeg1_lum_dc_uni[diff+255]>>8); } else { put_bits( &s->pb, mpeg1_chr_dc_uni[diff+255]&0xFF, mpeg1_chr_dc_uni[diff+255]>>8); } } } static void mpeg1_encode_block(MpegEncContext *s, DCTELEM *block, int n) { int alevel, level, last_non_zero, dc, diff, i, j, run, last_index, sign; int code, component; const uint16_t (*table_vlc)[2] = ff_rl_mpeg1.table_vlc; last_index = s->block_last_index[n]; /* DC coef */ if (s->mb_intra) { component = (n <= 3 ? 0 : (n&1) + 1); dc = block[0]; /* overflow is impossible */ diff = dc - s->last_dc[component]; encode_dc(s, diff, component); s->last_dc[component] = dc; i = 1; if (s->intra_vlc_format) table_vlc = ff_rl_mpeg2.table_vlc; } else { /* encode the first coefficient : needs to be done here because it is handled slightly differently */ level = block[0]; if (abs(level) == 1) { code = ((uint32_t)level >> 31); /* the sign bit */ put_bits(&s->pb, 2, code | 0x02); i = 1; } else { i = 0; last_non_zero = -1; goto next_coef; } } /* now quantify & encode AC coefs */ last_non_zero = i - 1; for(;i<=last_index;i++) { j = s->intra_scantable.permutated[i]; level = block[j]; next_coef: #if 0 if (level != 0) dprintf(s->avctx, "level[%d]=%d\n", i, level); #endif /* encode using VLC */ if (level != 0) { run = i - last_non_zero - 1; alevel= level; MASK_ABS(sign, alevel) sign&=1; if (alevel <= mpeg1_max_level[0][run]){ code= mpeg1_index_run[0][run] + alevel - 1; /* store the vlc & sign at once */ put_bits(&s->pb, table_vlc[code][1]+1, (table_vlc[code][0]<<1) + sign); } else { /* escape seems to be pretty rare <5% so I do not optimize it */ put_bits(&s->pb, table_vlc[111][1], table_vlc[111][0]); /* escape: only clip in this case */ put_bits(&s->pb, 6, run); if(s->codec_id == CODEC_ID_MPEG1VIDEO){ if (alevel < 128) { put_sbits(&s->pb, 8, level); } else { if (level < 0) { put_bits(&s->pb, 16, 0x8001 + level + 255); } else { put_sbits(&s->pb, 16, level); } } }else{ put_sbits(&s->pb, 12, level); } } last_non_zero = i; } } /* end of block */ put_bits(&s->pb, table_vlc[112][1], table_vlc[112][0]); } AVCodec mpeg1video_encoder = { "mpeg1video", AVMEDIA_TYPE_VIDEO, CODEC_ID_MPEG1VIDEO, sizeof(MpegEncContext), encode_init, MPV_encode_picture, MPV_encode_end, .supported_framerates= ff_frame_rate_tab+1, .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE}, .capabilities= CODEC_CAP_DELAY, .long_name= NULL_IF_CONFIG_SMALL("MPEG-1 video"), }; AVCodec mpeg2video_encoder = { "mpeg2video", AVMEDIA_TYPE_VIDEO, CODEC_ID_MPEG2VIDEO, sizeof(MpegEncContext), encode_init, MPV_encode_picture, MPV_encode_end, .supported_framerates= ff_frame_rate_tab+1, .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_NONE}, .capabilities= CODEC_CAP_DELAY, .long_name= NULL_IF_CONFIG_SMALL("MPEG-2 video"), };