⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fame_syntax_mpeg1.c

📁 一个很好用的MPEG1/4的开源编码器
💻 C
📖 第 1 页 / 共 2 页
字号:
  mv[k].dy = syntax_mpeg1->mv_pred.dy;}static void mpeg1_block_intra(fame_syntax_t *syntax, short *block, fame_vlc_t const *table, short *pred){  fame_syntax_mpeg1_t *syntax_mpeg1 = FAME_SYNTAX_MPEG1(syntax);  short v;  fame_bitbuffer_t * const buffer = &syntax_mpeg1->buffer;  unsigned char * data = buffer->data;  unsigned long shift = buffer->shift;  /* encode DC coefficient */  v = block[0] - *pred;  v = mpeg1_table_clip[v];  *pred += v;  fast_bitbuffer_write(data, shift, table[v+255].code, table[v+255].length);  /* encode AC coefficients */#if defined(HAS_BSWAP)  {    unsigned long dummy1, dummy2;    /* Note:        movsx mpeg1_table_clip+4096(, %%eax ,2), %%eax       has been replaced by        movw mpeg1_table_clip+4096(, %%eax ,2), %%ax        movsx %%ax, %%eax       because the first instruction failed on a PIII!! (wrong sign extension)       whereas it worked well on my P75 :)    */    /* Ok, a bit of explanations for a couple of tricks:         The DC value of block is already coded and stored in v so we can use it to store something.	 We add one index to the zigzag table so that after coding block[63] we go to index 0. There	 we need to escape the zero counting loop (1), what we ensure by putting a non-zero value in	 the DC coefficient. Then we can test for index == 0 to exit.	 Now this non-zero value is a bit special :)	 In order to have one more 'half' register, we store sp value (16 less significant bit of the	 32 bit register esp) *plus one* in the DC coefficient. Since the stack is aligned at an 	 address multiple of 4 bytes (at least), we are sure that sp != 0xffff and thus sp+1 will	 never be zero. We then retrieve sp at the end for it is needed by 'pop' instructions.     */    /* TODO : echange the role of edx and esp */    __asm__ __volatile__ ("pushl %%ebx\n"             /* save ebx            */			  "pushl %%ebp\n"             /* save stack pointer  */			  "inc %%sp\n"                /* make sure sp != 0   */			  "movw %%sp, (%%edx)\n"      /* store sp+1 in DC ;) */			  "movl %%esi, %%ebp\n"       /* ebp = vlc_table     */			  "xorl %%eax, %%eax\n"       /* eax = 0             */			  "movl $" ASMSYM "mpeg1_zigzag_table+1, %%esi\n" /*esi = zigzag*/			  "lea 1(%%esi), %%ebx\n"     /* ebx = zigzag_table+1*/			  "neg %%ebx\n"               /* ebx = -(esi+1)      */			  ".p2align 4,,7\n"           /* align for jump      */			  "0: xorw %%sp, %%sp\n"      /* sp = 0              */			  "1: movb (%%esi), %%al\n"   /* eax = index in block*/			  "incl %%esi\n"              /* (faster than lodsb) */			  "addw (%%edx, %%eax, 2), %%sp\n" /* sp = unzig     */			  "jz 1b\n"                   /* coeff == 0 then loop*/			  "orl %%eax, %%eax\n"        /* index == 0 then quit*/			  "jz 2f\n"                   /* (faster than jcxz)  */			  "movsx %%sp, %%eax\n"       /* extend sign         */			  "movw " ASMSYM "mpeg1_table_clip_data+4096(, %%eax ,2), %%ax\n" /*clip*/			  "movsx %%ax, %%eax\n"       /* extend sign         */			  "addl %%esi, %%ebx\n"       /* ebx = run           */			  "shll $7, %%eax\n"          /* eax *= 128(indexing)*/			  "lea (%%eax, %%ebx, 2), %%eax\n" /*eax = 2 * offset*/			  "lea (%%ebp, %%eax, 4), %%ebx\n" /* ebx = &vlc     */			  "movl (%%ebx), %%eax\n"     /* eax = code          */			  "addl 4(%%ebx), %%ecx\n"    /* ecx = shift+=length */			  "xorl %%ebx, %%ebx\n"       /* ebx = 0             */			  "shrd %%cl, %%eax, %%ebx\n" /* adjust code to fit  */			  "shr %%cl, %%eax\n"         /* adjust code to fit  */			  "bswap %%eax\n"      /* reverse byte order of code */			  "bswap %%ebx\n"      /* reverse byte order of code */			  "or %%eax, (%%edi)\n"       /* put first 32 bits   */			  "movl %%ecx, %%eax\n"       /* eax = shift + length*/			  "shrl $5, %%eax\n"          /* get dword increment */			  "andl $31, %%ecx\n"         /* mask shift          */			  "lea   (%%edi, %%eax, 4), %%edi\n"/* data+=(ecx>32)*/			  "orl %%ebx, (%%edi)\n"      /* put last 32 bits    */			  "xorl %%eax, %%eax\n"       /* eax = 0             */			  "lea 1(%%esi), %%ebx\n"     /* ebx = esi + 1 (last)*/			  "neg %%ebx\n"               /* ebx = -(esi + 1)    */			  "jmp 0b\n"                  /* loop                */			  "2:\n"			  "movw (%%edx), %%sp\n"      /* retrieve sp+1       */			  "dec %%sp\n"                /* restore esp */			  "popl %%ebp\n"              /* reload stack pointer*/			  "popl %%ebx\n"              /* reload ebx          */			  : "=c"(shift),			    "=a"(dummy1),			    "=d"(block),			    "=D"(data),			    "=S"(dummy2)			  : "d"(block),			    "c"(shift),			    "D"(data),                            "S"(syntax_mpeg1->vlc_table)			  : "memory");    block[0] = v; /* restore DC value */  }#else  {    short i;    unsigned long last;    fame_vlc_t const *vlc;    last = 1;    for(i = 1; i < 64; i++)    {      v = block[mpeg1_zigzag_table[i]];      /* count zeroes */      if(v != 0) {	/* write code */	vlc = syntax_mpeg1->vlc_table + (mpeg1_table_clip[v] << 6) + i - last;	fast_bitbuffer_write(data, shift, vlc->code, vlc->length);	/* reset zeroes count */	last = i+1;      }    }  }#endif /* HAS_BSWAP */  /* mark end of block */  fast_bitbuffer_write(data, shift, 2, 2);  buffer->data = data;  buffer->shift = shift;}static int mpeg1_write_intra_mb(fame_syntax_t *syntax,                                int mb_x,                                int mb_y,                                short *blocks[6],                                unsigned char *bab,                                unsigned char *bab_map,                                fame_bab_t bab_type,                                int dquant,                                unsigned char pattern){  fame_syntax_mpeg1_t *syntax_mpeg1 = FAME_SYNTAX_MPEG1(syntax);  int incr;  incr = mb_y * syntax_mpeg1->mb_width + mb_x - syntax_mpeg1->prev_mb_addr;  syntax_mpeg1->prev_mb_addr += incr;  while(incr > 33) {    /* address escape */    bitbuffer_write(&syntax_mpeg1->buffer, mb_addr_inc[33].code, mb_addr_inc[33].length);    incr -= 33;  }  /* address increment */  bitbuffer_write(&syntax_mpeg1->buffer, mb_addr_inc[incr-1].code, mb_addr_inc[incr-1].length);   switch(syntax_mpeg1->frame_type) {    case frame_type_I:      if(dquant) {	bitbuffer_write(&syntax_mpeg1->buffer, 1, 2); /* intra and dquant*/      } else {	bitbuffer_write(&syntax_mpeg1->buffer, 1, 1); /* intra coded */      }    break;    case frame_type_P:      if(dquant) {	bitbuffer_write(&syntax_mpeg1->buffer, 1, 6); /* intra and dquant */      } else {	bitbuffer_write(&syntax_mpeg1->buffer, 3, 5); /* intra coded */      }    break;  }  /* dquant */  if(dquant) {    syntax_mpeg1->qscale += dquant;    bitbuffer_write(&syntax_mpeg1->buffer, syntax_mpeg1->qscale, 5);  }  mpeg1_block_intra(syntax, blocks[0], encode_ydc_table, &syntax_mpeg1->y_dc_pred);  mpeg1_block_intra(syntax, blocks[1], encode_ydc_table, &syntax_mpeg1->y_dc_pred);  mpeg1_block_intra(syntax, blocks[2], encode_ydc_table, &syntax_mpeg1->y_dc_pred);  mpeg1_block_intra(syntax, blocks[3], encode_ydc_table, &syntax_mpeg1->y_dc_pred);  mpeg1_block_intra(syntax, blocks[4], encode_cdc_table, &syntax_mpeg1->cb_dc_pred);  mpeg1_block_intra(syntax, blocks[5], encode_cdc_table, &syntax_mpeg1->cr_dc_pred);  /* reset the motion predictors */  syntax_mpeg1->mv_pred.dx = syntax_mpeg1->mv_pred.dy = 0;  return(0);}static void mpeg1_block_inter(fame_syntax_t *syntax, short *block){  fame_syntax_mpeg1_t *syntax_mpeg1 = FAME_SYNTAX_MPEG1(syntax);  short i, v;  unsigned long last;  fame_vlc_t const *vlc;  fame_bitbuffer_t * const buffer = &syntax_mpeg1->buffer;  unsigned char * data = buffer->data;  unsigned long shift = buffer->shift;  /* TODO: optimized loop if HAS_BSWAP */  /* encode DC coefficient */  v = mpeg1_table_clip[block[0]];  if(v == 1) {    fast_bitbuffer_write(data, shift, 2, 2);    i = 1;  } else if(v == -1) {    fast_bitbuffer_write(data, shift, 3, 2);    i = 1;  } else {    i = 0;  }  /* encode AC coefficients */  last = i;  for(; i < 64; i++)  {    v = block[mpeg1_zigzag_table[i]];    /* count zeroes */    if(v != 0) {      /* write code */      vlc = syntax_mpeg1->vlc_table + (mpeg1_table_clip[v] << 6) + i - last;      fast_bitbuffer_write(data, shift, vlc->code, vlc->length);            /* reset zeroes count */      last = i+1;    }  }  /* mark end of block */  fast_bitbuffer_write(data, shift, 2, 2);  buffer->data = data;  buffer->shift = shift;}static void inline mpeg1_write_vector(fame_syntax_t *syntax, short delta){  fame_syntax_mpeg1_t *syntax_mpeg1 = FAME_SYNTAX_MPEG1(syntax);  short length;  short f_code;  short code;  short residual;  if (delta == 0) {    bitbuffer_write(&syntax_mpeg1->buffer,		    mb_motion_table[32].code,		    mb_motion_table[32].length);  } else {    f_code = syntax_mpeg1->f_code;    length = 8 << f_code;    f_code--;    if(delta >= length) {      delta = delta - length - length;    }    if(delta < -length) {      delta = delta + length + length;    }    if(delta > 0) {      delta--;      residual = delta & ((1 << f_code) - 1);      code = ((delta - residual) >> f_code) + 1;    } else {      delta = -delta;      delta--;      residual = delta & ((1 << f_code) - 1);      code = ((delta - residual)>> f_code) + 1;      code = -code;    }      code += 32;    bitbuffer_write(&syntax_mpeg1->buffer,		    mb_motion_table[code].code,		    mb_motion_table[code].length);        if(f_code)      bitbuffer_write(&syntax_mpeg1->buffer, residual, f_code);  }}static int mpeg1_write_inter_mb(fame_syntax_t *syntax,                                int mb_x,                                int mb_y,                                short *blocks[6],                                unsigned char *bab,                                unsigned char *bab_map,                                fame_bab_t bab_type,                                int dquant,                                unsigned char pattern,                                fame_motion_vector_t *forward,                                fame_motion_vector_t *backward,                                fame_motion_coding_t motion_coding){  fame_syntax_mpeg1_t *syntax_mpeg1 = FAME_SYNTAX_MPEG1(syntax);  int incr;  int motion_forward, motion_backward;  int coded[6];  int cbp;  int i, j;  int retval = 1;  incr = mb_y * syntax_mpeg1->mb_width + mb_x - syntax_mpeg1->prev_mb_addr;  /* TODO: support B pictures */  pattern = 0;  motion_forward = 0;  motion_backward = 0;  if(forward && (forward[0].dx != 0 || forward[0].dy != 0))    motion_forward = 1;  if(backward && (backward[0].dx != 0 || backward[0].dy != 0))    motion_backward = 1;  /* check for not coded blocks */  for(j = 0; j < 6; j++) {    coded[j] = 0;    if(blocks[j] != NULL)      for(i = 0; i < 64; i++) {	coded[j] |= blocks[j][i];      }  }  /* make cbp code */  cbp = 0;  if(coded[0])    cbp |= 0x20;  if(coded[1])    cbp |= 0x10;  if(coded[2])    cbp |= 0x08;  if(coded[3])    cbp |= 0x04;  if(coded[4])    cbp |= 0x02;  if(coded[5])    cbp |= 0x01;  if(!cbp && !motion_forward && !motion_backward &&      syntax_mpeg1->prev_mb_addr != syntax_mpeg1->slice_start &&     (syntax_mpeg1->prev_mb_addr + incr) != (syntax_mpeg1->slice_length - 1)) {    /* reset the DC predictors */    syntax_mpeg1->y_dc_pred = 128;    syntax_mpeg1->cr_dc_pred = syntax_mpeg1->cb_dc_pred = 128;    /* reset the motion predictors */    syntax_mpeg1->mv_pred.dx = syntax_mpeg1->mv_pred.dy = 0;    /* skip macroblock */    return(dquant);   }  else    motion_forward = 1; /* force coding of block */  syntax_mpeg1->prev_mb_addr += incr;  while(incr > 33) {    bitbuffer_write(&syntax_mpeg1->buffer, mb_addr_inc[33].code, mb_addr_inc[33].length);     /* address escape */    incr -= 33;  }  bitbuffer_write(&syntax_mpeg1->buffer, mb_addr_inc[incr-1].code, mb_addr_inc[incr-1].length); /* address increment */  switch(syntax_mpeg1->frame_type) {    case frame_type_P:      motion_backward = 0;      if(!motion_forward) {	if(dquant) {	  bitbuffer_write(&syntax_mpeg1->buffer, 1, 5); /*no motion,pat,dq   */	} else {	  bitbuffer_write(&syntax_mpeg1->buffer, 1, 2); /*no motion,pat,nodq */	}      } else {	if(!cbp) {	  bitbuffer_write(&syntax_mpeg1->buffer, 1, 3); /* motion,no pattern */	} else {	  if(dquant) {	    bitbuffer_write(&syntax_mpeg1->buffer, 2, 5); /* motion,pat,dq */	  } else {	    bitbuffer_write(&syntax_mpeg1->buffer, 1, 1); /* motion,pat,no dq*/	  }	}      }    break;    default:    break;  }  /* dquant */  if(cbp && dquant) {    syntax_mpeg1->qscale += dquant;    bitbuffer_write(&syntax_mpeg1->buffer, syntax_mpeg1->qscale, 5);    retval = 0;  } else    retval = dquant;  /* motion vectors */  if(motion_forward) {    mpeg1_write_vector(syntax, forward[0].dx - syntax_mpeg1->mv_pred.dx);    mpeg1_write_vector(syntax, forward[0].dy - syntax_mpeg1->mv_pred.dy);  }  /* update motion predictors */  syntax_mpeg1->mv_pred.dx = forward[0].dx;  syntax_mpeg1->mv_pred.dy = forward[0].dy;      /* code block pattern */  if(cbp)    bitbuffer_write(&syntax_mpeg1->buffer, mb_pattern_table[cbp].code, mb_pattern_table[cbp].length);  /* code only useful blocks according to pattern value */  if(cbp & 0x20)    mpeg1_block_inter(syntax, blocks[0]);  if(cbp & 0x10)    mpeg1_block_inter(syntax, blocks[1]);  if(cbp & 0x08)    mpeg1_block_inter(syntax, blocks[2]);  if(cbp & 0x04)    mpeg1_block_inter(syntax, blocks[3]);  if(cbp & 0x02)    mpeg1_block_inter(syntax, blocks[4]);  if(cbp & 0x01)    mpeg1_block_inter(syntax, blocks[5]);  /* reset the predictors to their original values */  syntax_mpeg1->y_dc_pred = 128;  syntax_mpeg1->cr_dc_pred = syntax_mpeg1->cb_dc_pred = 128;  return(retval);}static void mpeg1_compute_chrominance_vectors(fame_syntax_t *syntax,					      fame_motion_vector_t *vectors,					      unsigned char pattern){  int x, y;  x = vectors[0].dx+vectors[1].dx+vectors[2].dx+vectors[3].dx;  y = vectors[0].dy+vectors[1].dy+vectors[2].dy+vectors[3].dy;  if(x > 0) vectors[4].dx = x >> 3;  else      vectors[4].dx = -((-x) >> 3);  if(y > 0) vectors[4].dy = y >> 3;  else      vectors[4].dy = -((-y) >> 3);  vectors[5].dx = vectors[4].dx;  vectors[5].dy = vectors[4].dy;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -