?? skl_mpg4_enc.cpp
字號:
else Reduced_VOP = -1; } }}void SKL_MP4_ENC_I::Setup_Frame_Params(SKL_MP4_FRAME *Frame){ int Param; // we ask the analyzer for the final non-VOL params. // It might have better hints than we do. Get_Analyzer()->Get_Param( "quant", &Frame->Quant ); Get_Analyzer()->Get_Param( "fcode", &Frame->Fwd_Code ); if (Frame->Coding==B_VOP) Get_Analyzer()->Get_Param( "fcode-bwd", &Frame->Bwd_Code ); if (Frame->Reduced_VOP>=0) Frame->Reduced_VOP = 0; if (Frame->Coding != B_VOP && Frame->Coding != S_VOP) { int Reduc; if (Get_Analyzer()->Get_Param( "reduced-frame", &Reduc)) { if (Reduc>1) Reduc = 1; Frame->Reduced_VOP = Reduc; } } if (Frame->Coding==P_VOP || Frame->Coding==S_VOP) { if (!Get_Analyzer()->Get_Param( "rounding", &Frame->Rounding)) Frame->Rounding ^= 1; } else { if (Frame->Coding==B_VOP) Frame->Rounding = 0; } if (Frame->Coding==S_VOP) { Get_Analyzer()->Get_Param( "gmc-mode", &Param ); if (Param>0) { Frame->Coding = S_VOP; Sprite_Mode = SPRITE_GMC; Get_Analyzer()->Get_Param( "gmc-pts", &Sprite_Nb_Pts); const int (*Warps)[2] = (int (*)[2])Get_Analyzer()->Get_Param( "gmc-warp-pts" ); for(int n=0; n<Sprite_Nb_Pts; ++n) { S_Warp_Pts[n][0] = Warps[n][0]; S_Warp_Pts[n][1] = Warps[n][1]; } } else { Frame->Coding = P_VOP; Sprite_Mode = SPRITE_NONE; } } Get_Analyzer()->Get_Param( "inter-threshold", &_Inter_Coding_Threshold ); Get_Analyzer()->Get_Param( "use-trellis", &Param ); Set_Trellis_Usage(!!Param); Cur->Coding = Frame->Coding; /* TODO: DC_Thresh? Alt_Vert_Scan? ... */}//////////////////////////////////////////////////////////// Main entry point//////////////////////////////////////////////////////////int SKL_MP4_ENC_I::Encode(SKL_BYTE *Buf, int Max_Len){ SKL_ASSERT(Width!=0 && Height!=0 && Get_Analyzer()!=0); if (Last==0) { // no user input. Check if we have a pending B-VOP in store... return 0; } SKL_MP4_FRAME *Frame = this; Cur = Last; // get Input frame Last = 0; // mark it consumed Frame->Time = Cur->Time_Ticks; // set time Cur->Map = All_Maps[Cur_Map].Map; // assign analysis map Cur->MV = All_Maps[Cur_Map].MV; // assign analysis MV map if (++Cur_Map==Nb_Maps) Cur_Map = 0; Future->Map = 0; // sanity check Future->MV = 0; // "" // Analyze new frame -> decide: Coding, MB types, Quant, dQ, ... // 1rst pass: Motion analysis Frame->Coding = Get_Analyzer()->Analyze(this); if (Frame->Coding==I_VOP && _Key_VOL_Headers) _Need_VOL_Header = 1; Setup_VOL_Params(); // might trigger a _Need_VOL_Header // We, as encoder, have the final word about frame Coding type. if (_Need_VOL_Header) { // it's not a real scene change. Just a checkpoint: we must // insert an I-VOP after a VOL header) => Don't reset the MVs! // They might be useful for the next frame analysis. Frame->Coding = I_VOP; } if (Frame->Coding==B_VOP) {} else if (Frame->Coding==S_VOP) {} // 2nd pass for spatial analysis (dQ) Get_Analyzer()->Analyze_dQ(this, Frame->Coding==B_VOP); // Frame params are now ready => code bitstream syntax Setup_Frame_Params(Frame); Code_Frame(Buf, Max_Len, this); // send some stats to the analyzer Get_Analyzer()->Post_Coding_Update( this ); Frame_Number++; // display debug infos if (Debug_Level) { if (Debug_Level==4) Dump_Map(Cur, 0); else if (Debug_Level==5) Dump_Map(Cur, 1); else if (Debug_Level==6) Dump_Map(Cur, 2); } // reorder frames if needed int Ticks; // save current time first, before swapping Get_Analyzer()->Get_Param( "frame-ticks", &Ticks ); SKL_UINT64 Next_Time_Ticks = Cur->Time_Ticks + Ticks; if (Frame->Coding!=B_VOP) { Aux = Past; Past = Cur; Cur = Future; Future = Aux; Aux = Cur; Time_Last_Coded = Past->Time_Ticks; Time_Ref = Past->Time_Ticks / Time_Frequency; // sync-point#if 0 // secure tickers every 65k-ticks, to avoid overflows if (Time_Last_Coded>0x10000) { Time_Ref -= 0x10000; Time_Last_Coded -= 0x10000; Next_Time_Ticks -= 0x10000 * Time_Frequency; }#endif } // setup time of next-to-be-encoded frame, just in // case the user forgets to (or doesn't care doing so). Aux->Time_Ticks = Next_Time_Ticks; Aux->Time = (double)(SKL_INT64)Next_Time_Ticks / (double)(SKL_INT64)Time_Frequency; Aux->Map = 0; // sanity check Aux->MV = 0; // "" Aux->Coding = -1; // sanity check return Coded_Bits/8;}//////////////////////////////////////////////////////////// class SKL_MP4_ENC_I//////////////////////////////////////////////////////////SKL_MP4_ENC_I::SKL_MP4_ENC_I(SKL_MEM_I *Mem) : SKL_MP4_I(Mem) , SKL_MP4_ENC() , _Dflt_Analyzer(Skl_MP4_Get_Default_Analyzer(Mem)){ _Buf_Size = 0; _Buf = 0; _Buf_Len = 0; _In_Pic = 0; _Need_VOL_Header = 1; _Key_VOL_Headers = 0; _Emit_SEQ_Codes = 0; _Analyzer = 0; _Use_Trellis = -1; Set_Trellis_Usage(1); Init_VOL(0); Set_Analyzer( _Dflt_Analyzer ); Clear_Aux();}SKL_MP4_ENC_I::~SKL_MP4_ENC_I(){ Clear_Aux(); Clear_Buf(); if (_Analyzer!=0) _Analyzer->Shut_Down(); _Analyzer = 0; Skl_MP4_Destroy_Default_Analyzer( _Dflt_Analyzer );}SKL_MP4_ANALYZER *SKL_MP4_ENC_I::Set_Analyzer(SKL_MP4_ANALYZER *Anl){ SKL_MP4_ANALYZER *Previous = _Analyzer; if (_Analyzer!=0) _Analyzer->Shut_Down(); _Analyzer = (Anl==0) ? _Dflt_Analyzer : Anl; _Analyzer->Wake_Up(Previous); return Previous;}SKL_MP4_ANALYZER *SKL_MP4_ENC_I::Get_Analyzer() const{ return _Analyzer;}void SKL_MP4_ENC_I::Set_Slicer(SKL_MP4_SLICER Slicer, SKL_ANY Slicer_Data) { SKL_MP4_I::Set_Slicer(Slicer, Slicer_Data);}SKL_MEM_I *SKL_MP4_ENC_I::Set_Memory_Manager(SKL_MEM_I *Mem){ return SKL_MP4_I::Set_Memory_Manager(Mem);}void SKL_MP4_ENC_I::Set_Custom_Matrix(int Intra, const SKL_BYTE *M) { if (Set_Matrix(Intra, M)) _Need_VOL_Header = 1;}int SKL_MP4_ENC_I::Ioctl(SKL_CST_STRING Param){ if (Param==0) return -1; if (!strcmp(Param, "emit-key-headers")) { _Key_VOL_Headers = 1; return 1; } else if (!strcmp(Param, "no-emit-key-headers")) { _Key_VOL_Headers = 0; return 1; } else if (!strcmp(Param, "emit-sequence-codes")) { _Emit_SEQ_Codes = 1; return 1; } else if (!strcmp(Param, "no-emit-sequence-codes")) { _Emit_SEQ_Codes = 0; return 1; } return 0;}//////////////////////////////////////////////////////////void SKL_MP4_ENC_I::Alloc_Aux() { /* nothing more needed, for now */ }void SKL_MP4_ENC_I::Clear_Aux() { /* nothing more needed, for now */ }SKL_MP4_PIC *SKL_MP4_ENC_I::Prepare_For_Input(int W, int H){ if (W<=0 || W>2048 || H<=0 || H>2048) return 0; if (Width!=W || Height!=H) { Init_Pics(W, H, 3, 2); // will store new W/H Alloc_Aux(); // init our own rest _Need_VOL_Header = 1; } // user input is always 'Aux' // Time_Ticks should be ok from last encoding Last = Aux; return Last;}void SKL_MP4_ENC_I::Set_CPU( SKL_CPU_FEATURE Cpu ){ SKL_MP4_I::Set_CPU(Cpu); Set_Trellis_Usage(_Use_Trellis);}void SKL_MP4_ENC_I::Set_Trellis_Usage(const int Do_It){ _Use_Trellis = Do_It;}//////////////////////////////////////////////////////////// Interface Wrappersvoid SKL_MP4_ENC_I::Set_Debug_Level(int Level) { SKL_MP4_I::Set_Debug_Level( Level );}const SKL_MP4_PIC *SKL_MP4_ENC_I::Prepare_Next_Frame(int Width, int Height){ _In_Pic = Prepare_For_Input(Width, Height); return _In_Pic;}const SKL_MP4_PIC *SKL_MP4_ENC_I::Get_Next_Frame() const{ return _In_Pic;}const SKL_MP4_PIC *SKL_MP4_ENC_I::Get_Last_Coded_Frame() const{ return Past; // TODO: this is wrong for B-vop}void SKL_MP4_ENC_I::Get_All_Frames(SKL_MP4_PIC *Pic) const{ SKL_MP4_I::Get_All_Frames(Pic);}int SKL_MP4_ENC_I::Encode(){ size_t Needed_Size = (_In_Pic->Width*_In_Pic->Height)*2; // TODO: safety factor? int Buf_Size_Max = 0; if (Get_Analyzer()->Get_Param("buffer-size", &Buf_Size_Max)) if (Buf_Size_Max>0 && Needed_Size>(size_t)Buf_Size_Max) Needed_Size = Buf_Size_Max; if (Needed_Size<4096) Needed_Size = 4096; Check_Buf_Size( Needed_Size ); _Buf_Len = Encode(_Buf, _Buf_Len); return _Buf_Len;}int SKL_MP4_ENC_I::Finish_Encoding(){ // TODO: Check for a pending B-VOP... // TODO: should we emit a SEQ_END code? if (_Emit_SEQ_Codes) { SKL_FBB Bits(_Buf); Bits.Put_DWord(SEQ_END_CODE); _Buf_Len = 4; return 4; } return 0;}const SKL_BYTE *SKL_MP4_ENC_I::Get_Bits() const { return _Buf;}int SKL_MP4_ENC_I::Get_Bits_Length() const { return _Buf_Len;}void SKL_MP4_ENC_I::Check_Buf_Size(const size_t Needed_Size){ if (Needed_Size>_Buf_Size) { SKL_BYTE *New_Buf = (Mem!=0) ? (SKL_BYTE*)Mem->New( Needed_Size ) : (SKL_BYTE*)malloc( Needed_Size ); if (New_Buf==0) Skl_Throw( SKL_MEM_EXCEPTION("Byte buffer", Needed_Size) ); if (_Buf_Len>0) SKL_MEMCPY(New_Buf, _Buf, _Buf_Len); Clear_Buf(); _Buf = New_Buf; _Buf_Size = Needed_Size; } else { // TODO: shrink the _Buf from time to time? }}void SKL_MP4_ENC_I::Clear_Buf() { if (_Buf_Size>0) { if (Mem) Mem->Delete( _Buf, _Buf_Size ); else free( _Buf ); } _Buf_Size = 0; _Buf = 0; /* Don't touch _Len, here. We might just be swapping buffers.. */}//////////////////////////////////////////////////////////// SKL_MP4_ENC//////////////////////////////////////////////////////////SKL_MP4_ENC::SKL_MP4_ENC() {}SKL_MP4_ENC::~SKL_MP4_ENC() {}//////////////////////////////////////////////////////////// C factoryextern "C" {SKL_EXPORTSKL_MP4_ENC *Skl_MP4_New_Encoder() { return (SKL_MP4_ENC*)::new SKL_MP4_ENC_I((SKL_MEM_I*)0);}SKL_EXPORTvoid Skl_MP4_Delete_Encoder(SKL_MP4_ENC *Enc) { ::delete (SKL_MP4_ENC_I*)Enc; }} // extern "C"//////////////////////////////////////////////////////////
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -