📄 mpegvideo.c
字号:
/* * The simplest mpeg encoder (well, it was the simplest!) * Copyright (c) 2000,2001 Fabrice Bellard. * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at> * * 4MV & hq & B-frame encoding stuff by 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 mpegvideo.c * The simplest mpeg encoder (well, it was the simplest!). */#include "avcodec.h"#include "dsputil.h"#include "mpegvideo.h"#include "mpegvideo_common.h"#include "mjpegenc.h"#include "msmpeg4.h"#include "faandct.h"#include "jzmedia.h"#undef memcpy#define memcpy uc_memcpy#ifdef USE_16M_SDRAMvoid (*ff_wmv2_add_mb_funcp)(MpegEncContext *s, DCTELEM block[6][64], uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr) = NULL;const uint8_t ff_mpeg1_dc_scale_table[128]={// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,};#endif//#undef NDEBUG//#include <assert.h>//static int idct_row_max;static void dct_unquantize_mpeg1_intra_c(MpegEncContext *s, DCTELEM *block, int n, int qscale);static void dct_unquantize_mpeg1_inter_c(MpegEncContext *s, DCTELEM *block, int n, int qscale);static void dct_unquantize_mpeg2_intra_c(MpegEncContext *s, DCTELEM *block, int n, int qscale);static void dct_unquantize_mpeg2_intra_bitexact(MpegEncContext *s, DCTELEM *block, int n, int qscale);static void dct_unquantize_mpeg2_inter_c(MpegEncContext *s, DCTELEM *block, int n, int qscale);static void dct_unquantize_h263_intra_c(MpegEncContext *s, DCTELEM *block, int n, int qscale);static void dct_unquantize_h263_inter_c(MpegEncContext *s, DCTELEM *block, int n, int qscale);static void draw_edges_c(uint8_t *buf, int wrap, int width, int height, int w);static void idct_put_mxu_c (uint8_t *dest, int line_size, DCTELEM *block);//static void idct_add_mxu_c (uint8_t *dest, int line_size, DCTELEM *block);#ifdef HAVE_XVMCextern int XVMC_field_start(MpegEncContext*s, AVCodecContext *avctx);extern void XVMC_field_end(MpegEncContext *s);extern void XVMC_decode_mb(MpegEncContext *s);#endifvoid (*draw_edges)(uint8_t *buf, int wrap, int width, int height, int w)= draw_edges_c;/* enable all paranoid tests for rounding, overflows, etc... *///#define PARANOID//#define DEBUGstatic const uint8_t ff_default_chroma_qscale_table[32]={// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31};void ff_init_scantable(uint8_t *permutation, ScanTable *st, const uint8_t *src_scantable){ int i; int end; st->scantable= src_scantable; for(i=0; i<64; i++){ int j; j = src_scantable[i]; st->permutated[i] = permutation[j];#ifdef ARCH_POWERPC st->inverse[j] = i;#endif } end=-1; for(i=0; i<64; i++){ int j; j = st->permutated[i]; if(j>end) end=j; st->raster_end[i]= end; }}const uint8_t *ff_find_start_code(const uint8_t * restrict p, const uint8_t *end, uint32_t * restrict state){ int i; assert(p<=end); if(p>=end) return end; for(i=0; i<3; i++){ uint32_t tmp= *state << 8; *state= tmp + *(p++); if(tmp == 0x100 || p==end) return p; } while(p<end){ if (p[-1] > 1 ) p+= 3; else if(p[-2] ) p+= 2; else if(p[-3]|(p[-1]-1)) p++; else{ p++; break; } } p= FFMIN(p, end)-4; *state= AV_RB32(p); return p+4;}/* init common dct for both encoder and decoder */static int DCT_common_init(MpegEncContext *s){ s->dct_unquantize_h263_intra = dct_unquantize_h263_intra_c; s->dct_unquantize_h263_inter = dct_unquantize_h263_inter_c; s->dct_unquantize_mpeg1_intra = dct_unquantize_mpeg1_intra_c; s->dct_unquantize_mpeg1_inter = dct_unquantize_mpeg1_inter_c; s->dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_c; if(s->flags & CODEC_FLAG_BITEXACT) s->dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_bitexact; s->dct_unquantize_mpeg2_inter = dct_unquantize_mpeg2_inter_c;#if defined(HAVE_MMX) MPV_common_init_mmx(s);#elif defined(ARCH_ALPHA) MPV_common_init_axp(s);#elif defined(HAVE_MLIB) MPV_common_init_mlib(s);#elif defined(HAVE_MMI) MPV_common_init_mmi(s);#elif defined(ARCH_ARMV4L) MPV_common_init_armv4l(s);#elif defined(HAVE_ALTIVEC) MPV_common_init_altivec(s);#elif defined(ARCH_BFIN) MPV_common_init_bfin(s);#endif /* load & permutate scantables note: only wmv uses different ones */ if(s->alternate_scan){ ff_init_scantable(s->dsp.idct_permutation, &s->inter_scantable , ff_alternate_vertical_scan); ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable , ff_alternate_vertical_scan); }else{ ff_init_scantable(s->dsp.idct_permutation, &s->inter_scantable , ff_zigzag_direct); ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable , ff_zigzag_direct); } ff_init_scantable(s->dsp.idct_permutation, &s->intra_h_scantable, ff_alternate_horizontal_scan); ff_init_scantable(s->dsp.idct_permutation, &s->intra_v_scantable, ff_alternate_vertical_scan); return 0;}void copy_picture(Picture *dst, Picture *src){ *dst = *src; dst->type= FF_BUFFER_TYPE_COPY;}/** * allocates a Picture * The pixels are allocated/set by calling get_buffer() if shared=0 */int alloc_picture(MpegEncContext *s, Picture *pic, int shared){ const int big_mb_num= s->mb_stride*(s->mb_height+1) + 1; //the +1 is needed so memset(,,stride*height) does not sig11 const int mb_array_size= s->mb_stride*s->mb_height; const int b8_array_size= s->b8_stride*s->mb_height*2; const int b4_array_size= s->b4_stride*s->mb_height*4; int i; int r= -1; if(shared){ assert(pic->data[0]); assert(pic->type == 0 || pic->type == FF_BUFFER_TYPE_SHARED); pic->type= FF_BUFFER_TYPE_SHARED; }else{ assert(!pic->data[0]); r= s->avctx->get_buffer(s->avctx, (AVFrame*)pic); if(r<0 || !pic->age || !pic->type || !pic->data[0]){ av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed (%d %d %d %p)\n", r, pic->age, pic->type, pic->data[0]); return -1; } if(s->linesize && (s->linesize != pic->linesize[0] || s->uvlinesize != pic->linesize[1])){ av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed (stride changed)\n"); s->avctx->release_buffer(s->avctx, (AVFrame*)pic); return -1; } if(pic->linesize[1] != pic->linesize[2]){ av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed (uv stride mismatch)\n"); s->avctx->release_buffer(s->avctx, (AVFrame*)pic); return -1; } s->linesize = pic->linesize[0]; s->uvlinesize= pic->linesize[1]; } if(pic->qscale_table==NULL){ if (s->encoding) { CHECKED_ALLOCZ(pic->mb_var , mb_array_size * sizeof(int16_t)) CHECKED_ALLOCZ(pic->mc_mb_var, mb_array_size * sizeof(int16_t)) CHECKED_ALLOCZ(pic->mb_mean , mb_array_size * sizeof(int8_t)) } CHECKED_ALLOCZ(pic->mbskip_table , mb_array_size * sizeof(uint8_t)+2) //the +2 is for the slice end check CHECKED_ALLOCZ(pic->qscale_table , mb_array_size * sizeof(uint8_t)) CHECKED_ALLOCZ(pic->mb_type_base , big_mb_num * sizeof(uint32_t)) pic->mb_type= pic->mb_type_base + s->mb_stride+1; if(s->out_format == FMT_H264){ for(i=0; i<2; i++){ CHECKED_ALLOCZ(pic->motion_val_base[i], 2 * (b4_array_size+4) * sizeof(int16_t)) pic->motion_val[i]= pic->motion_val_base[i]+4; CHECKED_ALLOCZ(pic->ref_index[i], b8_array_size * sizeof(uint8_t)) } pic->motion_subsample_log2= 2; }else if(s->out_format == FMT_H263 || s->encoding || (s->avctx->debug&FF_DEBUG_MV) || (s->avctx->debug_mv)){ for(i=0; i<2; i++){ CHECKED_ALLOCZ(pic->motion_val_base[i], 2 * (b8_array_size+4) * sizeof(int16_t)) pic->motion_val[i]= pic->motion_val_base[i]+4; CHECKED_ALLOCZ(pic->ref_index[i], b8_array_size * sizeof(uint8_t)) } pic->motion_subsample_log2= 3; } if(s->avctx->debug&FF_DEBUG_DCT_COEFF) { CHECKED_ALLOCZ(pic->dct_coeff, 64 * mb_array_size * sizeof(DCTELEM)*6) } pic->qstride= s->mb_stride; CHECKED_ALLOCZ(pic->pan_scan , 1 * sizeof(AVPanScan)) } /* It might be nicer if the application would keep track of these * but it would require an API change. */ memmove(s->prev_pict_types+1, s->prev_pict_types, PREV_PICT_TYPES_BUFFER_SIZE-1); s->prev_pict_types[0]= s->pict_type; if(pic->age < PREV_PICT_TYPES_BUFFER_SIZE && s->prev_pict_types[pic->age] == B_TYPE) pic->age= INT_MAX; // Skipped MBs in B-frames are quite rare in MPEG-1/2 and it is a bit tricky to skip them anyway. return 0;fail: //for the CHECKED_ALLOCZ macro if(r>=0) s->avctx->release_buffer(s->avctx, (AVFrame*)pic); return -1;}/** * deallocates a picture */static void free_picture(MpegEncContext *s, Picture *pic){ int i; if(pic->data[0] && pic->type!=FF_BUFFER_TYPE_SHARED){ s->avctx->release_buffer(s->avctx, (AVFrame*)pic); } av_freep(&pic->mb_var); av_freep(&pic->mc_mb_var); av_freep(&pic->mb_mean); av_freep(&pic->mbskip_table); av_freep(&pic->qscale_table); av_freep(&pic->mb_type_base); av_freep(&pic->dct_coeff); av_freep(&pic->pan_scan); pic->mb_type= NULL; for(i=0; i<2; i++){ av_freep(&pic->motion_val_base[i]); av_freep(&pic->ref_index[i]); } if(pic->type == FF_BUFFER_TYPE_SHARED){ for(i=0; i<4; i++){ pic->base[i]= pic->data[i]= NULL; } pic->type= 0; }}static int init_duplicate_context(MpegEncContext *s, MpegEncContext *base){ int i; // edge emu needs blocksize + filter length - 1 (=17x17 for halfpel / 21x21 for h264) CHECKED_ALLOCZ(s->allocated_edge_emu_buffer, (s->width+64)*2*21*2); //(width + edge + align)*interlaced*MBsize*tolerance s->edge_emu_buffer= s->allocated_edge_emu_buffer + (s->width+64)*2*21; //FIXME should be linesize instead of s->width*2 but that is not known before get_buffer() CHECKED_ALLOCZ(s->me.scratchpad, (s->width+64)*4*16*2*sizeof(uint8_t)) s->rd_scratchpad= s->me.scratchpad; s->b_scratchpad= s->me.scratchpad; s->obmc_scratchpad= s->me.scratchpad + 16; if (s->encoding) { CHECKED_ALLOCZ(s->me.map , ME_MAP_SIZE*sizeof(uint32_t)) CHECKED_ALLOCZ(s->me.score_map, ME_MAP_SIZE*sizeof(uint32_t)) if(s->avctx->noise_reduction){ CHECKED_ALLOCZ(s->dct_error_sum, 2 * 64 * sizeof(int)) } } CHECKED_ALLOCZ(s->blocks, 64*12*2 * sizeof(DCTELEM)) s->block= s->blocks[0]; for(i=0;i<12;i++){ s->pblocks[i] = (short *)(&s->block[i]); } return 0;fail:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -