Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Dirk_S_
Beginner
46 Views

SDK H264 session sync

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
46 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.

Reply