View difference between Paste ID: cweWHXQZ and QPEpCP7t
SHOW: | | - or go back to the newest paste.
1
int encoder_x264_init(Encoder_t *encoder, Image_t *image) {
2-
    encoder->sps_data = NULL;
2+
	encoder->sps_data = NULL;
3-
    encoder->sps_data_size = 0;
3+
	encoder->sps_data_size = 0;
4-
    encoder->pps_data = NULL;
4+
	encoder->pps_data = NULL;
5-
    encoder->pps_data_size = 0;
5+
	encoder->pps_data_size = 0;
6-
    encoder->hwenc.sts = MFX_ERR_NONE;
6+
	encoder->hwenc.sts = MFX_ERR_NONE;
7-
    const mfxIMPL hwimpl[] = {MFX_IMPL_HARDWARE_ANY, MFX_IMPL_HARDWARE};;
7+
	const mfxIMPL hwimpl[] = {MFX_IMPL_HARDWARE_ANY, MFX_IMPL_HARDWARE};;
8-
    mfxVersion vers = {
8+
	mfxVersion vers = {
9-
                        .Minor = 0,
9+
						.Minor = 0,
10-
                        .Major = 1}; //Legacy support
10+
						.Major = 1}; //Legacy support
11-
    mfxU16 target_width = (image->width > 1920 ? 1920 : image->width);
11+
	mfxU16 target_width = (image->width > 1920 ? 1920 : image->width);
12
    mfxU16 target_height = (image->height > 1080 ? 1080 : image->height);
13
14-
//Initialization of Intel Media SDK ENCODER session
14+
	//Initialization of Intel Media SDK ENCODER session
15-
    for(int i=0; i < sizeof(hwimpl)/sizeof(hwimpl[0]);i++)
15+
	for(int i=0; i < sizeof(hwimpl)/sizeof(hwimpl[0]);i++)
16-
    {
16+
17-
        encoder->hwenc.sts = MFXInit(hwimpl[i], &vers, &encoder->hwenc.ENCses);
17+
		encoder->hwenc.sts = MFXInit(hwimpl[i], &vers, &encoder->hwenc.ENCses);
18-
        MSDK_CHECK_RESULT(encoder->hwenc.sts, MFX_ERR_NONE, encoder->hwenc.sts);
18+
19-
        if(encoder->hwenc.sts == MFX_ERR_NONE)
19+
		if(encoder->hwenc.sts == MFX_ERR_NONE)
20
		{
21-
            MFXQueryVersion(encoder->hwenc.ENCses,&encoder->hwenc.ver);
21+
			MFXQueryVersion(encoder->hwenc.ENCses,&encoder->hwenc.ver);
22-
            printf("Asked for version %d.%d.\n",vers.Major,vers.Minor);
22+
			printf("Asked for version %d.%d.\n",vers.Major,vers.Minor);
23-
            printf("SDK version loaded for the ENCODER session is %d.%d.\n",encoder->hwenc.ver.Major,encoder->hwenc.ver.Minor);
23+
			printf("SDK version loaded for the ENCODER session is %d.%d.\n",encoder->hwenc.ver.Major,encoder->hwenc.ver.Minor);
24-
            break;
24+
			break;
25-
        }
25+
26-
    }
26+
27-
    
27+
28-
    
28+
29-
    //Initialization of VPP session for format conversion and potential scaling
29+
	//Initialization of VPP session for format conversion and potential scaling
30-
    for(int i=0; i < sizeof(hwimpl)/sizeof(hwimpl[0]);i++)
30+
	for(int i=0; i < sizeof(hwimpl)/sizeof(hwimpl[0]);i++)
31-
    {
31+
32-
    encoder->hwenc.sts = MFXInit(hwimpl[i], &vers,&encoder->hwenc.VPPses);
32+
	encoder->hwenc.sts = MFXInit(hwimpl[i], &vers,&encoder->hwenc.VPPses);
33
	MSDK_CHECK_RESULT(encoder->hwenc.sts, MFX_ERR_NONE, encoder->hwenc.sts);
34-
        if(encoder->hwenc.sts == MFX_ERR_NONE)
34+
		if(encoder->hwenc.sts == MFX_ERR_NONE)
35
		{
36-
            MFXQueryVersion(encoder->hwenc.ENCses,&encoder->hwenc.ver);
36+
			MFXQueryVersion(encoder->hwenc.ENCses,&encoder->hwenc.ver);
37-
            printf("SDK version loaded for the VPP session is %d.%d.\n",encoder->hwenc.ver.Major,encoder->hwenc.ver.Minor);
37+
			printf("SDK version loaded for the VPP session is %d.%d.\n",encoder->hwenc.ver.Major,encoder->hwenc.ver.Minor);
38-
            break;
38+
			break;
39-
        }
39+
40-
    }
40+
41-
    
41+
42-
    //Initialization of encoder parameters
42+
	//Initialization of encoder parameters
43-
    memset(&encoder->hwenc.ENCParams,0,sizeof(encoder->hwenc.ENCParams));
43+
	memset(&encoder->hwenc.ENCParams,0,sizeof(encoder->hwenc.ENCParams));
44-
    encoder->hwenc.ENCParams.mfx.CodecId                    = MFX_CODEC_AVC;
44+
	encoder->hwenc.ENCParams.mfx.CodecId					= MFX_CODEC_AVC;
45-
    encoder->hwenc.ENCParams.mfx.TargetUsage                 = MFX_TARGETUSAGE_BALANCED;
45+
	encoder->hwenc.ENCParams.mfx.TargetUsage 				= MFX_TARGETUSAGE_BALANCED;
46-
    encoder->hwenc.ENCParams.mfx.TargetKbps                 = 2000; //Investigation required
46+
	encoder->hwenc.ENCParams.mfx.TargetKbps 				= 2000; //Investigation required
47-
    encoder->hwenc.ENCParams.mfx.RateControlMethod             = MFX_RATECONTROL_VBR;
47+
	encoder->hwenc.ENCParams.mfx.RateControlMethod 			= MFX_RATECONTROL_VBR;
48-
    encoder->hwenc.ENCParams.mfx.FrameInfo.FrameRateExtN    = 30;
48+
	encoder->hwenc.ENCParams.mfx.FrameInfo.FrameRateExtN	= 30;
49-
    encoder->hwenc.ENCParams.mfx.FrameInfo.FrameRateExtD    = 1;
49+
	encoder->hwenc.ENCParams.mfx.FrameInfo.FrameRateExtD	= 1;
50-
    encoder->hwenc.ENCParams.mfx.FrameInfo.FourCC            = MFX_FOURCC_NV12;
50+
	encoder->hwenc.ENCParams.mfx.FrameInfo.FourCC			= MFX_FOURCC_NV12;
51-
    encoder->hwenc.ENCParams.mfx.FrameInfo.ChromaFormat        = MFX_CHROMAFORMAT_YUV420;
51+
	encoder->hwenc.ENCParams.mfx.FrameInfo.ChromaFormat		= MFX_CHROMAFORMAT_YUV420;
52-
    encoder->hwenc.ENCParams.mfx.FrameInfo.PicStruct        = MFX_PICSTRUCT_PROGRESSIVE;
52+
	encoder->hwenc.ENCParams.mfx.FrameInfo.PicStruct		= MFX_PICSTRUCT_PROGRESSIVE;
53-
    encoder->hwenc.ENCParams.mfx.FrameInfo.CropX            = 0;
53+
	encoder->hwenc.ENCParams.mfx.FrameInfo.CropX			= 0;
54-
    encoder->hwenc.ENCParams.mfx.FrameInfo.CropY            = 0;
54+
	encoder->hwenc.ENCParams.mfx.FrameInfo.CropY			= 0;
55-
    encoder->hwenc.ENCParams.mfx.FrameInfo.CropW            = target_width;
55+
	encoder->hwenc.ENCParams.mfx.FrameInfo.CropW			= target_width;
56-
    encoder->hwenc.ENCParams.mfx.FrameInfo.CropH            = target_height;
56+
	encoder->hwenc.ENCParams.mfx.FrameInfo.CropH			= target_height;
57-
    
57+
58-
    //Width is aligned as a multiple of 16
58+
	//Width is aligned as a multiple of 16
59-
    encoder->hwenc.ENCParams.mfx.FrameInfo.Width = MSDK_ALIGN16(target_width);
59+
	encoder->hwenc.ENCParams.mfx.FrameInfo.Width = MSDK_ALIGN16(target_width);
60-
    
60+
61-
    //Same applies for height unless it's a field picture so it is a multiple of 32
61+
	//Same applies for height unless it's a field picture so it is a multiple of 32
62-
    encoder->hwenc.ENCParams.mfx.FrameInfo.Height = (MFX_PICSTRUCT_PROGRESSIVE == encoder->hwenc.ENCParams.mfx.FrameInfo.PicStruct)?
62+
	encoder->hwenc.ENCParams.mfx.FrameInfo.Height = (MFX_PICSTRUCT_PROGRESSIVE == encoder->hwenc.ENCParams.mfx.FrameInfo.PicStruct)?
63
        MSDK_ALIGN16(target_height) : MSDK_ALIGN32(target_height);
64-
    
64+
65-
    encoder->hwenc.ENCParams.IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY;
65+
	encoder->hwenc.ENCParams.IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY;
66-
    
66+
67-
    //Additional ENCODER configuration for low latency
67+
	//Additional ENCODER configuration for low latency
68-
    encoder->hwenc.ENCParams.AsyncDepth = 1;
68+
	encoder->hwenc.ENCParams.AsyncDepth = 1;
69-
    encoder->hwenc.ENCParams.mfx.GopRefDist = 1;//B-frames disabled
69+
	encoder->hwenc.ENCParams.mfx.GopRefDist = 1;//B-frames disabled
70-
    
70+
71-
    mfxExtCodingOption extras;
71+
	mfxExtCodingOption extras;
72-
    memset(&extras,0,sizeof(extras));
72+
	memset(&extras,0,sizeof(extras));
73-
    extras.Header.BufferId = MFX_EXTBUFF_CODING_OPTION;
73+
	extras.Header.BufferId = MFX_EXTBUFF_CODING_OPTION;
74-
    extras.Header.BufferSz = sizeof(extras);
74+
	extras.Header.BufferSz = sizeof(extras);
75-
    extras.MaxDecFrameBuffering = 1;
75+
	extras.MaxDecFrameBuffering = 1;
76-
    mfxExtBuffer *extrasBuf[1];
76+
	mfxExtBuffer *extrasBuf[1];
77-
    extrasBuf[0] = (mfxExtBuffer*)&extras;
77+
	extrasBuf[0] = (mfxExtBuffer*)&extras;
78-
    encoder->hwenc.ENCParams.ExtParam = extrasBuf;
78+
	encoder->hwenc.ENCParams.ExtParam = extrasBuf;
79-
    encoder->hwenc.ENCParams.NumExtParam = 1;
79+
	encoder->hwenc.ENCParams.NumExtParam = 1;
80-
    
80+
81-
    //Initialization of VPP parameters (input)
81+
	//Initialization of VPP parameters (input)
82-
    memset(&encoder->hwenc.VPPParams,0,sizeof(encoder->hwenc.VPPParams));
82+
	memset(&encoder->hwenc.VPPParams,0,sizeof(encoder->hwenc.VPPParams));
83-
    encoder->hwenc.VPPParams.vpp.In.FourCC            = MFX_FOURCC_RGB4;
83+
	encoder->hwenc.VPPParams.vpp.In.FourCC			= MFX_FOURCC_RGB4;
84-
    encoder->hwenc.VPPParams.vpp.In.ChromaFormat    = MFX_CHROMAFORMAT_YUV420;
84+
	encoder->hwenc.VPPParams.vpp.In.ChromaFormat	= MFX_CHROMAFORMAT_YUV420;
85-
    encoder->hwenc.VPPParams.vpp.In.CropX            = 0;
85+
	encoder->hwenc.VPPParams.vpp.In.CropX			= 0;
86-
    encoder->hwenc.VPPParams.vpp.In.CropY            = 0;
86+
	encoder->hwenc.VPPParams.vpp.In.CropY			= 0;
87-
    encoder->hwenc.VPPParams.vpp.In.CropW            = image->width;
87+
	encoder->hwenc.VPPParams.vpp.In.CropW			= image->width;
88-
    encoder->hwenc.VPPParams.vpp.In.CropH            = image->height;
88+
	encoder->hwenc.VPPParams.vpp.In.CropH			= image->height;
89-
    encoder->hwenc.VPPParams.vpp.In.PicStruct        = MFX_PICSTRUCT_PROGRESSIVE;
89+
	encoder->hwenc.VPPParams.vpp.In.PicStruct		= MFX_PICSTRUCT_PROGRESSIVE;
90-
    encoder->hwenc.VPPParams.vpp.In.FrameRateExtN    = 30;
90+
	encoder->hwenc.VPPParams.vpp.In.FrameRateExtN	= 30;
91-
    encoder->hwenc.VPPParams.vpp.In.FrameRateExtD    = 1;
91+
	encoder->hwenc.VPPParams.vpp.In.FrameRateExtD	= 1;
92-
    
92+
93-
    //Width is aligned as a multiple of 16    
93+
	//Width is aligned as a multiple of 16	
94-
    encoder->hwenc.VPPParams.vpp.In.Width = MSDK_ALIGN16(image->width);
94+
	encoder->hwenc.VPPParams.vpp.In.Width = MSDK_ALIGN16(image->width);
95-
    
95+
96-
    //Same applies for height unless it's a field picture so it is a multiple of 32
96+
	//Same applies for height unless it's a field picture so it is a multiple of 32
97-
    encoder->hwenc.VPPParams.vpp.In.Height = (MFX_PICSTRUCT_PROGRESSIVE == encoder->hwenc.VPPParams.vpp.In.PicStruct) ?
97+
	encoder->hwenc.VPPParams.vpp.In.Height = (MFX_PICSTRUCT_PROGRESSIVE == encoder->hwenc.VPPParams.vpp.In.PicStruct) ?
98-
        MSDK_ALIGN16(image->width) : MSDK_ALIGN32(image->height);
98+
		MSDK_ALIGN16(image->width) : MSDK_ALIGN32(image->height);
99-
    
99+
100-
    //Initialization of VPP parameters (output)
100+
	//Initialization of VPP parameters (output)
101-
    encoder->hwenc.VPPParams.vpp.Out.FourCC            = MFX_FOURCC_NV12;
101+
	encoder->hwenc.VPPParams.vpp.Out.FourCC			= MFX_FOURCC_NV12;
102-
    encoder->hwenc.VPPParams.vpp.Out.ChromaFormat    = MFX_CHROMAFORMAT_YUV420;
102+
	encoder->hwenc.VPPParams.vpp.Out.ChromaFormat	= MFX_CHROMAFORMAT_YUV420;
103-
    encoder->hwenc.VPPParams.vpp.Out.CropX            = 0;
103+
	encoder->hwenc.VPPParams.vpp.Out.CropX			= 0;
104-
    encoder->hwenc.VPPParams.vpp.Out.CropY            = 0;
104+
	encoder->hwenc.VPPParams.vpp.Out.CropY			= 0;
105-
    encoder->hwenc.VPPParams.vpp.Out.CropW            = target_width;
105+
	encoder->hwenc.VPPParams.vpp.Out.CropW			= target_width;
106-
    encoder->hwenc.VPPParams.vpp.Out.CropH            = target_height;
106+
	encoder->hwenc.VPPParams.vpp.Out.CropH			= target_height;
107-
    encoder->hwenc.VPPParams.vpp.Out.PicStruct        = MFX_PICSTRUCT_PROGRESSIVE;
107+
	encoder->hwenc.VPPParams.vpp.Out.PicStruct		= MFX_PICSTRUCT_PROGRESSIVE;
108-
    encoder->hwenc.VPPParams.vpp.Out.FrameRateExtN    = 30;
108+
	encoder->hwenc.VPPParams.vpp.Out.FrameRateExtN	= 30;
109-
    encoder->hwenc.VPPParams.vpp.Out.FrameRateExtD    = 1;
109+
	encoder->hwenc.VPPParams.vpp.Out.FrameRateExtD	= 1;
110-
    
110+
111-
    //Width is aligned as a multiple of 16    
111+
	//Width is aligned as a multiple of 16	
112-
    encoder->hwenc.VPPParams.vpp.Out.Width = MSDK_ALIGN16(image->width);
112+
	encoder->hwenc.VPPParams.vpp.Out.Width = MSDK_ALIGN16(target_width);
113-
    
113+
114-
    //Same applies for height unless it's a field picture so it is a multiple of 32
114+
	//Same applies for height unless it's a field picture so it is a multiple of 32
115-
    encoder->hwenc.VPPParams.vpp.Out.Height = (MFX_PICSTRUCT_PROGRESSIVE == encoder->hwenc.VPPParams.vpp.Out.PicStruct) ?
115+
	encoder->hwenc.VPPParams.vpp.Out.Height = (MFX_PICSTRUCT_PROGRESSIVE == encoder->hwenc.VPPParams.vpp.Out.PicStruct) ?
116-
        MSDK_ALIGN16(image->width) : MSDK_ALIGN32(image->height);
116+
		MSDK_ALIGN16(image->width) : MSDK_ALIGN32(target_height);
117-
    
117+
118-
    encoder->hwenc.VPPParams.AsyncDepth = 1;
118+
	encoder->hwenc.VPPParams.AsyncDepth = 1;
119-
    encoder->hwenc.VPPParams.IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY | MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
119+
	encoder->hwenc.VPPParams.IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY | MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
120-
    
120+
121
	
122
	//Disabling VPP enabled by default ops
123
	mfxExtVPPDoNotUse dnu;
124
	memset(&dnu,0,sizeof(mfxExtVPPDoNotUse));
125
	dnu.Header.BufferId = MFX_EXTBUFF_VPP_DONOTUSE;
126
	dnu.Header.BufferSz = sizeof(mfxExtVPPDoNotUse);
127
	dnu.NumAlg = 4;
128
	dnu.AlgList = malloc(sizeof(mfxU32)*dnu.NumAlg);
129
	MSDK_CHECK_POINTER(dnu.AlgList, MFX_ERR_MEMORY_ALLOC);
130
	dnu.AlgList[0] = MFX_EXTBUFF_VPP_DENOISE; 
131
	dnu.AlgList[1] = MFX_EXTBUFF_VPP_SCENE_ANALYSIS;
132
	dnu.AlgList[2] = MFX_EXTBUFF_VPP_DETAIL;
133
	dnu.AlgList[3] = MFX_EXTBUFF_VPP_PROCAMP;
134
	
135
	//Add the extended buffers
136
	mfxExtBuffer *dnuBuf[1];
137
	dnuBuf[0] = (mfxExtBuffer*)&dnu;
138
	encoder->hwenc.VPPParams.ExtParam = dnuBuf;
139
	encoder->hwenc.VPPParams.NumExtParam = 1;
140-
    //Check VPPParams validity. Adjust if necessary.
140+
141-
    encoder->hwenc.sts = MFXVideoVPP_Query(encoder->hwenc.VPPses,&encoder->hwenc.VPPParams,&encoder->hwenc.VPPParams);
141+
	//Check VPPParams validity. Adjust if necessary.
142-
    //MSDK_IGNORE_MFX_STS(encoder->hwenc.sts, MFX_WRN_INCOMPATIBLE_VIDEO_PARAM); 
142+
	encoder->hwenc.sts = MFXVideoVPP_Query(encoder->hwenc.VPPses,&encoder->hwenc.VPPParams,&encoder->hwenc.VPPParams);
143
	//MSDK_IGNORE_MFX_STS(encoder->hwenc.sts, MFX_WRN_INCOMPATIBLE_VIDEO_PARAM); 
144-
    
144+
145-
    //Validation of encoder parameters
145+
146-
    //If parameters are not valid the encoder will adjust the parameters as close as possible to the requested configuration
146+
	//Validation of encoder parameters
147-
    encoder->hwenc.sts = MFXVideoENCODE_Query(encoder->hwenc.ENCses,&encoder->hwenc.ENCParams,&encoder->hwenc.ENCParams);
147+
	//If parameters are not valid the encoder will adjust the parameters as close as possible to the requested configuration
148-
    //MSDK_IGNORE_MFX_STS(encoder->hwenc.sts, MFX_WRN_INCOMPATIBLE_VIDEO_PARAM); 
148+
	encoder->hwenc.sts = MFXVideoENCODE_Query(encoder->hwenc.ENCses,&encoder->hwenc.ENCParams,&encoder->hwenc.ENCParams);
149
	//MSDK_IGNORE_MFX_STS(encoder->hwenc.sts, MFX_WRN_INCOMPATIBLE_VIDEO_PARAM); 
150-
    
150+
151-
    //Ask the encoder how many surfaces it needs with this configuration
151+
152-
    mfxFrameAllocRequest ENCsurfReq;
152+
	//Ask the encoder how many surfaces it needs with this configuration
153-
    memset(&ENCsurfReq,0,sizeof(ENCsurfReq));
153+
	mfxFrameAllocRequest ENCsurfReq;
154-
    encoder->hwenc.sts = MFXVideoENCODE_QueryIOSurf(encoder->hwenc.ENCses, &encoder->hwenc.ENCParams, &ENCsurfReq);
154+
	memset(&ENCsurfReq,0,sizeof(ENCsurfReq));
155
	encoder->hwenc.sts = MFXVideoENCODE_QueryIOSurf(encoder->hwenc.ENCses, &encoder->hwenc.ENCParams, &ENCsurfReq);
156-
    
156+
	MSDK_CHECK_RESULT(encoder->hwenc.sts, MFX_ERR_NONE, encoder->hwenc.sts);
157-
    encoder->hwenc.nENCSurfs = ENCsurfReq.NumFrameSuggested;
157+
158-
    
158+
	//Creation of the VPP component and querying for surface buffers
159-
    printf("%d surfaces are needed for ENC input.\n",encoder->hwenc.nENCSurfs);
159+
	mfxFrameAllocRequest VPPsurfReq[2];//An array structure where position [0] is for input and [1] is for output
160-
    //Allocate memory to the encoder for required surfaces (surfaces will be shared with VPP output)
160+
	memset(&VPPsurfReq,0,sizeof(mfxFrameAllocRequest) * 2);
161-
    mfxU16 width = (mfxU16)MSDK_ALIGN32(ENCsurfReq.Info.Width);
161+
	encoder->hwenc.sts = MFXVideoVPP_QueryIOSurf(encoder->hwenc.VPPses,&encoder->hwenc.VPPParams,VPPsurfReq);
162-
    mfxU16 height = (mfxU16)MSDK_ALIGN32(ENCsurfReq.Info.Height);
162+
	MSDK_CHECK_RESULT(encoder->hwenc.sts, MFX_ERR_NONE, encoder->hwenc.sts);
163-
    mfxU8  bitsPerPixel = 12;  // NV12 format is a 12 bits per pixel format
163+
164-
    mfxU32 surfSize = (width * height * bitsPerPixel)>>3;
164+
	ENCsurfReq.Type |= MFX_MEMTYPE_FROM_VPPOUT; //Shared memory block for VPP out and ENCODER in
165-
    
165+
166-
    //Surface ENCODER pointers housekeeping
166+
	encoder->hwenc.nVPPSurfs[0] = VPPsurfReq[0].NumFrameSuggested;
167-
    encoder->hwenc.ENCsurfbuffs = (mfxU8*)malloc(sizeof(surfSize)*encoder->hwenc.nENCSurfs);
167+
	encoder->hwenc.nVPPSurfs[1] = VPPsurfReq[1].NumFrameSuggested;
168-
    
168+
	printf("%d surfaces are needed for VPP input.\n",encoder->hwenc.nVPPSurfs[0]);
169-
    encoder->hwenc.ptrENCSurfs = malloc(sizeof(mfxFrameSurface1*)*encoder->hwenc.nENCSurfs);//This is equivalent to mfxFrameSurface1*[encoder->hwenc.nENCSurfs]
169+
	encoder->hwenc.nENCSurfs = ENCsurfReq.NumFrameSuggested + encoder->hwenc.nVPPSurfs[1];
170-
    MSDK_CHECK_POINTER(encoder->hwenc.ptrENCSurfs, MFX_ERR_MEMORY_ALLOC);
170+
	encoder->hwenc.nVPPSurfs[1] = encoder->hwenc.nENCSurfs;
171-
    for(int i=0; i<encoder->hwenc.nENCSurfs; i++)
171+
	printf("%d surfaces are needed for ENC input.\n",encoder->hwenc.nENCSurfs);
172-
    {
172+
173-
        encoder->hwenc.ptrENCSurfs[i] = malloc(sizeof(mfxFrameSurface1));
173+
	//Allocate memory to vpp for input surfaces
174-
        memset(encoder->hwenc.ptrENCSurfs[i],0,sizeof(mfxFrameSurface1));
174+
	//Both width and height must be 32-bit aligned
175-
        memcpy(&(encoder->hwenc.ptrENCSurfs[i]->Info), &(encoder->hwenc.ENCParams.mfx.FrameInfo), sizeof(mfxFrameInfo));
175+
	mfxU16 width = (mfxU16)MSDK_ALIGN32(encoder->hwenc.VPPParams.vpp.In.Width);
176-
        encoder->hwenc.ptrENCSurfs[i]->Data.Y = &encoder->hwenc.ENCsurfbuffs[surfSize * i];
176+
	mfxU16 height = (mfxU16)MSDK_ALIGN32(encoder->hwenc.VPPParams.vpp.In.Height);
177-
        encoder->hwenc.ptrENCSurfs[i]->Data.U = encoder->hwenc.ptrENCSurfs[i]->Data.Y + target_width * target_height;
177+
	mfxU8  bitsPerPixel = 32;
178-
        encoder->hwenc.ptrENCSurfs[i]->Data.V = encoder->hwenc.ptrENCSurfs[i]->Data.U + 1;
178+
	mfxU32 surfSize = (width * height * bitsPerPixel)>>3;
179-
        encoder->hwenc.ptrENCSurfs[i]->Data.Pitch = target_width;
179+
180-
    }
180+
181-
    
181+
	//Surface VPP pointers housekeeping
182-
    //Creation of the VPP component and querying for surface buffers
182+
	encoder->hwenc.VPPsurfbuffsIN = (mfxU8*)malloc(sizeof(surfSize)*encoder->hwenc.nVPPSurfs[0]);
183-
    mfxFrameAllocRequest VPPsurfReq[2];//An array structure where position [0] is for input and [1] is for output
183+
	encoder->hwenc.ptrVPPSurfsIN = malloc(sizeof(mfxFrameSurface1*)*encoder->hwenc.nVPPSurfs[0]);
184-
    memset(&VPPsurfReq,0,sizeof(mfxFrameAllocRequest) * 2);
184+
	MSDK_CHECK_POINTER(encoder->hwenc.ptrVPPSurfsIN,MFX_ERR_MEMORY_ALLOC);
185-
    encoder->hwenc.sts = MFXVideoVPP_QueryIOSurf(encoder->hwenc.VPPses,&encoder->hwenc.VPPParams,VPPsurfReq);
185+
	for(int i=0; i<encoder->hwenc.nVPPSurfs[0]; i++)
186
	{
187-
    
187+
		encoder->hwenc.ptrVPPSurfsIN[i] = malloc(sizeof(mfxFrameSurface1));
188-
    encoder->hwenc.nVPPSurfs[0] = VPPsurfReq[0].NumFrameSuggested;
188+
		memset(encoder->hwenc.ptrVPPSurfsIN[i],0,sizeof(mfxFrameSurface1));
189-
    encoder->hwenc.nVPPSurfs[1] = VPPsurfReq[1].NumFrameSuggested;
189+
		memcpy(&(encoder->hwenc.ptrVPPSurfsIN[i]->Info), &(encoder->hwenc.VPPParams.vpp.In), sizeof(mfxFrameInfo));
190-
    printf("%d surfaces are needed for VPP input.\n",encoder->hwenc.nVPPSurfs[0]);
190+
		encoder->hwenc.ptrVPPSurfsIN[i]->Data.B = &encoder->hwenc.VPPsurfbuffsIN[surfSize * i];//Assuming Top-Down layout and little-endian
191-
    printf("%d surfaces are needed for VPP output.\n",encoder->hwenc.nVPPSurfs[1]);
191+
		encoder->hwenc.ptrVPPSurfsIN[i]->Data.G = encoder->hwenc.ptrVPPSurfsIN[i]->Data.B + 1;
192-
    //Allocate memory to vpp for input surfaces
192+
		encoder->hwenc.ptrVPPSurfsIN[i]->Data.R = encoder->hwenc.ptrVPPSurfsIN[i]->Data.G + 1;
193-
    //Both width and height must be 32-bit aligned
193+
		encoder->hwenc.ptrVPPSurfsIN[i]->Data.A = encoder->hwenc.ptrVPPSurfsIN[i]->Data.R + 1;
194-
    width = (mfxU16)MSDK_ALIGN32(encoder->hwenc.VPPParams.vpp.In.Width);
194+
		encoder->hwenc.ptrVPPSurfsIN[i]->Data.Pitch = image->width*bitsPerPixel>>3;
195-
    height = (mfxU16)MSDK_ALIGN32(encoder->hwenc.VPPParams.vpp.In.Height);
195+
	}	
196-
    bitsPerPixel = 32;
196+
197
	//Allocate memory to the encoder for required surfaces (surfaces will be shared with VPP output)
198-
    
198+
	width = (mfxU16)MSDK_ALIGN32(ENCsurfReq.Info.Width);
199-
    
199+
    height = (mfxU16)MSDK_ALIGN32(ENCsurfReq.Info.Height);
200-
    //Surface VPP pointers housekeeping
200+
    bitsPerPixel = 12;  // NV12 format is a 12 bits per pixel format
201-
    encoder->hwenc.VPPsurfbuffsIN = (mfxU8*)malloc(sizeof(surfSize)*encoder->hwenc.nVPPSurfs[0]);
201+
202-
    encoder->hwenc.ptrVPPSurfsIN = malloc(sizeof(mfxFrameSurface1*)*encoder->hwenc.nVPPSurfs[0]);
202+
203-
    MSDK_CHECK_POINTER(encoder->hwenc.ptrVPPSurfsIN,MFX_ERR_MEMORY_ALLOC);
203+
	//Surface VPP & ENCODER pointers housekeeping
204-
    for(int i=0; i<encoder->hwenc.nVPPSurfs[0]; i++)
204+
	encoder->hwenc.VPPsurfbuffsOUT = (mfxU8*)malloc(sizeof(surfSize)*encoder->hwenc.nENCSurfs);
205-
    {
205+
	MSDK_CHECK_POINTER(encoder->hwenc.VPPsurfbuffsOUT, MFX_ERR_MEMORY_ALLOC);
206-
        encoder->hwenc.ptrVPPSurfsIN[i] = malloc(sizeof(mfxFrameSurface1));
206+
	encoder->hwenc.ENCsurfbuffs = encoder->hwenc.VPPsurfbuffsOUT;
207-
        memset(encoder->hwenc.ptrVPPSurfsIN[i],0,sizeof(mfxFrameSurface1));
207+
	encoder->hwenc.ptrVPPSurfsOUT = malloc(sizeof(mfxFrameSurface1*)*encoder->hwenc.nENCSurfs);//This is equivalent to mfxFrameSurface1*[encoder->hwenc.nENCSurfs]
208-
        memcpy(&(encoder->hwenc.ptrVPPSurfsIN[i]->Info), &(encoder->hwenc.VPPParams.vpp.In), sizeof(mfxFrameInfo));
208+
	encoder->hwenc.ptrENCSurfs = malloc(sizeof(mfxFrameSurface1*)*encoder->hwenc.nENCSurfs);
209-
        encoder->hwenc.ptrVPPSurfsIN[i]->Data.B = &encoder->hwenc.VPPsurfbuffsIN[surfSize * i];//Assuming Top-Down layout and little-endian
209+
	MSDK_CHECK_POINTER(encoder->hwenc.ptrVPPSurfsOUT, MFX_ERR_MEMORY_ALLOC);
210-
        encoder->hwenc.ptrVPPSurfsIN[i]->Data.G = encoder->hwenc.ptrVPPSurfsIN[i]->Data.B + 1;
210+
	for(int i=0; i<encoder->hwenc.nENCSurfs; i++)
211-
        encoder->hwenc.ptrVPPSurfsIN[i]->Data.R = encoder->hwenc.ptrVPPSurfsIN[i]->Data.G + 1;
211+
212-
        encoder->hwenc.ptrVPPSurfsIN[i]->Data.A = encoder->hwenc.ptrVPPSurfsIN[i]->Data.R + 1;
212+
		encoder->hwenc.ptrVPPSurfsOUT[i] = malloc(sizeof(mfxFrameSurface1));
213-
        encoder->hwenc.ptrVPPSurfsIN[i]->Data.Pitch = image->width*bitsPerPixel>>3;
213+
		memset(encoder->hwenc.ptrVPPSurfsOUT[i],0,sizeof(mfxFrameSurface1));
214-
    }
214+
		memcpy(&(encoder->hwenc.ptrVPPSurfsOUT[i]->Info), &(encoder->hwenc.VPPParams.vpp.Out), sizeof(mfxFrameInfo));
215-
    
215+
		encoder->hwenc.ptrVPPSurfsOUT[i]->Data.Y = &encoder->hwenc.VPPsurfbuffsOUT[surfSize * i];
216-
    //Allocate memory to vpp for output surfaces
216+
        encoder->hwenc.ptrVPPSurfsOUT[i]->Data.U = encoder->hwenc.ptrVPPSurfsOUT[i]->Data.Y + target_width * target_height;
217-
    //This is a shared resource because this acts as an intermediate buffer between VPP and ENCODE operations
217+
        encoder->hwenc.ptrVPPSurfsOUT[i]->Data.V = encoder->hwenc.ptrVPPSurfsOUT[i]->Data.U + 1;
218-
    encoder->hwenc.VPPsurfbuffsOUT = encoder->hwenc.ENCsurfbuffs;
218+
        encoder->hwenc.ptrVPPSurfsOUT[i]->Data.Pitch = target_width;
219-
    encoder->hwenc.ptrVPPSurfsOUT = encoder->hwenc.ptrENCSurfs;
219+
		encoder->hwenc.ptrENCSurfs[i] = malloc(sizeof(mfxFrameSurface1));
220-
    MSDK_CHECK_POINTER(encoder->hwenc.ptrVPPSurfsOUT, MFX_ERR_MEMORY_ALLOC);
220+
		memcpy(&(encoder->hwenc.ptrENCSurfs[i]->Info), &(encoder->hwenc.ENCParams.mfx.FrameInfo), sizeof(mfxFrameInfo));
221-
    
221+
		memcpy(&(encoder->hwenc.ptrENCSurfs[i]->Data), &(encoder->hwenc.ptrVPPSurfsOUT[i]->Data), sizeof(mfxFrameData));
222-
    //Initialize Intel SDK Encoder
222+
223-
    encoder->hwenc.sts = MFXVideoENCODE_Init(encoder->hwenc.ENCses,&encoder->hwenc.ENCParams);
223+
224-
    //MSDK_IGNORE_MFX_STS(encoder->hwenc.sts, MFX_WRN_PARTIAL_ACCELERATION);
224+
	//Allocate memory to vpp for output surfaces
225
	//This is a shared resource because this acts as an intermediate buffer between VPP and ENCODE operations
226-
        
226+
	encoder->hwenc.ENCsurfbuffs = encoder->hwenc.VPPsurfbuffsOUT;
227-
    //Retrieve selected settings by encoder
227+
	MSDK_CHECK_POINTER(encoder->hwenc.ptrENCSurfs, MFX_ERR_MEMORY_ALLOC);
228-
    mfxVideoParam params;
228+
	MSDK_CHECK_POINTER(encoder->hwenc.ENCsurfbuffs, MFX_ERR_MEMORY_ALLOC);
229-
    memset(&params, 0, sizeof(params));
229+
230-
    encoder->hwenc.sts = MFXVideoENCODE_GetVideoParam(encoder->hwenc.ENCses, &params);
230+
	//Initialize Intel SDK VPP
231
	encoder->hwenc.sts = MFXVideoVPP_Init(encoder->hwenc.VPPses,&encoder->hwenc.VPPParams);
232-
    
232+
	//MSDK_IGNORE_MFX_STS(encoder->hwenc.sts, MFX_WRN_PARTIAL_ACCELERATION);
233-
    //Prepare the buffer for the H.264 bitstream
233+
234-
    memset(&encoder->hwenc.bitstr, 0, sizeof(encoder->hwenc.bitstr));
234+
235-
    //Assignment of MaxLength parameter is mandatory.
235+
	//Initialize Intel SDK Encoder
236-
    encoder->hwenc.bitstr.MaxLength = params.mfx.BufferSizeInKB * 1000;
236+
	encoder->hwenc.sts = MFXVideoENCODE_Init(encoder->hwenc.ENCses,&encoder->hwenc.ENCParams);
237-
    encoder->hwenc.bitstr.Data = malloc(sizeof(mfxU8)*encoder->hwenc.bitstr.MaxLength);
237+
	//MSDK_IGNORE_MFX_STS(encoder->hwenc.sts, MFX_WRN_PARTIAL_ACCELERATION);
238-
    MSDK_CHECK_POINTER(encoder->hwenc.bitstr.Data, MFX_ERR_MEMORY_ALLOC);
238+
239-
    
239+
240-
    //Initialize Intel SDK VPP
240+
	//Retrieve selected settings by encoder
241-
    encoder->hwenc.sts = MFXVideoVPP_Init(encoder->hwenc.VPPses,&encoder->hwenc.VPPParams);
241+
	mfxVideoParam params;
242-
    //MSDK_IGNORE_MFX_STS(encoder->hwenc.sts, MFX_WRN_PARTIAL_ACCELERATION);
242+
	memset(&params, 0, sizeof(params));
243
	encoder->hwenc.sts = MFXVideoENCODE_GetVideoParam(encoder->hwenc.ENCses, &params);
244
	MSDK_CHECK_RESULT(encoder->hwenc.sts, MFX_ERR_NONE, encoder->hwenc.sts);
245-
    encoder->image = image;
245+
246-
    encoder->width = (int)target_width;//Safe casting
246+
	//Prepare the buffer for the H.264 bitstream
247-
    encoder->height = (int)target_height;//Safe casting
247+
	memset(&encoder->hwenc.bitstr, 0, sizeof(encoder->hwenc.bitstr));
248
	//Assignment of MaxLength parameter is mandatory.
249-
    printf("End of initialization.\n");
249+
	encoder->hwenc.bitstr.MaxLength = params.mfx.BufferSizeInKB * 1000;
250-
    return 1;
250+
	encoder->hwenc.bitstr.Data = malloc(sizeof(mfxU8)*encoder->hwenc.bitstr.MaxLength);
251
	MSDK_CHECK_POINTER(encoder->hwenc.bitstr.Data, MFX_ERR_MEMORY_ALLOC);
252
	
253
	encoder->image = image;
254-
#ifdef BENCHMARK.
254+
	encoder->width = (int)target_width;//Safe casting
255
	encoder->height = (int)target_height;//Safe casting
256
	printf("End of initialization.\n");
257
	return 1;
258
}
259
260
int encoder_x264_encode(Encoder_t *encoder) {
261
#ifdef BENCHMARK
262
#ifdef _WIN32
263
    LARGE_INTEGER tStart, tEnd;
264
    QueryPerformanceFrequency(&tStart);
265
    double freq = (double)tStart.QuadPart;
266
    QueryPerformanceCounter(&tStart);
267
#endif
268
#endif
269
	
270
	int surfVPPindexIN = 0, surfVPPindexOUT = 0, surfENCindex = 0;
271
    mfxSyncPoint VPPsync,ENCsync;
272
    encoder->hwenc.nENCFrame = 0;
273
	encoder->hwenc.sts = MFX_ERR_NONE;
274
	uint8_t* data;
275
	uint32_t len;
276
	
277-
	data = cb_read_direct(&encoder->image->cb, &len);//Or if this doesn't work assign directly to pool
277+
278
		len = 4 * encoder->image->width * encoder->image->height;
279-
	//Main VPPprocess loop
279+
280
		len = 3 * encoder->image->width * encoder->image->height;
281
	
282-
		printf("Entering VPP while loop.\n");
282+
283
		return 0;
284
	printf("Expecting raw frame with size %d.\n",len);
285
	data = cb_read_direct(&encoder->image->cb, &len);
286-
		//encoder->hwenc.ptrVPPSurfsIN[surfVPPindexIN]->Data.A = (mfxU8*)data;//maybe memcpy is needed here
286+
287
288
	//Main VPP & ENNCODING process loop
289
	while (MFX_ERR_NONE <= encoder->hwenc.sts || MFX_ERR_MORE_DATA == encoder->hwenc.sts)
290
	{
291
		printf("Entering 1st while loop.\n");
292
		surfVPPindexIN = alloc_surfpool(encoder->hwenc.ptrVPPSurfsIN, encoder->hwenc.nVPPSurfs[0]);
293
		MSDK_CHECK_ERROR(MFX_ERR_NOT_FOUND, surfVPPindexIN, MFX_ERR_MEMORY_ALLOC);
294
		printf("Surface index for VPP in is %d.\n", surfVPPindexIN);
295
		
296
		cb_read(&encoder->image->cb, &encoder->hwenc.ptrVPPSurfsIN[surfVPPindexIN]->Data.B, &len);
297
		surfVPPindexOUT = alloc_surfpool(encoder->hwenc.ptrVPPSurfsOUT, encoder->hwenc.nVPPSurfs[1]);
298
		surfENCindex = surfVPPindexOUT;
299
		MSDK_CHECK_ERROR(MFX_ERR_NOT_FOUND, surfVPPindexOUT, MFX_ERR_MEMORY_ALLOC);
300
		printf("Surface index for VPP out is %d.\n", surfVPPindexOUT);
301
302
	for(;;)
303
		{
304
			printf("Entering VPP for loop.\n");
305
			encoder->hwenc.sts = MFXVideoVPP_RunFrameVPPAsync(encoder->hwenc.VPPses, encoder->hwenc.ptrVPPSurfsIN[surfVPPindexIN], encoder->hwenc.ptrVPPSurfsOUT[surfVPPindexOUT],NULL,&VPPsync);
306
			if (MFX_WRN_DEVICE_BUSY == encoder->hwenc.sts)
307
			{
308
				printf("Device is busy, retrying...\n");
309
                Sleep(1); // Wait if device is busy, then repeat the same call
310
			}
311
            else
312
			{
313
				printf("Exiting VPP for loop with status code %d.\n",encoder->hwenc.sts);
314
                break;
315
			}
316-
		encoder->hwenc.sts = MFXVideoCORE_SyncOperation(encoder->hwenc.VPPses, VPPsync, 10);
316+
317
		
318-
		printf("Exiting VPP while loop.\n");
318+
319
		{
320
			printf("More data is needed for VPP.\n");
321-
	//Main ENCODERprocess loop
321+
322
		}
323
		
324-
	printf("Entering ENCODER while loop.\n");
324+
325
		MSDK_BREAK_ON_ERROR(encoder->hwenc.sts);
326
		
327
		for(;;)
328-
		//if(surfVPPindexOUT != surfENCindex)
328+
329-
			//surfENCindex = surfVPPindexOUT;//Sync of indices
329+
330-
		//Not need to load anything since data appeared to the encoder's input from the VPP's output.
330+
			encoder->hwenc.sts = MFXVideoENCODE_EncodeFrameAsync(encoder->hwenc.ENCses,NULL,encoder->hwenc.ptrENCSurfs[surfENCindex], &encoder->hwenc.bitstr,&ENCsync);
331
			
332
			if (MFX_ERR_NONE < encoder->hwenc.sts && !ENCsync)
333
			{
334
				if (MFX_WRN_DEVICE_BUSY == encoder->hwenc.sts)
335-
			encoder->hwenc.sts = MFXVideoENCODE_EncodeFrameAsync(encoder->hwenc.ENCses,encoder->hwenc.ptrENCSurfs[surfENCindex], &encoder->hwenc.bitstr,NULL,&ENCsync);
335+
336
			}
337
            else if (MFX_ERR_NONE < encoder->hwenc.sts && ENCsync)
338
			{
339
				printf("There are warnings but they are ignored.\n");
340
				encoder->hwenc.sts = MFX_ERR_NONE; //Ignore warnings 
341
                break;
342
			}
343
			else if (MFX_ERR_NOT_ENOUGH_BUFFER == encoder->hwenc.sts)
344
			{
345
				printf("Must allocate more memory for output bitstream.\n");
346
				//Consider allocating more memory for bitstream output
347
				break;
348
			}
349
			else
350
			{				
351
				printf("Exiting ENCODER for loop with status code %d.\n",encoder->hwenc.sts);
352
				break;
353
			}
354
		}
355
		
356
		if(MFX_ERR_NONE == encoder->hwenc.sts)
357
        {
358
			printf("Waiting for ENCODE operation to sync.\n");
359
            encoder->hwenc.sts = MFXVideoCORE_SyncOperation(encoder->hwenc.ENCses, ENCsync, 60000); // Synchronize. Wait until encoded frame is ready
360
			if(encoder->hwenc.sts == MFX_ERR_NONE) printf("ENCODE operation synchronized successfully\n");
361
            MSDK_CHECK_RESULT(encoder->hwenc.sts, MFX_ERR_NONE, encoder->hwenc.sts);
362-
            encoder->hwenc.sts = MFXVideoCORE_SyncOperation(encoder->hwenc.ENCses, ENCsync, 10); // Synchronize. Wait until encoded frame is ready
362+
363
            //Must send bitstream now
364
			++encoder->hwenc.nENCFrame;
365
			printf("Sending bitstream.\n");
366
			encoder->hwenc.sts = send_h264stream(&encoder->hwenc.bitstr,encoder);
367
			printf("Bitstream exited with status code %d.\n",encoder->hwenc.sts);
368
            MSDK_BREAK_ON_ERROR(encoder->hwenc.sts);
369
		}
370
		
371-
	printf("Exiting ENCODER while loop.\n");
371+
372-
	MSDK_IGNORE_MFX_STS(encoder->hwenc.sts, MFX_ERR_MORE_DATA);
372+
		printf("Exiting 1st while loop.\n");
373
	}
374
	
375-
	//Draining VPP buffers
375+
	//Draining the VPP buffer
376
	while (MFX_ERR_NONE <= encoder->hwenc.sts || MFX_ERR_MORE_DATA == encoder->hwenc.sts)
377
	{
378
		printf("Entering 2nd while loop.\n");
379
		surfENCindex = alloc_surfpool(encoder->hwenc.ptrENCSurfs, encoder->hwenc.nENCSurfs);
380
		surfVPPindexOUT = surfENCindex;
381
		MSDK_CHECK_ERROR(MFX_ERR_NOT_FOUND, surfENCindex, MFX_ERR_MEMORY_ALLOC);
382
		
383
		for(;;)
384-
			if (MFX_WRN_DEVICE_BUSY == encoder->hwenc.sts)                
384+
385-
                Sleep(1); // Wait if device is busy, then repeat the same call          
385+
386-
            else 
386+
387
			if (MFX_WRN_DEVICE_BUSY == encoder->hwenc.sts)
388
			{
389
				printf("Device is busy, retrying...\n");
390-
		MSDK_IGNORE_MFX_STS(encoder->hwenc.sts, MFX_ERR_MORE_SURFACE);
390+
391
			}
392
            else
393-
		encoder->hwenc.sts = MFXVideoCORE_SyncOperation(encoder->hwenc.VPPses, VPPsync, 10);
393+
394
				printf("Exiting VPP for loop.\n");
395
                break;
396
			}
397-
	//Draining ENCODER buffers
397+
398
		
399-
	while (MFX_ERR_NONE <= encoder->hwenc.sts)
399+
400-
    {       
400+
401-
        for (;;)
401+
402-
        {                
402+
403-
            // Encode a frame asychronously (returns immediately)
403+
404-
            encoder->hwenc.sts = MFXVideoENCODE_EncodeFrameAsync(encoder->hwenc.ENCses,NULL, &encoder->hwenc.bitstr,NULL,&ENCsync);
404+
405
			encoder->hwenc.sts = MFXVideoENCODE_EncodeFrameAsync(encoder->hwenc.ENCses,NULL, NULL, &encoder->hwenc.bitstr,&ENCsync);
406-
            if (MFX_ERR_NONE < encoder->hwenc.sts && !ENCsync) // Repeat the call if warning and no output
406+
407-
            {
407+
408-
                if (MFX_WRN_DEVICE_BUSY == encoder->hwenc.sts)                
408+
409-
                    Sleep(1); // Wait if device is busy, then repeat the same call                 
409+
410-
            }
410+
411-
            else if (MFX_ERR_NONE < encoder->hwenc.sts && ENCsync)                 
411+
412-
            {
412+
413-
                encoder->hwenc.sts = MFX_ERR_NONE; // Ignore warnings if output is available                                    
413+
414
				encoder->hwenc.sts = MFX_ERR_NONE; //Ignore warnings 
415-
            }
415+
416
			}
417
			else if (MFX_ERR_NOT_ENOUGH_BUFFER == encoder->hwenc.sts)
418-
        }            
418+
419
				printf("Must allocate more memory for output bitstream.\n");
420-
        if(MFX_ERR_NONE == encoder->hwenc.sts)
420+
421
				break;
422-
            encoder->hwenc.sts = MFXVideoCORE_SyncOperation(encoder->hwenc.ENCses, ENCsync, 10); // Synchronize. Wait until encoded frame is ready
422+
423
			else
424
			{
425
				printf("Exiting ENCODER for loop.\n");
426-
            encoder->hwenc.sts = send_h264stream(&encoder->hwenc.bitstr,encoder);
426+
427
			}
428
			
429-
	}            
429+
430
        {
431
            encoder->hwenc.sts = MFXVideoCORE_SyncOperation(encoder->hwenc.ENCses, ENCsync, 50); // Synchronize. Wait until encoded frame is ready
432
            MSDK_CHECK_RESULT(encoder->hwenc.sts, MFX_ERR_NONE, encoder->hwenc.sts);
433
434
            //Must send bitstream now
435
			++encoder->hwenc.nENCFrame;
436
			encoder->hwenc.sts = send_h264stream(&encoder->hwenc.bitstr,encoder);
437
            MSDK_BREAK_ON_ERROR(encoder->hwenc.sts);
438
		}
439
	}
440
		printf("Exiting 2nd while loop.\n");
441
		MSDK_IGNORE_MFX_STS(encoder->hwenc.sts, MFX_ERR_MORE_DATA);
442
		MSDK_CHECK_RESULT(encoder->hwenc.sts, MFX_ERR_NONE, encoder->hwenc.sts);
443
	}
444
	//Draining ENCODER buffer
445
	while(MFX_ERR_NONE <= encoder->hwenc.sts)
446
	{
447
		printf("Entering 3rd while loop.\n");
448
		for(;;)
449
		{
450
			encoder->hwenc.sts = MFXVideoENCODE_EncodeFrameAsync(encoder->hwenc.ENCses, NULL, NULL, &encoder->hwenc.bitstr,&ENCsync);
451
			if (MFX_ERR_NONE < encoder->hwenc.sts && !ENCsync)
452
			{
453
				if (MFX_WRN_DEVICE_BUSY == encoder->hwenc.sts)
454
					Sleep(1); // Wait if device is busy, then repeat the same call          
455
			}
456
            else if (MFX_ERR_NONE < encoder->hwenc.sts && ENCsync)
457
			{
458
				encoder->hwenc.sts = MFX_ERR_NONE; //Ignore warnings 
459
                break;
460
			}
461
			else if (MFX_ERR_NOT_ENOUGH_BUFFER == encoder->hwenc.sts)
462
			{
463
				printf("Must allocate more memory for output bitstream.\n");
464
				//Consider allocating more memory for bitstream output
465
				break;
466
			}
467
			else
468
			{
469
				printf("Exiting ENCODER for loop.\n");
470
				break;
471
			}
472
		}
473
		
474
		if(MFX_ERR_NONE == encoder->hwenc.sts)
475
        {
476
            encoder->hwenc.sts = MFXVideoCORE_SyncOperation(encoder->hwenc.ENCses, ENCsync, 50); // Synchronize. Wait until encoded frame is ready
477
            MSDK_CHECK_RESULT(encoder->hwenc.sts, MFX_ERR_NONE, encoder->hwenc.sts);
478
479
            //Must send bitstream now
480
			++encoder->hwenc.nENCFrame;
481
			encoder->hwenc.sts = send_h264stream(&encoder->hwenc.bitstr,encoder);
482
            MSDK_BREAK_ON_ERROR(encoder->hwenc.sts);
483
		}
484
	}
485
	
486
	MSDK_IGNORE_MFX_STS(encoder->hwenc.sts, MFX_ERR_MORE_SURFACE);
487
	MSDK_CHECK_RESULT(encoder->hwenc.sts, MFX_ERR_NONE, encoder->hwenc.sts);
488
	
489
#ifdef BENCHMARK
490
    QueryPerformanceCounter(&tEnd);
491
    double duration = ((double)tEnd.QuadPart - (double)tStart.QuadPart)  / freq;
492
    printf("\nExecution time: %3.2fs (%3.2ffps)\n", duration, ++encoder->hwenc.nENCFrame/duration);
493
#endif
494
	
495
	return 1;
496
}