#include #include #include #include #include #include #include "mfxvideo.h" static void _initEncParam(mfxVideoParam *par); int main(int argc, char **argv) { int useHW = 1; int i,j; char type; mfxIMPL impl; mfxStatus sts; mfxVersion ver; mfxSession session; mfxSyncPoint sync; mfxBitstream bs; mfxVideoParam par; mfxFrameAllocRequest request; mfxFrameSurface1 *surfaces; FILE *fid = NULL; HANDLE pHandle; PROCESS_MEMORY_COUNTERS memInfoStart; PROCESS_MEMORY_COUNTERS memInfoNow; time_t tic,toc; int elapsed = 0; // Usage "msdkMem -s" use software only // Usage "msdkMem -h" use hardware only // Usage "msdkMem" uses hardware if (argc > 1) useHW = (argv[1][1] != 's'); if (argc > 2) { fid = fopen(argv[2],"wb"); if (fid == NULL) { fprintf(stderr, "Could not open %s\n", argv[2]); return(-1); } } ver.Major = 1; ver.Minor = 1; // Create MSDK session impl = (useHW == 1) ? MFX_IMPL_HARDWARE_ANY:MFX_IMPL_SOFTWARE; sts = MFXInit(impl,&ver, &session); if (sts != MFX_ERR_NONE) { fprintf(stderr,"Could not init session:%d\n", sts); return(-1); } else { MFXQueryVersion(session, &ver); MFXQueryIMPL(session,&impl); fprintf(stderr,"Using %s version %d.%d\n", (impl == MFX_IMPL_SOFTWARE) ? "SW":"HW", ver.Major, ver.Minor); } // Create encoder _initEncParam(&par); sts = MFXVideoENCODE_Init(session, &par); if (sts == MFX_WRN_PARTIAL_ACCELERATION) { fprintf(stderr, "WARNING: Full acceleration is not being used\n"); sts = MFX_ERR_NONE; } if (sts != MFX_ERR_NONE) { fprintf(stderr,"Could not create encoder:%d\n",sts); return(-1); } // Allocate dummy memory resources memset(&request, 0, sizeof(mfxFrameAllocRequest)); sts = MFXVideoENCODE_QueryIOSurf(session, &par, &request); if (sts != MFX_ERR_NONE) { fprintf(stderr,"Error determining required buffer size:%d\n", sts); return(-1); } else { fprintf(stderr,"%d buffers suggested\n",request.NumFrameSuggested); } surfaces = (mfxFrameSurface1 *) calloc(request.NumFrameSuggested, sizeof(mfxFrameSurface1)); for (i = 0;i < request.NumFrameSuggested;i++) { unsigned char *data; data = (unsigned char *) _aligned_malloc((1920*1088*3)/2, 128); surfaces[i].Data.Y = data; surfaces[i].Data.UV = data + 1920*1088; surfaces[i].Data.Pitch = 1920; surfaces[i].Info = par.mfx.FrameInfo; } bs.MaxLength = 1100*1000; bs.Data = malloc(bs.MaxLength); i = 0; j = 0; // Encode frames until end of time fprintf(stderr,"Starting frame encode\n"); fprintf(stderr,"Elapsed (s) DeltaMemory\n"); pHandle = GetCurrentProcess(); tic = time(NULL); while (1) { int fidx; // Show memory delta periodically toc = time(NULL); if ((toc - tic) >= elapsed) { int dt; int dm; if (elapsed <= 10) { GetProcessMemoryInfo(pHandle, &memInfoStart, sizeof(memInfoStart)); } else { GetProcessMemoryInfo(pHandle, &memInfoNow, sizeof(memInfoNow)); dt = (int) (toc - tic - 20); dm = memInfoNow.WorkingSetSize - memInfoStart.WorkingSetSize; fprintf(stderr,"%11d %11d\n",dt,dm); } elapsed += 10; } // Find a free buffer for (fidx = 0;fidx < request.NumFrameSuggested;fidx++) if (surfaces[fidx].Data.Locked == 0) break; if (fidx == request.NumFrameSuggested) { fprintf(stderr,"Ran out of buffers?\n"); return(-1); } // Fill buffer with dummy data memset(surfaces[fidx].Data.Y,j*16, (1920*1088*3)/2); j++; // Start one frame encode bs.DataOffset = 0; bs.DataLength = 0; do { sts = MFXVideoENCODE_EncodeFrameAsync(session, NULL, &surfaces[fidx], &bs, &sync); } while (sts == MFX_WRN_DEVICE_BUSY); if (sts == MFX_ERR_MORE_DATA) continue; if (sts == MFX_ERR_NONE) { // Wait for encode to finish do { sts = MFXVideoCORE_SyncOperation(session, sync, 1); } while (sts == MFX_WRN_IN_EXECUTION); if (sts != MFX_ERR_NONE) { fprintf(stderr,"Sync failed with %d\n", sts); return(-1); } // Show frame information switch (bs.FrameType & 0xf) { case MFX_FRAMETYPE_I: type = 'I'; break; case MFX_FRAMETYPE_P: type = 'P'; break; case MFX_FRAMETYPE_B: type = 'B'; break; default: type = '?'; break; } // fprintf(stderr,"Frame %03d of type %c is %6d bytes\n", i, type,bs.DataLength); if (fid) { fwrite(&bs.Data[bs.DataOffset], bs.DataLength, 1, fid); fflush(fid); } i++; } else { fprintf(stderr,"MFXVideoENCODE_EncodeFrameAsync failed with %d\n", sts); } } return(0); } // Configure encoder for MPEG2 with 1080i input, 16 Mb/s out static void _initEncParam(mfxVideoParam *par) { mfxExtCodingOption *option; mfxExtCodingOption **option_array; memset(par, 0, sizeof(mfxVideoParam)); par->AsyncDepth = 0; par->IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY; option = (mfxExtCodingOption *) malloc(sizeof(mfxExtCodingOption)); option_array = (mfxExtCodingOption**) malloc(sizeof(mfxExtCodingOption*)); memset(option, 0, sizeof(mfxExtCodingOption)); option->Header.BufferId = MFX_EXTBUFF_CODING_OPTION; option->Header.BufferSz = sizeof(mfxExtCodingOption); option->FramePicture = MFX_CODINGOPTION_ON; option_array[0] = option; par->ExtParam = (mfxExtBuffer **) option_array; par->NumExtParam = 1; par->mfx.BRCParamMultiplier = 0; par->mfx.CodecId = MFX_CODEC_MPEG2; par->mfx.CodecProfile = MFX_PROFILE_MPEG2_MAIN; par->mfx.CodecLevel = MFX_LEVEL_MPEG2_HIGH; par->mfx.NumThread = 0; par->mfx.TargetUsage = MFX_TARGETUSAGE_BEST_QUALITY; par->mfx.TargetKbps = 12000; par->mfx.GopPicSize = 15; par->mfx.GopRefDist = 3; par->mfx.GopOptFlag = 0; par->mfx.IdrInterval = 1; par->mfx.RateControlMethod = (mfxU16) MFX_RATECONTROL_CBR; par->mfx.EncodedOrder = 0; par->mfx.FrameInfo.FourCC = MFX_FOURCC_NV12; par->mfx.FrameInfo.Width = 1920; par->mfx.FrameInfo.Height = 1088; par->mfx.FrameInfo.CropX = 0; par->mfx.FrameInfo.CropY = 0; par->mfx.FrameInfo.CropW = 1920; par->mfx.FrameInfo.CropH = 1088; par->mfx.FrameInfo.FrameRateExtD = 1001; par->mfx.FrameInfo.FrameRateExtN = 30000; par->mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_FIELD_TFF; par->mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420; }