Media (Intel® Video Processing Library, Intel Media SDK)
Access community support with transcoding, decoding, and encoding in applications using media tools like Intel® oneAPI Video Processing Library and Intel® Media SDK
Announcements
The Intel Media SDK project is no longer active. For continued support and access to new features, Intel Media SDK users are encouraged to read the transition guide on upgrading from Intel® Media SDK to Intel® Video Processing Library (VPL), and to move to VPL as soon as possible.
For more information, see the VPL website.

SDK H264 session sync

Dirk_S_
Beginner
767 Views

Dear all,

I try to write a very simple example of the sample_encode. Reading the same YUV file, NV12, using the same parameters. But after m_mfxSession.SyncOperation( encSync, MSDK_WAIT_INTERVAL); the mfxBitstream isn't updated.

sample_encode return and sync after the first 5 calls to m_pmfxENC->EncodeFrameAsync(NULL, &frameSurface1, &bitStream, &encSync); in sample encode and in my program:

0, 0x400                                    0, 0x400

-10, 0xC00                                -10, 0xC02

0, 0x1000                                  0, 0x1003

0, 0x1400                                  0, 0x1404

0, 0x1800                                  0, 0x1805

DataLength isn't filled after the first call in my program. So sync seems to be the problem.

#include "stdafx.h"
#include "erzeugen.h"
//#include"GdiplusEnv.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// Das einzige Anwendungsobjekt

CWinApp theApp;

using namespace std;

// Einstellungen - Verzeichnisse - header....
#include "mfxcommon.h"
#include "mfxmvc.h"
#include "mfxvideo.h"
#include "mfxvp8.h"
#include "mfxvideo++.h"
#include "mfxplugin.h"
#include "mfxplugin++.h"


#define IMG_WIDTH	1024
#define IMG_HEIGHT	1224

#define MSDK_ALIGN16(value)                      (((value + 15) >> 4) << 4) // round up to a multiple of 16
#define MSDK_ALIGN32(value)                      (((value + 31) >> 5) << 5) // round up to a multiple of 32

#define MSDK_DEC_WAIT_INTERVAL 60000
#define MSDK_ENC_WAIT_INTERVAL 10000
#define MSDK_VPP_WAIT_INTERVAL 60000
#define MSDK_WAIT_INTERVAL MSDK_DEC_WAIT_INTERVAL+3*MSDK_VPP_WAIT_INTERVAL+MSDK_ENC_WAIT_INTERVAL // an estimate for the longest pipeline we have in samples

#pragma comment(lib, "libmfx.lib")

// Linker - Eingabe - Standard Bib ingnorieren -> msvcrt.lib;msvcrtd.lib;libcmt.lib

class CSmplBitstreamWriter
{
public :

    CSmplBitstreamWriter();
    virtual ~CSmplBitstreamWriter();

    virtual mfxStatus Init(const wchar_t *strFileName);
    virtual mfxStatus WriteNextFrame(mfxBitstream *pMfxBitstream, bool isPrint = true);
    virtual void Close();
    mfxU32 m_nProcessedFramesNum;

protected:
    HANDLE		m_fSource;
    bool        m_bInited;
};

CSmplBitstreamWriter::CSmplBitstreamWriter()
{
    m_fSource = INVALID_HANDLE_VALUE;
    m_bInited = false;
    m_nProcessedFramesNum = 0;
}

CSmplBitstreamWriter::~CSmplBitstreamWriter()
{
    Close();
}

void CSmplBitstreamWriter::Close()
{
    if( m_fSource != INVALID_HANDLE_VALUE )
    {
		CloseHandle(m_fSource);
        m_fSource = INVALID_HANDLE_VALUE;
    }

    m_bInited = false;
    m_nProcessedFramesNum = 0;
}

mfxStatus CSmplBitstreamWriter::Init(const wchar_t *strFileName)
{
    Close();

    //init file to write encoded data
	m_fSource= CreateFile( strFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
		FILE_ATTRIBUTE_NORMAL, NULL);
    
    //set init state to true in case of success
    m_bInited = true;
    return MFX_ERR_NONE;
}

