📄 encoder_toplevel.c
字号:
cpi->MotionCompensation = 1;
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);
/* 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, int *fixedq, int *keyframe){
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;
cpi->wasKeyframe=0;
if (*fixedq!=-1)
cpi->FixedQ=cpi->pb.QThreshTable[*fixedq];
/* 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;
cpi->wasKeyframe=1;
} 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;
*fixedq=cpi->pb.FrameQIndex;
t->granulepos=
((cpi->CurrentFrame-cpi->LastKeyFrame-1)<<cpi->pb.keyframe_granule_shift)+
cpi->LastKeyFrame-1;
*keyframe=cpi->wasKeyframe;
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);
#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);
oggpackB_write(cpi->oggbuffer,cpi->pb.info.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=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 + -