C_RESULT p264_write_picture_layer( video_controller_t* controller, video_stream_t* stream ) { uint32_t format = 0, resolution = 0, width, height; p264_codec_t* p264_codec = (p264_codec_t*) controller->video_codec; p264_picture_layer_t* picture_layer = &p264_codec->picture_layer; width = controller->width; height = controller->height; while( format == 0 ) { if( width == QQCIF_WIDTH ) format = UVLC_FORMAT_CIF; if( width == QQVGA_WIDTH ) format = UVLC_FORMAT_VGA; width >>= 1; height >>= 1; resolution ++; } picture_layer->format = format; picture_layer->resolution = resolution; video_write_data( stream, picture_layer->format, 2 ); video_write_data( stream, picture_layer->resolution, 3 ); video_write_data( stream, picture_layer->picture_type, 3 ); video_write_data( stream, picture_layer->quant, 6 ); video_write_data( stream, controller->num_frames, 32 ); return C_OK; }
// write 16 intra_4x4 mode. Data should contains prediction on intra_4x4 (see p264 standard) // example : data = [ pred (1bits) | code (3bits) ] // if pred == 0 the prediction made over up and left block is correct. Thus no intra code has to bee transmitted // if pred != 1, the prediction is wrong. The intra 4x4 mode should be transmitted using only 3 bits (see p264 standard) void p264_write_intra_4x4 (video_stream_t* const stream, intra_4x4_mode_t* data) { uint32_t i=16; while(i--) { if (((*data)&0x08) == 0) { // the prediction is good, signal it video_write_data (stream,0,1); } else { // the prediction is false, transmit the intra 4x4 mode video_write_data (stream,*data,4); } data++; } }
void p264_write_block( video_stream_t* const stream, int16_t* data, uint32_t length) { int32_t code, run, num_coeff; // count number of DC coeff num_coeff = 0; int16_t * p_data = data; while (length--) { if (*p_data++ != 0) num_coeff++; } if (num_coeff == 0) { video_write_data( stream, 1, 1 ); // signal that there's no coeff } else { video_write_data( stream, 0, 1 ); // signal that there are coeffs run = 0; while( num_coeff > 0 ) { code = *data++; if( code == 0 ) { run ++; } else { num_coeff--; p264_encode( stream, code, run, num_coeff ); run = 0; } } } }
C_RESULT video_encode_picture( video_controller_t* controller, const vp_api_picture_t* picture, bool_t* got_image ) { vp_api_picture_t blockline = { 0 }; controller->mode = VIDEO_ENCODE; video_controller_set_format( controller, picture->width, picture->height ); blockline = *picture; blockline.height = MB_HEIGHT_Y; blockline.complete = 1; blockline.vision_complete = 0; // Reset internal stream for new blockline/picture controller->in_stream.used = 0; controller->in_stream.index = 0; while( !controller->picture_complete ) { video_encode_blockline( controller, &blockline, blockline.blockline == (controller->num_blockline-1) ); blockline.y_buf += MB_HEIGHT_Y * picture->y_line_size; blockline.cb_buf += MB_HEIGHT_C * picture->cb_line_size; blockline.cr_buf += MB_HEIGHT_C * picture->cr_line_size; blockline.blockline++; } if( picture->complete ) { video_write_data( &controller->in_stream, 0, controller->in_stream.length+1 ); controller->in_stream.length = 32; controller->picture_complete = 0; *got_image = TRUE; } return C_OK; }
void uvlc_encode( video_stream_t* const stream, int32_t level, int32_t run, int32_t not_last ) { int32_t sign, length, data, value_code, value_length; /// Encode number of zeros data = run; length = 0; value_code = 1; if( data > 0 ) { length = 32 - clz(data); // compute number of bits used in run ( = length of run ) data -= 1 << ( length - 1 ); // compute value of run } value_length = length + 1; length -= 1; if( length > 0 ) { PACK_BITS( value_code, value_length, data, length ); } /// Encode level data = level; // sign handling sign = 0; if( data < 0 ) { data = -data; sign = 1; } // TODO Check saturation & if level == -128 length = 32 - clz(data); // number of bits used in level ( = length of level ) if( length > 1 ) { data -= 1 << (length - 1); length += 1; } PACK_BITS( value_code, value_length, 1, length ); VP_OS_ASSERT( length != 2 ); length -= 2; if(length > 0) { PACK_BITS( value_code, value_length, data, length ); } PACK_BITS( value_code, value_length, sign, 1 ); /// Encode last // add sequence for end of block if required if( not_last == 0 ) { PACK_BITS( value_code, value_length, 0x5, 3 ); } /// Write output video_write_data( stream, value_code, value_length ); }
C_RESULT p264_write_gob_layer( video_stream_t* stream, p264_gob_layer_t* gob ) { video_write_data( stream, gob->quant, 6 ); return C_OK; }
C_RESULT vlib_stage_encoding_transform(vlib_stage_encoding_config_t *cfg, vp_api_io_data_t *in, vp_api_io_data_t *out) { static int32_t local_subsampl = 0; vp_os_mutex_lock(&out->lock); if( out->status == VP_API_STATUS_INIT ) { out->numBuffers = 1; out->buffers = (int8_t**)(int8_t*)&cfg->controller.in_stream.bytes; out->indexBuffer = 0; out->status = VP_API_STATUS_PROCESSING; cfg->current_size = 0; } if( local_subsampl == 0 && out->status == VP_API_STATUS_PROCESSING ) { RTMON_USTART(VIDEO_VLIB_ENCODE_EVENT); if(cfg->block_mode_enable) video_encode_blockline( &cfg->controller, cfg->picture, cfg->picture->complete ); else video_encode_picture( &cfg->controller, cfg->picture, (bool_t*)&cfg->picture->complete ); RTMON_USTOP(VIDEO_VLIB_ENCODE_EVENT); if(cfg->picture->complete) { RTMON_UVAL(ENCODED_PICTURE_UVAL, cfg->controller.num_frames); local_subsampl++; } cfg->current_size = cfg->controller.in_stream.used; if( cfg->controller.in_stream.length != 32 ) { // flush & reset internal stream video_write_data( &cfg->controller.in_stream, 0, cfg->controller.in_stream.length+1 ); cfg->controller.in_stream.length = 32; } out->size = cfg->controller.in_stream.used; RTMON_UVAL(ENCODED_BLOCKLINE_SIZE_UVAL, out->size); cfg->controller.in_stream.used = 0; cfg->controller.in_stream.index = 0; } else { out->size = 0; if( cfg->picture->complete ) { local_subsampl++; } } if(local_subsampl >= (int32_t)cfg->subsampl) local_subsampl = 0; vp_os_mutex_unlock( &out->lock ); return C_OK; }
C_RESULT p264_write_mb_layer(video_controller_t* controller, video_stream_t* stream, video_macroblock_t* mb, int32_t num_macro_blocks ) { int16_t* data; //uint32_t code; uint32_t i; while( num_macro_blocks > 0 ) { //PRINT ("p264_write_mb_layer : stream size %d stream used %d\n",stream->size,stream->used); if (controller->picture_type == VIDEO_PICTURE_INTER) { // write all partition for (i=0; i<mb->nb_partition; i++) { video_write_data( stream,mb->inter_partition_mode[i],3); } // write all motion vector for (i=0; i<mb->nb_partition; i++) { int32_t s_code; s_code = (int32_t)mb->inter_MV[i].x; p264_encode_int(stream, s_code); s_code = (int32_t)mb->inter_MV[i].y; p264_encode_int(stream, s_code); } // write residual data as an intra4x4 // write all 4x4 block luma AC coeff i=16; data = ((MB_p264_t*)mb->data)->inter.AC_Y; while(i--) { p264_write_block( stream, data, 16); data += BLOCK_SIZE2; } // write 4 DC U coeff p264_write_block(stream,((MB_p264_t*)mb->data)->inter.DC_U,4); // write AC U coeff i=4; data = &((MB_p264_t*)mb->data)->inter.AC_U[1]; while(i--) { p264_write_block( stream, data, 15); data += BLOCK_SIZE2; } // write 4 DC V coeff p264_write_block(stream,((MB_p264_t*)mb->data)->inter.DC_V,4); // write AC V coeff i=4; data = &((MB_p264_t*)mb->data)->inter.AC_V[1]; while(i--) { p264_write_block( stream, data, 15); data += BLOCK_SIZE2; } } else { // write MB intra type (16x16 or 4x4) video_write_data( stream, mb->intra_type, 1 ); // write intra chroma type video_write_data (stream, mb->intra_chroma_8x8_mode,2); if (mb->intra_type == INTRA_4x4) { // write all luma 4x4 prediction modes p264_write_intra_4x4(stream,mb->intra_4x4_mode); // write all 4x4 block luma AC coeff i=16; data = ((MB_p264_t*)mb->data)->intra_4x4.AC_Y; while(i--) { p264_write_block( stream, data, 16); data += BLOCK_SIZE2; } // write 4 DC U coeff p264_write_block(stream,((MB_p264_t*)mb->data)->intra_4x4.DC_U,4); // write AC U coeff i=4; data = &((MB_p264_t*)mb->data)->intra_4x4.AC_U[1]; while(i--) { p264_write_block( stream, data, 15); data += BLOCK_SIZE2; } // write 4 DC V coeff p264_write_block(stream,((MB_p264_t*)mb->data)->intra_4x4.DC_V,4); // write AC V coeff i=4; data = &((MB_p264_t*)mb->data)->intra_4x4.AC_V[1]; while(i--) { p264_write_block( stream, data, 15); data += BLOCK_SIZE2; } } else { // write luma 16x16 prediction mode video_write_data(stream, mb->intra_luma_16x16_mode,2); // write 16 DC luma p264_write_block( stream, ((MB_p264_t*)mb->data)->intra_16x16.DC_Y, 16); // write 16 luma AC coeff block i=16; data = &((MB_p264_t*)mb->data)->intra_16x16.AC_Y[1]; while(i--) { p264_write_block( stream, data, 15); data += BLOCK_SIZE2; } // write 4 DC U coeff p264_write_block(stream,((MB_p264_t*)mb->data)->intra_16x16.DC_U,4); // write AC U coeff i=4; data = &((MB_p264_t*)mb->data)->intra_16x16.AC_U[1]; while(i--) { p264_write_block( stream, data, 15); data += BLOCK_SIZE2; } // write 4 DC V coeff p264_write_block(stream,((MB_p264_t*)mb->data)->intra_16x16.DC_V,4); // write AC V coeff i=4; data = &((MB_p264_t*)mb->data)->intra_16x16.AC_V[1]; while(i--) { p264_write_block( stream, data, 15); data += BLOCK_SIZE2; } } } mb ++; num_macro_blocks --; } return C_OK; }