mfxStatus CSmplBitstreamWriter::WriteNextFrame(mfxBitstream *pMfxBitstream, bool isPrint)
{
    // check if writer is initialized

    DWORD nBytesWritten = 0;

	WriteFile( m_fSource, pMfxBitstream->Data + pMfxBitstream->DataOffset, pMfxBitstream->DataLength, &nBytesWritten, NULL);
    //nBytesWritten = (mfxU32)fwrite(pMfxBitstream->Data + pMfxBitstream->DataOffset, 1, pMfxBitstream->DataLength, m_fSource);
    //MSDK_CHECK_NOT_EQUAL(nBytesWritten, pMfxBitstream->DataLength, MFX_ERR_UNDEFINED_BEHAVIOR);

    // mark that we don't need bit stream data any more
    pMfxBitstream->DataLength = 0;

    m_nProcessedFramesNum++;

    // print encoding progress to console every certain number of frames (not to affect performance too much)
    if (isPrint && (1 == m_nProcessedFramesNum  || (0 == (m_nProcessedFramesNum % 100))))
    {
        //msdk_printf(MSDK_STRING("Frame number: %u\r"), m_nProcessedFramesNum);
    }

    return MFX_ERR_NONE;
}


int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	HMODULE hModule = ::GetModuleHandle(NULL);

	if (hModule == NULL)
		return -1;

	if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0))
		return -2;

	mfxVideoParam m_mfxEncParams;
    mfxVideoParam m_mfxVppParams;

	memset( &m_mfxEncParams, 0, sizeof(m_mfxEncParams));
	memset( &m_mfxVppParams, 0, sizeof(m_mfxVppParams));

	m_mfxEncParams.mfx.CodecId= MFX_CODEC_AVC;
	m_mfxEncParams.mfx.TargetUsage= 4;		// trade-off between quality and speed
    m_mfxEncParams.mfx.TargetKbps= 16960;	// in Kbps
    m_mfxEncParams.mfx.RateControlMethod= 1;
	m_mfxEncParams.mfx.FrameInfo.FrameRateExtN= 30;
	m_mfxEncParams.mfx.FrameInfo.FrameRateExtD= 1;
	m_mfxEncParams.mfx.EncodedOrder= 0; // binary flag, 0 signals encoder to take frames in display order
	m_mfxEncParams.IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY;
	m_mfxEncParams.mfx.FrameInfo.FourCC       = MFX_FOURCC_NV12;
    m_mfxEncParams.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
    m_mfxEncParams.mfx.FrameInfo.PicStruct    = 2;

	// set frame size and crops
    // width must be a multiple of 16
    // height must be a multiple of 16 in case of frame picture and a multiple of 32 in case of field picture
    m_mfxEncParams.mfx.FrameInfo.Width  = MSDK_ALIGN16( IMG_WIDTH);
    m_mfxEncParams.mfx.FrameInfo.Height = (MFX_PICSTRUCT_PROGRESSIVE == m_mfxEncParams.mfx.FrameInfo.PicStruct)?
        MSDK_ALIGN16(IMG_HEIGHT) : MSDK_ALIGN32(IMG_HEIGHT);

	m_mfxEncParams.mfx.FrameInfo.CropX = 0;
    m_mfxEncParams.mfx.FrameInfo.CropY = 0;
    m_mfxEncParams.mfx.FrameInfo.CropW = IMG_WIDTH;
    m_mfxEncParams.mfx.FrameInfo.CropH = IMG_HEIGHT;

	m_mfxEncParams.AsyncDepth= 4;

	// Vpp?
	m_mfxVppParams.IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY | MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
	m_mfxVppParams.vpp.In.FourCC    = MFX_FOURCC_NV12;
    m_mfxVppParams.vpp.In.PicStruct = 2;
	m_mfxVppParams.vpp.In.FrameRateExtN= 30;
	m_mfxVppParams.vpp.In.FrameRateExtD= 1;

	mfxStatus sts = MFX_ERR_NONE;

	mfxVersion min_version;
    mfxVersion version;     // real API version with which library is initialized
	memset( &min_version, 0, sizeof(min_version));

    // we set version to 1.0 and later we will query actual version of the library which will got leaded
    min_version.Major = 1;
    min_version.Minor = 0;

	MFXVideoSession m_mfxSession;
    // create a session for the second vpp and encode
	sts=  m_mfxSession.Init( MFX_IMPL_SOFTWARE, &min_version);
	MFXQueryVersion(m_mfxSession , &version);


	MFXVideoENCODE *m_pmfxENC = new MFXVideoENCODE(m_mfxSession);

	
	m_pmfxENC->Close();
	sts= m_pmfxENC->Init(&m_mfxEncParams);

	CSmplBitstreamWriter *pWriter = new CSmplBitstreamWriter;
	pWriter->Init( L"test.mp4");

	mfxBitstream	bitStream;

	memset( &bitStream, 0, sizeof(bitStream));
	bitStream.Data= (mfxU8*)malloc( IMG_WIDTH*IMG_HEIGHT*4);
	bitStream.MaxLength= IMG_WIDTH*IMG_HEIGHT*4;
	bitStream.PicStruct= 2;
	bitStream.FrameType= 17089;

	mfxSyncPoint encSync;
	memset( &encSync, 0, sizeof(encSync));

	mfxFrameSurface1 frameSurface1;
	mfxFrameSurface1 frameSurface2;
	memset( &frameSurface1, 0, sizeof(frameSurface1));
	memset( &frameSurface2, 0, sizeof(frameSurface2));

	frameSurface1.Info.FourCC= MFX_FOURCC_NV12;
	frameSurface1.Info.Width= 1024;
	frameSurface1.Info.Height= 1248;

	frameSurface1.Info.CropX= 0;
	frameSurface1.Info.CropY= 0;
	frameSurface1.Info.CropW= 1024;
	frameSurface1.Info.CropH= 1224;

	frameSurface1.Info.PicStruct = 2;
	frameSurface1.Info.FrameRateExtN= 30;
	frameSurface1.Info.FrameRateExtD= 1;
	frameSurface1.Info.ChromaFormat= MFX_CHROMAFORMAT_YUV420;

	// Datei einlesen
	// Datei ist 1024x1224, keine Padbytes
	mfxU8* yptr1= (mfxU8*)malloc( 1024*1224);
	mfxU8* uvptr1= (mfxU8*)malloc( 1024*1224/2);
	mfxU8* yptr2= (mfxU8*)malloc( 1024*1224);
	mfxU8* uvptr2= (mfxU8*)malloc( 1024*1224/2);

	BOOL usefirst= TRUE;

	frameSurface1.Data.Y= (mfxU8*)yptr1;
	frameSurface1.Data.UV= (mfxU8*)uvptr1;
	frameSurface1.Data.Pitch= 1024;
	frameSurface1.Data.PitchLow= 1024;

	memcpy( &frameSurface2, &frameSurface1, sizeof(frameSurface1));

	frameSurface2.Data.Y= (mfxU8*)yptr2;
	frameSurface2.Data.UV= (mfxU8*)uvptr2;

	int count= 0;

	HANDLE hFile= CreateFile( L"test.yuv", GENERIC_READ, 0, NULL, OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL, NULL);
	if( hFile != INVALID_HANDLE_VALUE )
	{
		DWORD dwRead1, dwRead2;

		if( frameSurface1.Data.Locked == 0 )
		{
			ReadFile( hFile, yptr1, 1024*1224, &dwRead1, NULL);
			ReadFile( hFile, uvptr1, 1024*1224/2, &dwRead2, NULL);
		}
		else
		{
			ReadFile( hFile, yptr2, 1024*1224, &dwRead1, NULL);
			ReadFile( hFile, uvptr2, 1024*1224/2, &dwRead2, NULL);
		}

		if( dwRead1 == (1024*1224) && dwRead2 == (1024*1224/2) )
		{
			do
			{
				count++;

				encSync= 0;

				sts = MFX_ERR_NONE;

				if( frameSurface1.Data.Locked == 0 )
				{
					sts= m_pmfxENC->EncodeFrameAsync(NULL, &frameSurface1, &bitStream, &encSync);
					frameSurface2.Data.Locked= 0;
				}
				else
				{
					sts= m_pmfxENC->EncodeFrameAsync(NULL, &frameSurface2, &bitStream, &encSync);
					frameSurface1.Data.Locked= 0;
				}

				m_mfxSession.DoWork();
				m_mfxSession.SyncOperation( encSync, MSDK_WAIT_INTERVAL);
				//MFXVideoCORE_SyncOperation(m_mfxSession, encSync, MSDK_WAIT_INTERVAL);

				if( bitStream.DataLength > 0 )
					sts= MFX_ERR_NONE;

				sts= MFX_ERR_NONE;

				if( frameSurface1.Data.Locked == 0 )
				{
					ReadFile( hFile, yptr1, 1024*1224, &dwRead1, NULL);
					ReadFile( hFile, uvptr1, 1024*1224/2, &dwRead2, NULL);
				}
				else
				{
					ReadFile( hFile, yptr2, 1024*1224, &dwRead1, NULL);
					ReadFile( hFile, uvptr2, 1024*1224/2, &dwRead2, NULL);
				}

			} while( dwRead1 == (1024*1224) && dwRead2 == (1024*1224/2) );
		}
		
		CloseHandle( hFile);
	}

	// aufräumen
	free( bitStream.Data);
	free( yptr1);
	free( uvptr1);
	free( yptr2);
	free( uvptr2);
	delete pWriter;
	delete m_pmfxENC;

	return 0;
}

Many thanks for your help

0 Kudos
1 Reply
Dirk_S_
Beginner
767 Views

The YUV buffers must be large enough for the uncropped frame size.

Changed the mallocs to 1024*1248 and 1024*1248/2 and it works.

0 Kudos
Reply