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(¶ms, 0, sizeof(params)); |
229 | + | |
230 | - | encoder->hwenc.sts = MFXVideoENCODE_GetVideoParam(encoder->hwenc.ENCses, ¶ms); |
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(¶ms, 0, sizeof(params)); |
243 | encoder->hwenc.sts = MFXVideoENCODE_GetVideoParam(encoder->hwenc.ENCses, ¶ms); | |
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 | } |