📄 fame_syntax_mpeg1.c
字号:
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 + -