📄 tmp4.cpp
字号:
/******************************************************** * Some code. Copyright (C) 2003 by Pascal Massimino. * * All Rights Reserved. (http://skal.planet-d.net) * * For Educational/Academic use ONLY. See 'LICENSE.TXT'.* ********************************************************//* * MPEG4 codec front end example * ********************************************************/#include "skl_utils.h"#include "skl_syst/skl_mpg4.h"#include "skl_syst/skl_dyn_load.h"#include "skl_syst/skl_exception.h"#include "skl_syst/skl_ptimer.h"#include "skl_syst/skl_mem_trc.h"#include "skl_syst/skl_dsp.h"#include "skl_syst/skl_cpu_specs.h"#include "skl_2d/skl_btm.h"#include "skl_2d/skl_window.h"#include <math.h>//////////////////////////////////////////////////////////// DLL declaration for codecs////////////////////////////////////////////////////////// // plug-in to use for codec#ifndef _WINDOWS#define SKL_MP4_DLL_NAME "libskl_mp4"#else#define SKL_MP4_DLL_NAME "skl_drv_mpg"#endifSKL_DYN_LIBRARY(SKL_MP4_DLL, SKL_MP4_DLL_NAME, 0100); // DLL symbols to mapSKL_MP4_NEW_DEC MP4_New_Decoder;SKL_MP4_DELETE_DEC MP4_Delete_Decoder;SKL_MP4_NEW_ENC MP4_New_Encoder;SKL_MP4_DELETE_ENC MP4_Delete_Encoder;////////////////////////////////////////////////////////////// -- global params////////////////////////////////////////////////////////////#define VERSION 0.23fint Save, Show, With_Slices, From_Mem, Trace_Mem, MPEG12;int To_RGB;int Nb_Frames, Skip_Frames;int Streaming;int Sequence_Codes;long Jump_To;int Global_Q;int Interlace_DCT; // 0=disabled, 1=decide, 2=forceint Interlace_Field; // 0=disabled, 1=decide, 2=forceint Sub_Pixel;float dQuant_Amp;float Lambda;int Inter_Thresh;int Use_Trellis;int Intra_Max;int Inter4V_Probing, Field_Pred_Probing;int SAD_Skip_Limit;int SAD_Intra_Limit;int Search_Metric;int MV_Size;int Enc_Buf_Size;int Use_GMC;int Hi_Mem;int GMC_Accuracy;int Use_Reduced;int Quant_Type;int Bit_Rate;float FPS;int System_Stream; // 0: none, 1:AVI, 2:MPGint Search_Method;int Intra_Limit;int Delay;int VTrace, Debug, ADebug, Quiet;int Show_PSNR;int Transfer_Type;int Edge_Detect;int YUV_Input, YUV_W, YUV_H;SKL_CST_STRING In_File, Out_File, Pass_File, Ref_YUV_File;SKL_CPU_FEATURE Cpu;SKL_IMG_DSP Img_Dsp = {0};SKL_YUV_DSP YUV_Dsp = {0};int Pass_Nb;float Pass_RF;const char *Custom_Matrix = 0;SKL_MEM_I *All_Mem = 0; // memory pool////////////////////////////////////////////////////////////// YUV/PGM input and output////////////////////////////////////////////////////////////static void YUV_Out(SKL_MP4_PIC *Pic){ SKL_BYTE *Src = Pic->Y; int k = Pic->Height; while(k-->0) { fwrite(Src, Pic->Width, 1, stdout); Src += Pic->BpS; } Src = Pic->U; for(k = Pic->Height/2; k>0; --k) { fwrite(Src, Pic->Width/2, 1, stdout); Src += Pic->BpS; } Src = Pic->V; for(k = Pic->Height/2; k>0; --k) { fwrite(Src, Pic->Width/2, 1, stdout); Src += Pic->BpS; }}static void PGM_Out(SKL_MP4_PIC *Pic){ fprintf(stdout, "P5\n\n%d %d\n255\n", Pic->Width, Pic->Height*3/2 ); SKL_BYTE *Src = Pic->Y; int k = Pic->Height; while(k-->0) { fwrite(Src, Pic->Width, 1, stdout); Src += Pic->BpS; } k = Pic->Height/2; SKL_BYTE *USrc = Pic->U; SKL_BYTE *VSrc = Pic->V; while(k-->0) { fwrite(USrc, Pic->Width/2, 1, stdout); fwrite(VSrc, Pic->Width/2, 1, stdout); USrc += Pic->BpS; VSrc += Pic->BpS; }}static int PGM_In(SKL_MP4_ENC *Enc, FILE *In, int *W, int *H, double Time){ const SKL_MP4_PIC *Pic; SKL_BYTE *Dst; int k; if (!YUV_Input) { int Tmp; if (fscanf(In, "P5\n%d %d\n%d", W, H, &Tmp )!=3) return 0; if (Tmp!=255 || *W<=0 || *H<=0) return 0; fgetc(In); // skips the '\n' Pic = Enc->Prepare_Next_Frame(*W, (*H)*2/3); if (Pic==0) return 0; for(Dst = Pic->Y, k=0; k<Pic->Height; ++k) { if (fread(Dst, Pic->Width, 1, In)!=1) return 0; Dst += Pic->BpS; } SKL_BYTE *DstU = Pic->U; SKL_BYTE *DstV = Pic->V; for(k=0; k<Pic->Height/2; ++k) { if (fread(DstU, Pic->Width/2, 1, In)!=1) return 0; if (fread(DstV, Pic->Width/2, 1, In)!=1) return 0; DstU += Pic->BpS; DstV += Pic->BpS; } } else { *W = YUV_W; *H = YUV_H * 3/2; Pic = Enc->Prepare_Next_Frame(YUV_W, YUV_H); if (Pic==0) return 0; for(Dst = Pic->Y, k=0; k<Pic->Height; ++k) { if (fread(Dst, Pic->Width, 1, In)!=1) return 0; Dst += Pic->BpS; } for(Dst = Pic->U, k=0; k<Pic->Height/2; ++k) { if (fread(Dst, Pic->Width/2, 1, In)!=1) return 0; Dst += Pic->BpS; } for(Dst = Pic->V, k=0; k<Pic->Height/2; ++k) { if (fread(Dst, Pic->Width/2, 1, In)!=1) return 0; Dst += Pic->BpS; } } if (Edge_Detect==1) { if (Img_Dsp.Name==0) Skl_Init_Img_DSP(&Img_Dsp, Cpu); SKL_BYTE *Dst = Pic->Y; const int BpS = Pic->BpS; int x, y; for(y=0; y<Pic->Height/16; y++) for(x=0; x<Pic->Width/16; x++) Img_Dsp.Grad2_18x18_To_8x8(Dst+(x+y*BpS)*8, BpS, Dst+(x+y*BpS)*16, BpS); } return 1;}////////////////////////////////////////////////////////////// YUV => RGB and display////////////////////////////////////////////////////////////static void YUV_To_RGB32(SKL_BTM &Btm, const SKL_MP4_PIC &Pic){ if (YUV_Dsp.Name==0) { Skl_Init_YUV_DSP(&YUV_Dsp, Cpu); YUV_Dsp.Init(Transfer_Type); } SKL_BYTE *Dst = Btm.Lock(); const int BpS = Btm.BpS(); if (Btm.Format()==0x40888) YUV_Dsp.YUV_TO_RGB32(Dst, BpS, Pic.Y, Pic.U, Pic.V, Pic.BpS, Pic.Width, Pic.Height); else if (Btm.Format()==0x20565) YUV_Dsp.YUV_TO_RGB565(Dst, BpS, Pic.Y, Pic.U, Pic.V, Pic.BpS, Pic.Width, Pic.Height); YUV_Dsp.Switch_Off(); /* else: not supported yet */ Btm.Unlock();}static void Deal_With_Pic(SKL_MP4_PIC &Pic, int Nb){ int W = Pic.Width; int H = Pic.Height; int BpS = Pic.BpS; SKL_BYTE *Src = Pic.Y; if (VTrace==2) { Src = Pic.U; H /= 2; } else if (VTrace==3) { Src = Pic.Y - 16 - 16*BpS; W += 2*16; H = H+16+16 + H/2+8+8; } if (Save==2) PGM_Out(&Pic); else if (Save==3) YUV_Out(&Pic); if (Show && VTrace==0) {#ifndef SKL_NO_VIDEO if (To_RGB==0x40888) { SKL_WINDOW *Vid = Sku_Get_Video(W, H, 0x40888); YUV_To_RGB32(*Vid, Pic); if (Save==1) Sku_Dump_Pic(Vid); } else if (To_RGB==0x20565) { SKL_WINDOW *Vid = Sku_Get_Video(W, H, 0x20565); YUV_To_RGB32(*Vid, Pic); if (Save==1) Sku_Dump_Pic(Vid); }#endif } else if (Show||Save) { static SKL_CMAP_X Cmap; static int Ok = 0; if (!Ok) { Cmap.Ramp( SKL_COLOR_BLACK, SKL_COLOR_WHITE ); Ok = 1; } SKL_BTM Btm(All_Mem); Btm.Set_Virtual(W, H, 0x10000, Src, BpS, &Cmap);#ifndef SKL_NO_VIDEO if (Show) Sku_Show_Pic(&Btm);#endif if (Save==1) Sku_Dump_Pic(&Btm); }}////////////////////////////////////////////////////////////// Decoding////////////////////////////////////////////////////////////struct PSNR_INFOS{ double PSNR_Y,PSNR_U,PSNR_V,PSNR_A; double pY, pU, pV, pA; size_t Size; int Cnt; SKL_BYTE *Y, *U, *V; FILE *_File; void Store(SKL_BYTE *Dst, const SKL_BYTE *Src, int W, int H, int BpS) { W = (W+7) & ~7; for(int y=0; y<H; ++y, Src+=BpS, Dst+=BpS) SKL_MEMCPY(Dst, Src, W); } void Load(SKL_BYTE *Dst, SKL_CST_STRING YUV_In, int W, int H, int BpS) { if (_File==0) { _File = fopen( YUV_In, "rb" ); if (_File==0) Skl_Throw( SKL_EXCEPTION( "Can't open Reference YUV file\n" ) ); } const int W_Padded = (W+7) & ~7; for(int y=0; y<H; ++y, Dst+=BpS) { fread(Dst, W, 1, _File); for(int x=W; x<W_Padded; ++x) Dst[x] = 0; } } SKL_UINT32 Get_SSE(SKL_BYTE *Ref, const SKL_BYTE *Src, int W, int H, int BpS) { SKL_UINT32 SSE = 0; int x,y; for(y=0; (y+16)<=H; y+=16) { for(x=0; (x+16)<=W; x+=16) SSE += Img_Dsp.SSD_16x16(Ref+x,Src+x,BpS); if ((x+8)<=W) SSE += Img_Dsp.SSD_8x8(Ref+x,Src+x,BpS); Src += 16*BpS; Ref += 16*BpS; } if ((y+8)<=H) for(x=0; x<W; x+=8) SSE += Img_Dsp.SSD_8x8(Ref+x,Src+x,BpS); return SSE; } double Compute_PSNR(int Val, int Size) { return Val>0. ? -4.3429448*log( 1.*Val / (255.*255.*Size) ) : 0.; } void Check(int W, int H, int BpS) { const size_t Needed = BpS*H + 2*(BpS/2)*(H/2); if (Y==0 || Size!=Needed) { Clear(); Y = (SKL_BYTE*)All_Mem->New(Needed); U = Y + BpS*H; V = U + BpS/2; Size = Needed; } if (Img_Dsp.Name==0) Skl_Init_Img_DSP(&Img_Dsp, Cpu); } void Clear() { if (Y!=0) { All_Mem->Delete( Y, Size ); Y=0; Size=0; } } void Print_Infos() { SKL_ASSERT(Cnt>0); if (Cnt==1) printf( "#frm \tY U V All avrg:Y U V All\n" ); printf( "%d \t%.3f %.3f %.3f %.3f \t%.3f %.3f %.3f %.3f\n", Cnt, pY, pU, pV, pA, PSNR_Y/Cnt, PSNR_U/Cnt, PSNR_V/Cnt, PSNR_A/Cnt); } PSNR_INFOS() { Size = 0; Y=U=V=0; Cnt = 0; PSNR_Y = PSNR_U = PSNR_V = PSNR_A = 0.; _File = 0; } ~PSNR_INFOS() { if (_File!=0) fclose(_File); Clear(); }};////////////////////////////////////////////////////////////// compare PSNR against ref file////////////////////////////////////////////////////////////static void Compare_PSNR_External(const SKL_MP4_PIC *Pic, PSNR_INFOS *I){ SKL_ASSERT(Ref_YUV_File!=0); I->Check(Pic->Width, Pic->Height, Pic->BpS); I->Load(I->Y, Ref_YUV_File, Pic->Width, Pic->Height, Pic->BpS); I->Load(I->U, Ref_YUV_File, Pic->Width/2, Pic->Height/2, Pic->BpS); I->Load(I->V, Ref_YUV_File, Pic->Width/2, Pic->Height/2, Pic->BpS); SKL_UINT32 SSE_Y = I->Get_SSE(I->Y, Pic->Y, Pic->Width, Pic->Height, Pic->BpS); SKL_UINT32 SSE_U = I->Get_SSE(I->U, Pic->U, Pic->Width/2, Pic->Height/2, Pic->BpS); SKL_UINT32 SSE_V = I->Get_SSE(I->V, Pic->V, Pic->Width/2, Pic->Height/2, Pic->BpS); Img_Dsp.Switch_Off(); I->PSNR_Y += I->pY = I->Compute_PSNR(SSE_Y, Pic->Width*Pic->Height); I->PSNR_U += I->pU = I->Compute_PSNR(SSE_U, Pic->Width*Pic->Height/4); I->PSNR_V += I->pV = I->Compute_PSNR(SSE_V, Pic->Width*Pic->Height/4); I->PSNR_A += I->pA = I->Compute_PSNR(SSE_Y+SSE_U+SSE_V, 3*Pic->Width*Pic->Height/2); I->Cnt++; if (I->Cnt==10000) { // reset every ~10000 frames, to avoid overflow... // (yeah, I know, we won't end up with the real PSNR :) I->PSNR_Y /= I->Cnt; I->PSNR_U /= I->Cnt; I->PSNR_V /= I->Cnt; I->PSNR_A /= I->Cnt; I->Cnt = 1; } I->Print_Infos();}////////////////////////////////////////////////////////////// simple empty example of slicer hook////////////////////////////////////////////////////////////static void Display_Slice(const SKL_MP4_PIC *Pic, int y, int Height, SKL_ANY Data){ printf( "Slice y=%3d/%3d (height=%d)\n", y, Pic->Height, Height );}////////////////////////////////////////////////////////////// naive AVI parsing////////////////////////////////////////////////////////////static SKL_UINT32 Get32b_LE(FILE *f) { return ((SKL_UINT32)fgetc(f)<<0) | (fgetc(f)<<8) | (fgetc(f)<<24) | (fgetc(f)<<24);}static SKL_UINT16 Get16b_LE(FILE *f) { return (fgetc(f)<<0) | (fgetc(f)<<8);}static SKL_UINT32 TwoCC(const char * const S) { return (S[0]<<0) | (S[1]<<8);}static SKL_UINT32 FourCC(const char * const S) { return (S[0]<<24) | (S[1]<<16) | (S[2]<<8) | (S[3]<<0);}static int Locate_Marker(SKL_UINT32 Marker, FILE *f) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -