📄 fame_syntax_mpeg4.c
字号:
} else { /* Binary Only not (yet) supported */ } /* Next Start Code */ mpeg4_next_start_code(buff); /* User Data */ } }static void mpeg4_start_GOP(fame_syntax_t *syntax, int frame){#ifndef OPENDIVX_COMPATIBILITY fame_syntax_mpeg4_t *syntax_mpeg4 = FAME_SYNTAX_MPEG4(syntax); fame_bitbuffer_t *buff; int fps_num, fps_den; fps_num = syntax_mpeg4->fps_num; fps_den = syntax_mpeg4->fps_den; buff = &syntax_mpeg4->buffer; /* Group Of VOP default values */ syntax_mpeg4->closed_gov=1; syntax_mpeg4->broken_link=0; syntax_mpeg4->vop_time_increment=0; bitbuffer_write(buff,MPEG4_GVOP_START_CODE, 32); /* timecount hours */ bitbuffer_write(buff, (frame*fps_den/(3600*fps_num)) & 0x1f, 5); /* timecount minutes */ bitbuffer_write(buff, ((frame*fps_den/(60*fps_num))%60) & 0x3f, 6); /* marker */ bitbuffer_write(buff, 1, 1); /* timecount seconds */ bitbuffer_write(buff, ((frame*fps_den/fps_num)%60) & 0x3f, 6); bitbuffer_write(buff, syntax_mpeg4->closed_gov, 1); bitbuffer_write(buff, syntax_mpeg4->broken_link, 1); /* Next Start Code */ mpeg4_next_start_code(buff);#endif}static void mpeg4_start_picture(fame_syntax_t *syntax, char frame_type, int frame_number, fame_box_t *box, int rounding_control, int search_range){ fame_syntax_mpeg4_t *syntax_mpeg4 = FAME_SYNTAX_MPEG4(syntax); fame_bitbuffer_t *buff; int tmp; unsigned int modulo_time_base; buff = &syntax_mpeg4->buffer; switch(frame_type) { case 'I': syntax_mpeg4->vop_coding_type = MPEG4_I_FRAME; break; case 'P': syntax_mpeg4->vop_coding_type = MPEG4_P_FRAME; break; default: FAME_ERROR("Unsupported picture coding type %c", frame_type); return; } /* Video Object Plane */ syntax_mpeg4->vop_rounding_type = rounding_control; syntax_mpeg4->vop_reduced_resolution = 0; syntax_mpeg4->vop_horizontal_mc_spatial_ref=box->x; syntax_mpeg4->vop_vertical_mc_spatial_ref=box->y; syntax_mpeg4->vop_width=box->w; syntax_mpeg4->vop_height=box->h; syntax_mpeg4->vop_constant_alpha=0; syntax_mpeg4->vop_constant_alpha_value=128; syntax_mpeg4->intra_dc_vlc_thr=0; /* use intra DC vlc for all DC coefficients */ tmp = (box->w+15)/16 * (box->h+15)/16; syntax_mpeg4->macroblock_number_size = get_min_bit(tmp); /* compute fcode */ syntax_mpeg4->vop_fcode_forward = syntax_mpeg4->vop_fcode_backward = fame_max(1, get_min_bit(search_range-1)-3); if(syntax_mpeg4->vop_fcode_forward > 7) { FAME_WARNING("vop_fcode_forward > 7, search range too big.\n"); syntax_mpeg4->vop_fcode_forward = 7; } if(syntax_mpeg4->vop_fcode_backward > 7) { FAME_WARNING("vop_fcode_backward > 7, search range too big.\n"); syntax_mpeg4->vop_fcode_backward = 7; } bitbuffer_write(buff, MPEG4_VOP_START_CODE, 32); /* picture start code */ bitbuffer_write(buff, syntax_mpeg4->vop_coding_type,2); /* Modulo time base */ modulo_time_base = syntax_mpeg4->vop_time_increment / syntax_mpeg4->vop_time_increment_resolution; if (modulo_time_base) { bitbuffer_write(buff, ((1 << modulo_time_base) - 1), modulo_time_base); syntax_mpeg4->vop_time_increment %= syntax_mpeg4->vop_time_increment_resolution; } bitbuffer_write(buff,0,1); /* end of modulo time base */ bitbuffer_write(buff,1,1); /* Marker */ bitbuffer_write(buff,syntax_mpeg4->vop_time_increment%syntax_mpeg4->vop_time_increment_resolution, get_min_bit(syntax_mpeg4->vop_time_increment_resolution)); syntax_mpeg4->vop_time_increment += syntax_mpeg4->fixed_vop_time_increment; bitbuffer_write(buff,1,1); bitbuffer_write(buff,1,1); /* VOP coded */ if(syntax_mpeg4->newpred_enable) { /* not supported */ } if( (syntax_mpeg4->video_object_layer_shape != MPEG4_Video_Object_Layer_Shape_BinaryOnly ) && (syntax_mpeg4->vop_coding_type == MPEG4_P_FRAME)) bitbuffer_write(buff,syntax_mpeg4->vop_rounding_type,1); if ( (syntax_mpeg4->reduced_resolution_vop_enable) && (syntax_mpeg4->video_object_layer_shape == MPEG4_Video_Object_Layer_Shape_Rectangular ) && ((syntax_mpeg4->vop_coding_type == MPEG4_I_FRAME) || (syntax_mpeg4->vop_coding_type == MPEG4_P_FRAME ))) bitbuffer_write(buff,syntax_mpeg4->vop_reduced_resolution,1); if(syntax_mpeg4->video_object_layer_shape != MPEG4_Video_Object_Layer_Shape_Rectangular ) { /* TODO: test Sprite */ { bitbuffer_write(buff,syntax_mpeg4->vop_width & 0x1fff,13); bitbuffer_write(buff,1,1); /* Marker */ bitbuffer_write(buff,syntax_mpeg4->vop_height & 0x1fff,13); bitbuffer_write(buff,1,1); /* Marker */ bitbuffer_write(buff,syntax_mpeg4->vop_horizontal_mc_spatial_ref & 0x1fff,13); bitbuffer_write(buff,1,1); /* Marker */ bitbuffer_write(buff,syntax_mpeg4->vop_vertical_mc_spatial_ref & 0x1fff,13); bitbuffer_write(buff,1,1); /* Marker */ } bitbuffer_write(buff,syntax_mpeg4->change_conv_ratio_disable,1); bitbuffer_write(buff,syntax_mpeg4->vop_constant_alpha,1); if(syntax_mpeg4->vop_constant_alpha) bitbuffer_write(buff,syntax_mpeg4->vop_constant_alpha_value,8) } if (syntax_mpeg4->video_object_layer_shape != MPEG4_Video_Object_Layer_Shape_BinaryOnly ) if (!syntax_mpeg4->complexity_estimation_disable) { /* not supported */ } if (syntax_mpeg4->video_object_layer_shape != MPEG4_Video_Object_Layer_Shape_BinaryOnly ) { bitbuffer_write(buff,syntax_mpeg4->intra_dc_vlc_thr,3); if(syntax_mpeg4->interlaced) { /* not supported */ } } /* TODO: sprites */ { } syntax_mpeg4->flag_video_packet_header = 0; /* restart motion predictor */ syntax_mpeg4->mv_pred = syntax_mpeg4->motion_pred;}static void inline mpeg4_reset_pred(fame_syntax_t *syntax){ fame_syntax_mpeg4_t *syntax_mpeg4 = FAME_SYNTAX_MPEG4(syntax); int i; /* horizontal predictors */ FASTCOPY16(syntax_mpeg4->y_pred_h[0], syntax_mpeg4->pred_default); FASTCOPY16(syntax_mpeg4->y_pred_h[1], syntax_mpeg4->pred_default); FASTCOPY16(syntax_mpeg4->y_pred_h[2], syntax_mpeg4->pred_default); FASTCOPY16(syntax_mpeg4->cr_pred_h[0], syntax_mpeg4->pred_default); FASTCOPY16(syntax_mpeg4->cr_pred_h[1], syntax_mpeg4->pred_default); FASTCOPY16(syntax_mpeg4->cb_pred_h[0], syntax_mpeg4->pred_default); FASTCOPY16(syntax_mpeg4->cb_pred_h[1], syntax_mpeg4->pred_default); /* vertical predictors */ for(i = 0; i < syntax_mpeg4->mb_width; i++) { FASTCOPY16(syntax_mpeg4->y_pred_v[0][i], syntax_mpeg4->pred_default); FASTCOPY16(syntax_mpeg4->y_pred_v[1][i], syntax_mpeg4->pred_default); FASTCOPY16(syntax_mpeg4->cr_pred_v[i], syntax_mpeg4->pred_default); FASTCOPY16(syntax_mpeg4->cb_pred_v[i], syntax_mpeg4->pred_default); } /* motion predictors */ memset(syntax_mpeg4->motion_pred, 0, 4*syntax_mpeg4->mb_height* syntax_mpeg4->mb_width*sizeof(fame_motion_vector_t));}static void mpeg4_start_slice(fame_syntax_t *syntax, int vpos, int length, unsigned char qscale){ fame_syntax_mpeg4_t *syntax_mpeg4 = FAME_SYNTAX_MPEG4(syntax); fame_bitbuffer_t *buff; /* compute dc_scaler */ if(qscale == 0 || qscale > 31) { FAME_WARNING("Invalid quantisation scale %d (1-31), setting to 8.\n", qscale); } buff = &syntax_mpeg4->buffer; /* Video Packet default value */ syntax_mpeg4->vop_quant = syntax_mpeg4->quant_scale = qscale; syntax_mpeg4->vop_shape_coding_type = 0; /* always intra shape coding */ syntax_mpeg4->header_extension_code = 0; syntax_mpeg4->macroblock_number = vpos * ((syntax_mpeg4->vop_width+15) / 16); if (!syntax_mpeg4->flag_video_packet_header) { if (syntax_mpeg4->video_object_layer_shape != MPEG4_Video_Object_Layer_Shape_BinaryOnly ) { bitbuffer_write(buff,syntax_mpeg4->vop_quant & ((1 << syntax_mpeg4->quant_precision)-1),syntax_mpeg4->quant_precision); if (syntax_mpeg4->video_object_layer_shape == MPEG4_Video_Object_Layer_Shape_Grayscale ) { /* Not supported */ } if (syntax_mpeg4->vop_coding_type != MPEG4_I_FRAME ) bitbuffer_write(buff,syntax_mpeg4->vop_fcode_forward & 7,3); if (syntax_mpeg4->vop_coding_type == MPEG4_B_FRAME ) bitbuffer_write(buff,syntax_mpeg4->vop_fcode_backward & 7,3); if(!syntax_mpeg4->scalability) { if ((syntax_mpeg4->video_object_layer_shape != MPEG4_Video_Object_Layer_Shape_Rectangular) && (syntax_mpeg4->vop_coding_type != MPEG4_I_FRAME )) bitbuffer_write(buff,syntax_mpeg4->vop_shape_coding_type,1); }else { /* Not supported */ } } else { /* Not supported */ } syntax_mpeg4->flag_video_packet_header=1; } else { int resync_length = 0; /* compute resync marker length */ if (syntax_mpeg4->vop_coding_type == MPEG4_I_FRAME || syntax_mpeg4->video_object_layer_shape == MPEG4_Video_Object_Layer_Shape_BinaryOnly) resync_length = 16; else { if(syntax_mpeg4->vop_coding_type == MPEG4_P_FRAME) resync_length = 15+syntax_mpeg4->vop_fcode_forward; if(syntax_mpeg4->vop_coding_type == MPEG4_B_FRAME) resync_length = fame_max(15+fame_max(syntax_mpeg4->vop_fcode_forward, syntax_mpeg4->vop_fcode_backward), 17); } /* resync marker */ bitbuffer_write(buff, 0, resync_length); bitbuffer_write(buff, 1, 1); if(syntax_mpeg4->video_object_layer_shape != MPEG4_Video_Object_Layer_Shape_Rectangular) bitbuffer_write(buff,syntax_mpeg4->header_extension_code,1); if(syntax_mpeg4->header_extension_code) /* TODO: test sprite_enable */ { /* Not implemented */ } bitbuffer_write(buff,syntax_mpeg4->macroblock_number,syntax_mpeg4->macroblock_number_size); if(syntax_mpeg4->video_object_layer_shape!= MPEG4_Video_Object_Layer_Shape_BinaryOnly) bitbuffer_write(buff,syntax_mpeg4->quant_scale & 0x1f, 5); if(syntax_mpeg4->video_object_layer_shape == MPEG4_Video_Object_Layer_Shape_Rectangular) bitbuffer_write(buff,syntax_mpeg4->header_extension_code,1); if(syntax_mpeg4->header_extension_code) { /* Not Implemented */ } if (syntax_mpeg4->newpred_enable) { /* Not implemented */ } } /* reset the DC predictors to their original values */ mpeg4_reset_pred(syntax);}static void mpeg4_end_slice(fame_syntax_t *syntax) { fame_syntax_mpeg4_t *syntax_mpeg4 = FAME_SYNTAX_MPEG4(syntax); mpeg4_next_start_code(&syntax_mpeg4->buffer); /* next start code */}static void mpeg4_end_sequence(fame_syntax_t *syntax){ fame_syntax_mpeg4_t *syntax_mpeg4 = FAME_SYNTAX_MPEG4(syntax); /* end sequence code */ bitbuffer_write(&syntax_mpeg4->buffer, MPEG4_SEQUENCE_END_CODE, 32);}static void mpeg4_predict_vector(fame_syntax_t *syntax, int mb_x, int mb_y, int k, fame_motion_vector_t *mv){#define MEDIAN(a,b,c) ((b)<(a))?(((c)>(a))?(a):(((c)<(b))?(b):(c))):(((c)<(a))?(a):(((c)>(b))?(b):(c))) fame_syntax_mpeg4_t *syntax_mpeg4 = FAME_SYNTAX_MPEG4(syntax); fame_motion_vector_t *predictor1, *predictor2, *predictor3, *mv_pred; int pitch; int border1, border2, border3; int mb_addr, slice_addr; /* HACK: we use count as a flag for vector validity */ /* TODO: thus, checking borders is probably not needed anymore */ /* though checking video packets boundaries is. */ pitch = syntax_mpeg4->mb_width; slice_addr = syntax_mpeg4->macroblock_number; mb_addr = mb_y*syntax_mpeg4->mb_width+mb_x; border1 = (mb_x == 0) || (mb_addr <= slice_addr); border2 = (mb_addr - pitch < slice_addr); border3 = (mb_x == pitch - 1) || (mb_addr - pitch + 1 < slice_addr); pitch = syntax_mpeg4->mb_width*4; mv_pred = syntax_mpeg4->mv_pred; switch(k) { case 0: predictor1 = mv_pred - 3; predictor2 = mv_pred - pitch + 2; predictor3 = mv_pred - pitch + 6; break; /* WARNING: count must be valid in 'mv' past this point */ case 1: predictor1 = &mv[0]; border1 = 0; predictor2 = mv_pred - pitch + 3; predictor3 = mv_pred - pitch + 6; break; case 2: predictor1 = mv_pred - 1; predictor2 = &mv[0]; border2 = 0; predictor3 = &mv[1]; border3 = 0; break; case 3: predictor1 = &mv[2]; border1 = 0; predictor2 = &mv[0]; border2 = 0; predictor3 = &mv[1]; border3 = 0; break; default: /* invalid k */ predictor1 = predictor2 = predictor3 = NULL; break; } if(border1 || !predictor1->count) { if(border2 || !predictor2->count) { if(border3 || !predictor3->count) { /* no pred */ mv_pred[k].dx = 0; mv_pred[k].dy = 0; } else { /* only p3 */ mv_pred[k].dx = predictor3->dx; mv_pred[k].dy = predictor3->dy; } } else { if(border3 || !predictor3->count) { /* p2 only */ mv_pred[k].dx = predictor2->dx; mv_pred[k].dy = predictor2->dx; } else { /* p2, p3 */ mv_pred[k].dx = MEDIAN(0,predictor2->dx,predictor3->dx); mv_pred[k].dy = MEDIAN(0,predictor2->dy,predictor3->dy); } } } else if(border3 || !predictor3->count) { if(border2 || !predictor2->count) { /* p1 only */ mv_pred[k].dx = predictor1->dx; mv_pred[k].dy = predictor1->dy; } else { /* p1, p2 */ mv_pred[k].dx = MEDIAN(predictor1->dx,predictor2->dx,0); mv_pred[k].dy = MEDIAN(predictor1->dy,predictor2->dy,0); } } else { if(border2 || !predictor2->count) { /* p1, p3 */ mv_pred[k].dx = MEDIAN(predictor1->dx,0,predictor3->dx); mv_pred[k].dy = MEDIAN(predictor1->dx,0,predictor3->dx); } else { /* p1, p2, p3 */ mv_pred[k].dx = MEDIAN(predictor1->dx, predictor2->dx, predictor3->dx); mv_pred[k].dy = MEDIAN(predictor1->dy, predictor2->dy, predictor3->dy); } } if(k == 0) { /* HACK: fill in the 16x16 vector with the predictor */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -