📄 cinepak.c
字号:
PIX_SET_Y( 2*j + 1, 2*i + 1, p_context->codebook_v1[i_strip][i_index].i_y[2*i+j] ); PIX_SET_UV( 1,p_dst_u, j, i, p_context->codebook_v1[i_strip][i_index].i_u ); PIX_SET_UV( 2,p_dst_v, j, i, p_context->codebook_v1[i_strip][i_index].i_v ); } }#undef PIX_SET_Y#undef PIX_SET_UV}/***************************************************************************** * The function that decode one frame *****************************************************************************/static int cinepak_decode_frame( cinepak_context_t *p_context, int i_length, uint8_t *p_data ){ int i_strip; int i_frame_flags; int i_frame_size; int i_width, i_height; int i_frame_strips; int i_index; int i_strip_x1 =0, i_strip_y1=0; int i_strip_x2 =0, i_strip_y2=0; if( i_length <= 10 ) { /* Broken header or no data */ return( -1 ); } /* get header */ i_frame_flags = *(p_data++); i_frame_size = GET3BYTES( p_data ); i_width = GET2BYTES( p_data ); i_height = GET2BYTES( p_data ); i_frame_strips = GET2BYTES( p_data ); if( !i_frame_size || !i_width || !i_height ) { /* Broken header */ return( -1 ); } /* Check if we have a picture buffer with good size */ if( ( p_context->i_width != i_width ) || ( p_context->i_height != i_height ) ) { int i; for( i = 0; i < 3; i++ ) { FREE( p_context->p_pix[i] ); } p_context->i_width = i_width; p_context->i_height = i_height; p_context->i_stride[0] = ( i_width + 3 ) & 0xfffc; p_context->i_stride[1] = p_context->i_stride[2] = p_context->i_stride[0] / 2; p_context->i_lines[0] = ( i_height + 3 ) & 0xfffc; p_context->i_lines[1] = p_context->i_lines[2] = p_context->i_lines[0] /2; for( i = 0; i < 3; i++ ) { p_context->p_pix[i] = malloc( p_context->i_stride[i] * p_context->i_lines[i] ); /* Set it to all black */ memset( p_context->p_pix[i], ( i == 0 ) ? 0 : 128 , p_context->i_stride[i] * p_context->i_lines[i] ); } } if( i_frame_size != i_length ) { i_length = __MIN( i_length, i_frame_size ); } i_length -= 10; if( i_frame_strips >= CINEPAK_MAXSTRIP ) { i_frame_strips = CINEPAK_MAXSTRIP; } /* Now decode each strip */ for( i_strip = 0; i_strip < i_frame_strips; i_strip++ ) { int i_strip_id; int i_strip_size; if( i_length <= 12 ) { break; } i_strip_id = GET2BYTES( p_data ); i_strip_size = GET2BYTES( p_data ); i_strip_size = __MIN( i_strip_size, i_length ); /* FIXME I don't really understand how it's work; */ i_strip_y1 = i_strip_y2 + GET2BYTES( p_data ); i_strip_x1 = GET2BYTES( p_data ); i_strip_y2 = i_strip_y2 + GET2BYTES( p_data ); i_strip_x2 = GET2BYTES( p_data ); i_length -= i_strip_size; i_strip_size -= 12; /* init codebook , if needed */ if( ( i_strip > 0 )&&( !(i_frame_flags&0x01) ) ) { memcpy( &p_context->codebook_v1[i_strip], &p_context->codebook_v1[i_strip-1], sizeof(cinepak_codebook_t[256] ) ); memcpy( &p_context->codebook_v4[i_strip], &p_context->codebook_v4[i_strip-1], sizeof(cinepak_codebook_t[256] ) ); } /* Now parse all chunk in this strip */ while( i_strip_size > 0 ) { cinepak_codebook_t (*p_codebook)[CINEPAK_MAXSTRIP][256]; int i_mode; int i_chunk_id; int i_chunk_size; uint32_t i_vector_flags; int i_count; int i; int i_x, i_y; /* (0,0) begin in fact at (x1,y1) ... */ i_chunk_id = GET2BYTES( p_data ); i_chunk_size = GET2BYTES( p_data ); i_chunk_size = __MIN( i_chunk_size, i_strip_size ); i_strip_size -= i_chunk_size; i_chunk_size -= 4; i_x = 0; i_y = 0; if( i_chunk_size < 0 ) { break; } switch( i_chunk_id ) { case( 0x2000 ): /* 12bits v4 Intra*/ case( 0x2200 ): /* 12bits v1 Intra*/ case( 0x2400 ): /* 8bits v4 Intra*/ case( 0x2600 ): /* 8bits v1 Intra */ i_mode = ( ( i_chunk_id&0x0400 ) == 0 ); p_codebook = ( i_chunk_id&0x0200 ) ? &p_context->codebook_v1 : &p_context->codebook_v4; i_count = __MIN( i_chunk_size / ( i_mode ? 6 : 4 ), 256 ); for( i = 0; i < i_count; i++ ) { cinepak_LoadCodebook( &((*p_codebook)[i_strip][i]), p_data, i_mode&~p_context->b_grayscale ); p_data += i_mode ? 6 : 4; i_chunk_size -= i_mode ? 6 : 4; } break; case( 0x2100 ): /* selective 12bits v4 Inter*/ case( 0x2300 ): /* selective 12bits v1 Inter*/ case( 0x2500 ): /* selective 8bits v4 Inter*/ case( 0x2700 ): /* selective 8bits v1 Inter*/ i_mode = ( ( i_chunk_id&0x0400 ) == 0 ); p_codebook = ( i_chunk_id&0x0200 ) ? &p_context->codebook_v1 : &p_context->codebook_v4; i_index = 0; while( (i_chunk_size > 4)&&(i_index<256)) { i_vector_flags = GET4BYTES( p_data ); i_chunk_size -= 4; for( i = 0; i < 32; i++ ) { if( ( i_chunk_size < ( i_mode ? 6 : 4 ) ) || (i_index >= 256 ) ) { break; } if( i_vector_flags&0x80000000UL ) { cinepak_LoadCodebook( &((*p_codebook)[i_strip][i_index]), p_data, i_mode&~p_context->b_grayscale ); p_data += i_mode ? 6 : 4; i_chunk_size -= i_mode ? 6 : 4; } i_index++; i_vector_flags <<= 1; } } break; case( 0x3000 ): /* load image Intra */ while( (i_chunk_size >= 4 )&&(i_y<i_strip_y2-i_strip_y1) ) { i_vector_flags = GET4BYTES( p_data ); i_chunk_size -= 4; i_strip_size -= 4; i_length -= 4; for( i = 0; i < 32; i++ ) { if( ( i_y >= i_strip_y2 - i_strip_y1) || ( i_chunk_size<=0 ) ) { break; } if( i_vector_flags&0x80000000UL ) { cinepak_Getv4( p_context, i_strip, i_strip_x1 + i_x, i_strip_y1 + i_y, i_strip_x2, i_strip_y2, p_data ); p_data += 4; i_chunk_size -= 4; } else { cinepak_Getv1( p_context, i_strip, i_strip_x1 + i_x, i_strip_y1 + i_y, i_strip_x2, i_strip_y2, p_data ); p_data++; i_chunk_size--; } i_x += 4; if( i_x >= i_strip_x2 - i_strip_x1 ) { i_x = 0; i_y += 4; } i_vector_flags <<= 1; } } break; case( 0x3100 ): /* load image Inter */ while( ( i_chunk_size > 4 )&&( i_y < i_strip_y2 - i_strip_y1) ) { uint32_t i_mask; i_vector_flags = GET4BYTES( p_data ); i_chunk_size -= 4; i_mask = 0x80000000UL; while( (i_chunk_size > 0 ) && ( i_mask ) && ( i_y < i_strip_y2 - i_strip_y1 ) ) { if( i_vector_flags&i_mask ) { i_mask >>= 1; if( !i_mask ) { if( i_chunk_size < 4 ) { break; } i_vector_flags = GET4BYTES( p_data ); i_chunk_size -= 4; i_mask = 0x80000000UL; } if( i_vector_flags&i_mask ) { if( i_chunk_size < 4 ) break; cinepak_Getv4( p_context, i_strip, i_strip_x1 + i_x, i_strip_y1 + i_y, i_strip_x2, i_strip_y2, p_data ); p_data += 4; i_chunk_size -= 4; } else { if( i_chunk_size < 1 ) break; cinepak_Getv1( p_context, i_strip, i_strip_x1 + i_x, i_strip_y1 + i_y, i_strip_x2, i_strip_y2, p_data ); p_data++; i_chunk_size--; } } i_mask >>= 1; i_x += 4; if( i_x >= i_strip_x2 - i_strip_x1 ) { i_x = 0; i_y += 4; } } } break; case( 0x3200 ): /* load intra picture but all v1*/ while( ( i_chunk_size > 0 ) && ( i_y < i_strip_y2 - i_strip_y1 ) ) { cinepak_Getv1( p_context, i_strip, i_strip_x1 + i_x, i_strip_y1 + i_y, i_strip_x2, i_strip_y2, p_data ); p_data++; i_chunk_size--; i_x += 4; if( i_x >= i_strip_x2 - i_strip_x1 ) { i_x = 0; i_y += 4; } } break; default: break; } p_data += i_chunk_size ; /* skip remains bytes */ } } return( 0 );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -