📄 encoder_toplevel.c
字号:
cpi->ThreshMapThreshold = 5; cpi->MaxConsDroppedFrames = 1; /* Set encoder flags. */ /* if not AutoKeyframing cpi->ForceKeyFrameEvery = is frequency */ if(!c->keyframe_auto_p) c->keyframe_frequency_force = c->keyframe_frequency; /* Set the frame rate variables. */ if ( c->fps_numerator < 1 ) c->fps_numerator = 1; if ( c->fps_denominator < 1 ) c->fps_denominator = 1; /* don't go too nuts on keyframe spacing; impose a high limit to make certain the granulepos encoding strategy works */ if(c->keyframe_frequency_force>32768)c->keyframe_frequency_force=32768; if(c->keyframe_mindistance>32768)c->keyframe_mindistance=32768; if(c->keyframe_mindistance>c->keyframe_frequency_force) c->keyframe_mindistance=c->keyframe_frequency_force; cpi->pb.keyframe_granule_shift=_ilog(c->keyframe_frequency_force-1); /* clamp the target_bitrate to a maximum of 24 bits so we get a more meaningful value when we write this out in the header. */ if(c->target_bitrate>(1<<24)-1)c->target_bitrate=(1<<24)-1; /* copy in config */ memcpy(&cpi->pb.info,c,sizeof(*c)); th->i=&cpi->pb.info; th->granulepos=-1; /* Set up default values for QTargetModifier[Q_TABLE_SIZE] table */ for ( i = 0; i < Q_TABLE_SIZE; i++ ) cpi->QTargetModifier[i] = 1.0; /* Set up an encode buffer */#ifndef LIBOGG2 cpi->oggbuffer = _ogg_malloc(sizeof(oggpack_buffer)); oggpackB_writeinit(cpi->oggbuffer);#else cpi->oggbuffer = _ogg_malloc(oggpack_buffersize()); cpi->oggbufferstate = ogg_buffer_create(); oggpackB_writeinit(cpi->oggbuffer, cpi->oggbufferstate);#endif /* Set data rate related variables. */ cpi->Configuration.TargetBandwidth = (c->target_bitrate) / 8; cpi->Configuration.OutputFrameRate = (double)( c->fps_numerator / c->fps_denominator ); cpi->frame_target_rate = cpi->Configuration.TargetBandwidth / cpi->Configuration.OutputFrameRate; /* Set key frame data rate target; this is nominal keyframe size */ cpi->Configuration.KeyFrameDataTarget = (c->keyframe_data_target_bitrate * c->fps_denominator / c->fps_numerator ) / 8; /* Note the height and width in the pre-processor control structure. */ cpi->ScanConfig.VideoFrameHeight = cpi->pb.info.height; cpi->ScanConfig.VideoFrameWidth = cpi->pb.info.width; InitFrameDetails(&cpi->pb); InitFilterTables(&cpi->pb); EInitFragmentInfo(cpi); EInitFrameInfo(cpi); /* Set up pre-processor config pointers. */ cpi->ScanConfig.Yuv0ptr = cpi->yuv0ptr; cpi->ScanConfig.Yuv1ptr = cpi->yuv1ptr; cpi->ScanConfig.SrfWorkSpcPtr = cpi->ConvDestBuffer; cpi->ScanConfig.disp_fragments = cpi->pb.display_fragments; cpi->ScanConfig.RegionIndex = cpi->pb.pixel_index_table; /* Initialise the pre-processor module. */ ScanYUVInit(&cpi->pp, &(cpi->ScanConfig)); /* Initialise Motion compensation */ InitMotionCompensation(cpi); /* Initialise the compression process. */ /* We always start at frame 1 */ cpi->CurrentFrame = 1; /* Reset the rate targeting correction factor. */ cpi->BpbCorrectionFactor = 1.0; cpi->TotalByteCount = 0; cpi->TotalMotionScore = 0; /* Up regulation variables. */ cpi->FinalPassLastPos = 0; /* Used to regulate a final unrestricted pass. */ cpi->LastEndSB = 0; /* Where we were in the loop last time. */ cpi->ResidueLastEndSB = 0; /* Where we were in the residue update loop last time. */ InitHuffmanSet(&cpi->pb); /* This makes sure encoder version specific tables are initialised */ InitQTables(&cpi->pb); /* Indicate that the next frame to be compressed is the first in the current clip. */ cpi->ThisIsFirstFrame = 1; cpi->readyflag = 1; return 0;}int theora_encode_YUVin(theora_state *t, yuv_buffer *yuv){ ogg_int32_t i; unsigned char *LocalDataPtr; unsigned char *InputDataPtr; CP_INSTANCE *cpi=(CP_INSTANCE *)(t->internal_encode); if(!cpi->readyflag)return OC_EINVAL; if(cpi->doneflag)return OC_EINVAL; /* If frame size has changed, abort out for now */ if (yuv->y_height != (int)cpi->pb.info.height || yuv->y_width != (int)cpi->pb.info.width ) return(-1); /* Copy over input YUV to internal YUV buffers. */ /* we invert the image for backward compatibility with VP3 */ /* First copy over the Y data */ LocalDataPtr = cpi->yuv1ptr + yuv->y_width*(yuv->y_height - 1); InputDataPtr = yuv->y; for ( i = 0; i < yuv->y_height; i++ ){ memcpy( LocalDataPtr, InputDataPtr, yuv->y_width ); LocalDataPtr -= yuv->y_width; InputDataPtr += yuv->y_stride; } /* Now copy over the U data */ LocalDataPtr = &cpi->yuv1ptr[(yuv->y_height * yuv->y_width)]; LocalDataPtr += yuv->uv_width*(yuv->uv_height - 1); InputDataPtr = yuv->u; for ( i = 0; i < yuv->uv_height; i++ ){ memcpy( LocalDataPtr, InputDataPtr, yuv->uv_width ); LocalDataPtr -= yuv->uv_width; InputDataPtr += yuv->uv_stride; } /* Now copy over the V data */ LocalDataPtr = &cpi->yuv1ptr[((yuv->y_height*yuv->y_width)*5)/4]; LocalDataPtr += yuv->uv_width*(yuv->uv_height - 1); InputDataPtr = yuv->v; for ( i = 0; i < yuv->uv_height; i++ ){ memcpy( LocalDataPtr, InputDataPtr, yuv->uv_width ); LocalDataPtr -= yuv->uv_width; InputDataPtr += yuv->uv_stride; } /* Special case for first frame */ if ( cpi->ThisIsFirstFrame ){ CompressFirstFrame(cpi); cpi->ThisIsFirstFrame = 0; cpi->ThisIsKeyFrame = 0; } else { /* don't allow generating invalid files that overflow the p-frame shift, even if keyframe_auto_p is turned off */ if(cpi->LastKeyFrame >= (ogg_uint32_t) cpi->pb.info.keyframe_frequency_force) cpi->ThisIsKeyFrame = 1; if ( cpi->ThisIsKeyFrame ) { CompressKeyFrame(cpi); cpi->ThisIsKeyFrame = 0; } else { /* Compress the frame. */ CompressFrame( cpi ); } } /* Update stats variables. */ cpi->LastFrameSize = oggpackB_bytes(cpi->oggbuffer); cpi->CurrentFrame++; cpi->packetflag=1; t->granulepos= ((cpi->CurrentFrame-cpi->LastKeyFrame-1)<<cpi->pb.keyframe_granule_shift)+ cpi->LastKeyFrame-1; return 0;}int theora_encode_packetout( theora_state *t, int last_p, ogg_packet *op){ CP_INSTANCE *cpi=(CP_INSTANCE *)(t->internal_encode); long bytes=oggpackB_bytes(cpi->oggbuffer); if(!bytes)return(0); if(!cpi->packetflag)return(0); if(cpi->doneflag)return(-1);#ifndef LIBOGG2 op->packet=oggpackB_get_buffer(cpi->oggbuffer);#else op->packet=oggpackB_writebuffer(cpi->oggbuffer);#endif op->bytes=bytes; op->b_o_s=0; op->e_o_s=last_p; op->packetno=cpi->CurrentFrame; op->granulepos=t->granulepos; cpi->packetflag=0; if(last_p)cpi->doneflag=1; return 1;}static void _tp_writebuffer(oggpack_buffer *opb, const char *buf, const long len){ long i; for (i = 0; i < len; i++) oggpackB_write(opb, *buf++, 8);}static void _tp_writelsbint(oggpack_buffer *opb, long value){ oggpackB_write(opb, value&0xFF, 8); oggpackB_write(opb, value>>8&0xFF, 8); oggpackB_write(opb, value>>16&0xFF, 8); oggpackB_write(opb, value>>24&0xFF, 8);}/* build the initial short header for stream recognition and format */int theora_encode_header(theora_state *t, ogg_packet *op){ CP_INSTANCE *cpi=(CP_INSTANCE *)(t->internal_encode); int offset_y;#ifndef LIBOGG2 oggpackB_reset(cpi->oggbuffer);#else oggpackB_writeinit(cpi->oggbuffer, cpi->oggbufferstate);#endif oggpackB_write(cpi->oggbuffer,0x80,8); _tp_writebuffer(cpi->oggbuffer, "theora", 6); oggpackB_write(cpi->oggbuffer,VERSION_MAJOR,8); oggpackB_write(cpi->oggbuffer,VERSION_MINOR,8); oggpackB_write(cpi->oggbuffer,VERSION_SUB,8); oggpackB_write(cpi->oggbuffer,cpi->pb.info.width>>4,16); oggpackB_write(cpi->oggbuffer,cpi->pb.info.height>>4,16); oggpackB_write(cpi->oggbuffer,cpi->pb.info.frame_width,24); oggpackB_write(cpi->oggbuffer,cpi->pb.info.frame_height,24); oggpackB_write(cpi->oggbuffer,cpi->pb.info.offset_x,8); /* Applications use offset_y to mean offset from the top of the image; the * meaning in the bitstream is the opposite (from the bottom). Transform. */ offset_y = cpi->pb.info.height - cpi->pb.info.frame_height - cpi->pb.info.offset_y; oggpackB_write(cpi->oggbuffer,offset_y,8); oggpackB_write(cpi->oggbuffer,cpi->pb.info.fps_numerator,32); oggpackB_write(cpi->oggbuffer,cpi->pb.info.fps_denominator,32); oggpackB_write(cpi->oggbuffer,cpi->pb.info.aspect_numerator,24); oggpackB_write(cpi->oggbuffer,cpi->pb.info.aspect_denominator,24); oggpackB_write(cpi->oggbuffer,cpi->pb.info.colorspace,8); oggpackB_write(cpi->oggbuffer,cpi->pb.info.target_bitrate,24); oggpackB_write(cpi->oggbuffer,cpi->pb.info.quality,6); oggpackB_write(cpi->oggbuffer,cpi->pb.keyframe_granule_shift,5); oggpackB_write(cpi->oggbuffer,cpi->pb.info.pixelformat,2); oggpackB_write(cpi->oggbuffer,0,3); /* spare config bits */#ifndef LIBOGG2 op->packet=oggpackB_get_buffer(cpi->oggbuffer);#else op->packet=oggpackB_writebuffer(cpi->oggbuffer);#endif op->bytes=oggpackB_bytes(cpi->oggbuffer); op->b_o_s=1; op->e_o_s=0; op->packetno=0; op->granulepos=0; cpi->packetflag=0; return(0);}/* build the comment header packet from the passed metadata */int theora_encode_comment(theora_comment *tc, ogg_packet *op){ const char *vendor = theora_version_string(); const int vendor_length = strlen(vendor); oggpack_buffer *opb;#ifndef LIBOGG2 opb = _ogg_malloc(sizeof(oggpack_buffer)); oggpackB_writeinit(opb);#else opb = _ogg_malloc(oggpack_buffersize()); oggpackB_writeinit(opb, ogg_buffer_create());#endif oggpackB_write(opb, 0x81, 8); _tp_writebuffer(opb, "theora", 6); _tp_writelsbint(opb, vendor_length); _tp_writebuffer(opb, vendor, vendor_length); _tp_writelsbint(opb, tc->comments); if(tc->comments){ int i; for(i=0;i<tc->comments;i++){ if(tc->user_comments[i]){ _tp_writelsbint(opb,tc->comment_lengths[i]); _tp_writebuffer(opb,tc->user_comments[i],tc->comment_lengths[i]); }else{ oggpackB_write(opb,0,32); } } } op->bytes=oggpack_bytes(opb);#ifndef LIBOGG2 /* So we're expecting the application will free this? */ op->packet=_ogg_malloc(oggpack_bytes(opb)); memcpy(op->packet, oggpack_get_buffer(opb), oggpack_bytes(opb)); oggpack_writeclear(opb);#else op->packet = oggpack_writebuffer(opb); /* When the application puts op->packet into a stream_state object, it becomes the property of libogg2's internal memory management. */#endif _ogg_free(opb); op->b_o_s=0; op->e_o_s=0; op->packetno=0; op->granulepos=0; return (0);}/* build the final header packet with the tables required for decode */int theora_encode_tables(theora_state *t, ogg_packet *op){ CP_INSTANCE *cpi=(CP_INSTANCE *)(t->internal_encode);#ifndef LIBOGG2 oggpackB_reset(cpi->oggbuffer);#else oggpackB_writeinit(cpi->oggbuffer, cpi->oggbufferstate);#endif oggpackB_write(cpi->oggbuffer,0x82,8); _tp_writebuffer(cpi->oggbuffer,"theora",6); WriteFilterTables(&cpi->pb,cpi->oggbuffer); WriteQTables(&cpi->pb,cpi->oggbuffer); WriteHuffmanTrees(cpi->pb.HuffRoot_VP3x,cpi->oggbuffer);#ifndef LIBOGG2 op->packet=oggpackB_get_buffer(cpi->oggbuffer);#else op->packet=oggpackB_writebuffer(cpi->oggbuffer);#endif op->bytes=oggpackB_bytes(cpi->oggbuffer); op->b_o_s=0; op->e_o_s=0; op->packetno=0; op->granulepos=0; cpi->packetflag=0; return(0);}void theora_encoder_clear (CP_INSTANCE * cpi){ if(cpi){ ClearHuffmanSet(&cpi->pb); ClearFragmentInfo(&cpi->pb); ClearFrameInfo(&cpi->pb); EClearFragmentInfo(cpi); EClearFrameInfo(cpi); ClearTmpBuffers(&cpi->pb); ClearPPInstance(&cpi->pp); oggpackB_writeclear(cpi->oggbuffer); _ogg_free(cpi->oggbuffer); _ogg_free(cpi); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -