1 // Copyright (c) 2017-2020 Intel Corporation
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in all
11 // copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 // SOFTWARE.
20 
21 #include "mfx_common.h"
22 #if defined (MFX_ENABLE_MJPEG_VIDEO_ENCODE)
23 
24 #include "mfx_mjpeg_encode_hw_utils.h"
25 #include "libmfx_core_factory.h"
26 #include "libmfx_core_interface.h"
27 #include "jpegbase.h"
28 #include "mfx_enc_common.h"
29 #include "mfx_mjpeg_encode_interface.h"
30 
31 using namespace MfxHwMJpegEncode;
32 
33 
QueryHwCaps(VideoCORE * core,JpegEncCaps & hwCaps)34 mfxStatus MfxHwMJpegEncode::QueryHwCaps(VideoCORE * core, JpegEncCaps & hwCaps)
35 {
36     MFX_CHECK_NULL_PTR1(core);
37 
38     if (core->GetVAType() == MFX_HW_VAAPI && core->GetHWType() < MFX_HW_CHT)
39         return MFX_ERR_UNSUPPORTED;
40 
41     std::unique_ptr<DriverEncoder> ddi;
42     ddi.reset( CreatePlatformMJpegEncoder(core) );
43     if (ddi.get() == 0)
44         return MFX_ERR_NULL_PTR;
45 
46     // the device is created just to query caps,
47     // so width/height are insignificant
48     mfxStatus sts = ddi->CreateAuxilliaryDevice(core, 640, 480, true);
49     MFX_CHECK_STS(sts);
50 
51     sts = ddi->QueryEncodeCaps(hwCaps);
52     MFX_CHECK_STS(sts);
53 
54     return MFX_ERR_NONE;
55 }
56 
IsJpegParamExtBufferIdSupported(mfxU32 id)57 bool MfxHwMJpegEncode::IsJpegParamExtBufferIdSupported(mfxU32 id)
58 {
59     return
60         id == MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION ||
61         id == MFX_EXTBUFF_JPEG_QT ||
62         id == MFX_EXTBUFF_JPEG_HUFFMAN;
63 }
64 
CheckExtBufferId(mfxVideoParam const & par)65 mfxStatus MfxHwMJpegEncode::CheckExtBufferId(mfxVideoParam const & par)
66 {
67     for (mfxU32 i = 0; i < par.NumExtParam; i++)
68     {
69         if (par.ExtParam[i] == 0)
70             return MFX_ERR_INVALID_VIDEO_PARAM;
71 
72         if (!IsJpegParamExtBufferIdSupported(par.ExtParam[i]->BufferId))
73             return MFX_ERR_INVALID_VIDEO_PARAM;
74 
75         // check if buffer presents twice in video param
76         if (GetExtBuffer(
77             par.ExtParam + i + 1,
78             par.NumExtParam - i - 1,
79             par.ExtParam[i]->BufferId) != 0)
80         {
81             return MFX_ERR_INVALID_VIDEO_PARAM;
82         }
83     }
84 
85     return MFX_ERR_NONE;
86 }
87 
CheckJpegParam(VideoCORE * core,mfxVideoParam & par,JpegEncCaps const & hwCaps)88 mfxStatus MfxHwMJpegEncode::CheckJpegParam(VideoCORE *core, mfxVideoParam & par, JpegEncCaps const & hwCaps)
89 {
90     MFX_CHECK(core, MFX_ERR_UNDEFINED_BEHAVIOR);
91     MFX_CHECK(hwCaps.Baseline, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
92     MFX_CHECK(hwCaps.Sequential, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
93     MFX_CHECK(hwCaps.Huffman, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
94 
95     MFX_CHECK((par.mfx.Interleaved && hwCaps.Interleaved) || (!par.mfx.Interleaved && hwCaps.NonInterleaved),
96         MFX_WRN_PARTIAL_ACCELERATION);
97 
98     MFX_CHECK(par.mfx.FrameInfo.Width > 0 && par.mfx.FrameInfo.Height > 0,
99         MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
100 
101     mfxF64 BytesPerPx = 0;
102     switch (par.mfx.FrameInfo.FourCC)
103     {
104         case MFX_FOURCC_NV12:
105         case MFX_FOURCC_YV12:
106             BytesPerPx = 1.5;
107             break;
108         case MFX_FOURCC_YUY2:
109             BytesPerPx = 2;
110             break;
111         case MFX_FOURCC_RGB4:
112         default:
113             BytesPerPx = 4;
114     }
115     if (core->GetVAType() == MFX_HW_D3D9)
116     {
117         MFX_CHECK(par.mfx.FrameInfo.Height <= hwCaps.MaxPicWidth/BytesPerPx, MFX_WRN_PARTIAL_ACCELERATION );
118     }
119 
120     MFX_CHECK(par.mfx.FrameInfo.Width <= (mfxU16)hwCaps.MaxPicWidth && par.mfx.FrameInfo.Height <= (mfxU16)hwCaps.MaxPicHeight,
121         MFX_WRN_PARTIAL_ACCELERATION);
122 
123     MFX_CHECK(hwCaps.SampleBitDepth == 8, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
124     MFX_CHECK(hwCaps.MaxNumComponent == 3, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
125     MFX_CHECK(hwCaps.MaxNumScan >= 1, MFX_WRN_PARTIAL_ACCELERATION);
126 
127     mfxStatus sts = CheckExtBufferId(par);
128     if (sts != MFX_ERR_NONE)
129         return MFX_WRN_PARTIAL_ACCELERATION;
130 
131     mfxExtJPEGQuantTables* qt_in  = (mfxExtJPEGQuantTables*)GetExtBuffer( par.ExtParam, par.NumExtParam, MFX_EXTBUFF_JPEG_QT );
132     mfxExtJPEGHuffmanTables* ht_in  = (mfxExtJPEGHuffmanTables*)GetExtBuffer( par.ExtParam, par.NumExtParam, MFX_EXTBUFF_JPEG_HUFFMAN );
133 
134     if (qt_in && qt_in->NumTable > hwCaps.MaxNumQuantTable)
135         return MFX_WRN_PARTIAL_ACCELERATION;
136     if (ht_in && (ht_in->NumDCTable > hwCaps.MaxNumHuffTable || ht_in->NumACTable > hwCaps.MaxNumHuffTable))
137         return MFX_WRN_PARTIAL_ACCELERATION;
138 
139     return MFX_ERR_NONE;
140 }
141 
FastCopyFrameBufferSys2Vid(VideoCORE * core,mfxMemId vidMemId,mfxFrameData & sysSurf,mfxFrameInfo & frmInfo)142 mfxStatus MfxHwMJpegEncode::FastCopyFrameBufferSys2Vid(
143     VideoCORE    * core,
144     mfxMemId       vidMemId,
145     mfxFrameData & sysSurf,
146     mfxFrameInfo & frmInfo
147     )
148 {
149     MFX_CHECK_NULL_PTR1(core);
150     mfxFrameData vidSurf = {};
151     mfxStatus sts = MFX_ERR_NONE;
152     vidSurf.MemId = vidMemId;
153 
154     {
155         MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_INTERNAL, "Copy input (sys->vid)");
156         mfxFrameSurface1 surfSrc = { {0,}, frmInfo, sysSurf };
157         mfxFrameSurface1 surfDst = { {0,}, frmInfo, vidSurf };
158         sts = core->DoFastCopyWrapper(&surfDst,MFX_MEMTYPE_INTERNAL_FRAME|MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET, &surfSrc,MFX_MEMTYPE_EXTERNAL_FRAME|MFX_MEMTYPE_SYSTEM_MEMORY);
159         MFX_CHECK_STS(sts);
160     }
161     MFX_CHECK_STS(sts);
162 
163     return sts;
164 }
165 
Init(mfxVideoParam const * par,mfxEncodeCtrl const * ctrl,JpegEncCaps const * hwCaps)166 mfxStatus ExecuteBuffers::Init(mfxVideoParam const *par, mfxEncodeCtrl const * ctrl, JpegEncCaps const * hwCaps)
167 {
168     mfxStatus sts = MFX_ERR_NONE;
169 
170     mfxU32 fourCC = par->mfx.FrameInfo.FourCC;
171     mfxU16 chromaFormat = par->mfx.FrameInfo.ChromaFormat;
172 
173     mfxExtJPEGQuantTables* jpegQT = NULL;
174     mfxExtJPEGHuffmanTables* jpegHT = NULL;
175     if (ctrl && ctrl->ExtParam && ctrl->NumExtParam > 0)
176     {
177         jpegQT = (mfxExtJPEGQuantTables*)   GetExtBuffer( ctrl->ExtParam, ctrl->NumExtParam, MFX_EXTBUFF_JPEG_QT );
178         jpegHT = (mfxExtJPEGHuffmanTables*) GetExtBuffer( ctrl->ExtParam, ctrl->NumExtParam, MFX_EXTBUFF_JPEG_HUFFMAN );
179     }
180 
181     mfxExtJPEGQuantTables* jpegQTInitial = (mfxExtJPEGQuantTables*) GetExtBuffer( par->ExtParam, par->NumExtParam, MFX_EXTBUFF_JPEG_QT );
182     mfxExtJPEGHuffmanTables* jpegHTInitial = (mfxExtJPEGHuffmanTables*) GetExtBuffer( par->ExtParam, par->NumExtParam, MFX_EXTBUFF_JPEG_HUFFMAN );
183 
184     m_payload_base.length = 0;
185     m_payload_list.clear();
186     if (fourCC == MFX_FOURCC_RGB4 && chromaFormat == MFX_CHROMAFORMAT_YUV444)
187     {
188         m_app14_data.header    = 0xEEFF;//APP14
189         m_app14_data.lenH      = 0;
190         m_app14_data.lenL      = 14;
191         m_app14_data.s[0]      = 0x41;//"A"
192         m_app14_data.s[1]      = 0x64;//"D"
193         m_app14_data.s[2]      = 0x6F;//"O"
194         m_app14_data.s[3]      = 0x62;//"B"
195         m_app14_data.s[4]      = 0x65;//"E"
196         m_app14_data.versionH  = 0;
197         m_app14_data.versionL  = 0x64;
198         m_app14_data.flags0H   = 0;
199         m_app14_data.flags0L   = 0;
200         m_app14_data.flags1H   = 0;
201         m_app14_data.flags1L   = 0;
202         m_app14_data.transform = 0; //RGB
203 
204         mfxU32 payloadSize = 16;
205         if (m_payload_base.length + payloadSize > m_payload_base.maxLength)
206         {
207             mfxU8* data = new mfxU8[m_payload_base.length + payloadSize];
208             std::copy(m_payload_base.data, m_payload_base.data + m_payload_base.length, data);
209             delete[] m_payload_base.data;
210             m_payload_base.data = data;
211             m_payload_base.maxLength = m_payload_base.length + payloadSize;
212         }
213         m_payload_list.resize(1);
214         m_payload_list.back().data = m_payload_base.data + m_payload_base.length;
215         std::copy(reinterpret_cast<mfxU8*>(&m_app14_data), reinterpret_cast<mfxU8*>(&m_app14_data) + payloadSize, m_payload_list.back().data);
216         m_payload_list.back().length = payloadSize;
217         m_payload_base.length += m_payload_list.back().length;
218     }
219     else
220     {
221         m_app0_data.header      = 0xE0FF;//APP0
222         m_app0_data.lenH        = 0;
223         m_app0_data.lenL        = 16;
224         m_app0_data.s[0]        = 0x4A;//"J"
225         m_app0_data.s[1]        = 0x46;//"F"
226         m_app0_data.s[2]        = 0x49;//"I"
227         m_app0_data.s[3]        = 0x46;//"F"
228         m_app0_data.s[4]        = 0;   // 0
229         m_app0_data.versionH    = 0x01;
230         m_app0_data.versionL    = 0x02;
231         m_app0_data.units       = JRU_NONE;
232         m_app0_data.xDensity    = 0x0100;//1
233         m_app0_data.yDensity    = 0x0100;//1
234         m_app0_data.xThumbnails = 0;
235         m_app0_data.yThumbnails = 0;
236 
237         mfxU32 payloadSize = 18;
238         if (m_payload_base.length + payloadSize > m_payload_base.maxLength)
239         {
240             mfxU8* data = new mfxU8[m_payload_base.length + payloadSize];
241             std::copy(m_payload_base.data, m_payload_base.data + m_payload_base.length, data);
242             delete[] m_payload_base.data;
243             m_payload_base.data = data;
244             m_payload_base.maxLength = m_payload_base.length + payloadSize;
245         }
246         m_payload_list.resize(1);
247         m_payload_list.back().data = m_payload_base.data + m_payload_base.length;
248         std::copy(reinterpret_cast<mfxU8*>(&m_app0_data), reinterpret_cast<mfxU8*>(&m_app0_data) + payloadSize, m_payload_list.back().data);
249         m_payload_list.back().length = payloadSize;
250         m_payload_base.length += m_payload_list.back().length;
251     }
252 
253     if (ctrl && ctrl->Payload && ctrl->NumPayload > 0)
254     {
255         for (mfxU16 i=0; i<ctrl->NumPayload; i++)
256         {
257             mfxPayload* pExtPayload = ctrl->Payload[i];
258             if (pExtPayload)
259             {
260                 if (pExtPayload->Data && (pExtPayload->NumBit>>3) > 0)
261                 {
262                     mfxU32 payloadSize = pExtPayload->NumBit>>3;
263                     if (m_payload_base.length + payloadSize > m_payload_base.maxLength)
264                     {
265                         mfxU8* data = new mfxU8[m_payload_base.length + payloadSize];
266                         std::copy(m_payload_base.data, m_payload_base.data + m_payload_base.length, data);
267                         delete[] m_payload_base.data;
268                         m_payload_base.data = data;
269                         m_payload_base.maxLength = m_payload_base.length + payloadSize;
270                     }
271                     m_payload_list.resize(m_payload_list.size()+1);
272                     m_payload_list.back().data = m_payload_base.data + m_payload_base.length;
273                     std::copy(pExtPayload->Data, pExtPayload->Data + payloadSize, m_payload_list.back().data);
274                     m_payload_list.back().length = payloadSize;
275                     m_payload_base.length += m_payload_list.back().length;
276                 }
277                 else
278                 {
279                     return MFX_ERR_INVALID_VIDEO_PARAM;
280                 }
281             }
282         }
283     }
284 
285 #if defined (MFX_VA_LINUX)
286     // Picture Header
287     memset(&m_pps, 0, sizeof(m_pps));
288     m_pps.reconstructed_picture = 0;
289     m_pps.pic_flags.bits.profile = 0;
290     m_pps.pic_flags.bits.progressive = 0;
291     m_pps.pic_flags.bits.huffman = 1;
292     m_pps.pic_flags.bits.interleaved   = (par->mfx.Interleaved != 0);
293     m_pps.pic_flags.bits.differential  = 0;
294     m_pps.picture_width       = (mfxU32)par->mfx.FrameInfo.CropW;
295     m_pps.picture_height      = (mfxU32)par->mfx.FrameInfo.CropH;
296     m_pps.sample_bit_depth = 8;
297     m_pps.component_id[0] = 1;
298     m_pps.component_id[1] = 2;
299     m_pps.component_id[2] = 3;
300 
301     if (!jpegQT && !jpegQTInitial)
302         m_pps.quality = (par->mfx.Quality > 100) ? 100 : par->mfx.Quality;
303 
304     if (fourCC == MFX_FOURCC_NV12 && chromaFormat == MFX_CHROMAFORMAT_YUV420)
305         m_pps.num_components = 3;
306     else if (fourCC == MFX_FOURCC_YUY2 && chromaFormat == MFX_CHROMAFORMAT_YUV422H)
307         m_pps.num_components = 3;
308     else if (fourCC == MFX_FOURCC_NV12 && chromaFormat == MFX_CHROMAFORMAT_YUV400)
309         m_pps.num_components = 1;
310     else if (fourCC == MFX_FOURCC_RGB4 && chromaFormat == MFX_CHROMAFORMAT_YUV444)
311         m_pps.num_components = 3;
312     else
313         return MFX_ERR_UNDEFINED_BEHAVIOR;
314 
315     // Scan Header
316     m_pps.num_scan = 1;
317     m_scan_list.resize(1);
318     memset(&m_scan_list[0], 0, sizeof(m_scan_list[0]));
319     m_scan_list[0].restart_interval = par->mfx.RestartInterval;
320     m_scan_list[0].num_components = m_pps.num_components;
321     m_scan_list[0].components[0].component_selector = 1;
322     m_scan_list[0].components[1].component_selector = 2;
323     m_scan_list[0].components[2].component_selector = 3;
324 
325     // Quanlization tables
326     if (jpegQT || jpegQTInitial)
327     {
328         // External tables
329         mfxExtJPEGQuantTables *pExtQuant = jpegQT ? jpegQT : jpegQTInitial;
330         MFX_CHECK(pExtQuant->NumTable && (pExtQuant->NumTable <= hwCaps->MaxNumQuantTable), MFX_ERR_UNDEFINED_BEHAVIOR);
331         m_dqt_list.resize(1);
332         if(pExtQuant->NumTable == 1)
333         {
334             m_dqt_list[0].load_lum_quantiser_matrix = true;
335             m_dqt_list[0].load_chroma_quantiser_matrix = false;
336             for(mfxU16 i = 0; i< 64; i++)
337             {
338                 m_dqt_list[0].lum_quantiser_matrix[i]=(unsigned char) pExtQuant->Qm[0][i];
339             }
340             m_pps.quantiser_table_selector[0] = 0;
341             m_pps.quantiser_table_selector[1] = 0;
342             m_pps.quantiser_table_selector[2] = 0;
343         }
344         else if(pExtQuant->NumTable == 2)
345         {
346             m_dqt_list[0].load_chroma_quantiser_matrix = true;
347             m_dqt_list[0].load_lum_quantiser_matrix = true;
348             for(mfxU16 i = 0; i< 64; i++)
349             {
350                 m_dqt_list[0].lum_quantiser_matrix[i]=(unsigned char) pExtQuant->Qm[0][i];
351                 m_dqt_list[0].chroma_quantiser_matrix[i]=(unsigned char) pExtQuant->Qm[1][i];
352             }
353             m_pps.quantiser_table_selector[0] = 0;
354             m_pps.quantiser_table_selector[1] = 1;
355             m_pps.quantiser_table_selector[2] = 1;
356         }
357         else
358             return MFX_ERR_INVALID_VIDEO_PARAM;
359     }
360     else
361     {
362         // No external tables - use Quality parameter
363         m_dqt_list.resize(0);
364         if (fourCC == MFX_FOURCC_RGB4)
365         {
366             m_pps.quantiser_table_selector[0] = 0;
367             m_pps.quantiser_table_selector[1] = 0;
368             m_pps.quantiser_table_selector[2] = 0;
369         }
370         else
371         {
372             m_pps.quantiser_table_selector[0] = 0;
373             m_pps.quantiser_table_selector[1] = 1;
374             m_pps.quantiser_table_selector[2] = 1;
375         }
376     }
377 
378     // Huffman tables
379     if (jpegHT || jpegHTInitial)
380     {
381         // External tables
382         mfxExtJPEGHuffmanTables *pExtHuffman = jpegHT ? jpegHT : jpegHTInitial;
383         MFX_CHECK(pExtHuffman->NumDCTable &&
384                   pExtHuffman->NumACTable &&
385                  (pExtHuffman->NumDCTable < hwCaps->MaxNumHuffTable) &&
386                  (pExtHuffman->NumACTable < hwCaps->MaxNumHuffTable), MFX_ERR_UNDEFINED_BEHAVIOR);
387         m_dht_list.resize(1);
388         for (mfxU16 j = 0; j < pExtHuffman->NumDCTable; j++)
389         {
390             if(j < 2)
391             {
392                 MFX_INTERNAL_CPY(m_dht_list[0].huffman_table[j].num_dc_codes, pExtHuffman->DCTables[j].Bits, 16 * sizeof(mfxU8));
393                 MFX_INTERNAL_CPY(m_dht_list[0].huffman_table[j].dc_values, pExtHuffman->DCTables[j].Values, 12 * sizeof(mfxU8));
394             }
395             else
396                 return MFX_ERR_INVALID_VIDEO_PARAM;
397         }
398         for (mfxU16 j = 0; j < pExtHuffman->NumACTable; j++)
399         {
400             if(j < 2)
401             {
402                 MFX_INTERNAL_CPY(m_dht_list[0].huffman_table[j].num_ac_codes, pExtHuffman->ACTables[j].Bits, 16 * sizeof(mfxU8));
403                 MFX_INTERNAL_CPY(m_dht_list[0].huffman_table[j].ac_values, pExtHuffman->ACTables[j].Values, 162 * sizeof(mfxU8));
404             }
405             else
406                 return MFX_ERR_INVALID_VIDEO_PARAM;
407         }
408     }
409     else
410     {
411         // Internal tables
412         if (hwCaps->MaxNumHuffTable == 0)
413         {
414             m_dht_list.resize(0);
415         }
416         else if (hwCaps->MaxNumHuffTable == 1 || fourCC == MFX_FOURCC_RGB4)
417         {
418             m_dht_list.resize(1);
419 
420             m_dht_list[0].load_huffman_table[0] = 1;  //0 for luma
421 
422             for(mfxU16 i = 0; i < 16; i++)
423                 m_dht_list[0].huffman_table[0].num_dc_codes[i] = DefaultLuminanceDCBits[i];
424             for(mfxU16 i = 0; i < 12; i++)
425                 m_dht_list[0].huffman_table[0].dc_values[i] = DefaultLuminanceDCValues[i];
426             for(mfxU16 i = 0; i < 16; i++)
427                 m_dht_list[0].huffman_table[0].num_ac_codes[i] = DefaultLuminanceACBits[i];
428             for(mfxU16 i = 0; i < 162; i++)
429                 m_dht_list[0].huffman_table[0].ac_values[i] = DefaultLuminanceACValues[i];
430 
431             m_scan_list[0].components[0].dc_table_selector = 0;
432             m_scan_list[0].components[1].dc_table_selector = 0;
433             m_scan_list[0].components[2].dc_table_selector = 0;
434             m_scan_list[0].components[0].ac_table_selector = 0;
435             m_scan_list[0].components[1].ac_table_selector = 0;
436             m_scan_list[0].components[2].ac_table_selector = 0;
437         }
438         else
439         {
440             m_dht_list.resize(1);
441 
442             m_dht_list[0].load_huffman_table[0] = 1;  //0 for luma
443             m_dht_list[0].load_huffman_table[1] = 1;  // 1 for chroma
444 
445             for(mfxU16 i = 0; i < 16; i++)
446                 m_dht_list[0].huffman_table[0].num_dc_codes[i] = DefaultLuminanceDCBits[i];
447             for(mfxU16 i = 0; i < 12; i++)
448                 m_dht_list[0].huffman_table[0].dc_values[i] = DefaultLuminanceDCValues[i];
449             for(mfxU16 i = 0; i < 16; i++)
450                 m_dht_list[0].huffman_table[0].num_ac_codes[i] = DefaultLuminanceACBits[i];
451             for(mfxU16 i = 0; i < 162; i++)
452                 m_dht_list[0].huffman_table[0].ac_values[i] = DefaultLuminanceACValues[i];
453             for(mfxU16 i = 0; i < 16; i++)
454                 m_dht_list[0].huffman_table[1].num_dc_codes[i] = DefaultChrominanceDCBits[i];
455             for(mfxU16 i = 0; i < 12; i++)
456                 m_dht_list[0].huffman_table[1].dc_values[i] = DefaultChrominanceDCValues[i];
457             for(mfxU16 i = 0; i < 16; i++)
458                 m_dht_list[0].huffman_table[1].num_ac_codes[i] = DefaultChrominanceACBits[i];
459             for(mfxU16 i = 0; i < 162; i++)
460                 m_dht_list[0].huffman_table[1].ac_values[i] = DefaultChrominanceACValues[i];
461 
462             m_scan_list[0].components[0].dc_table_selector = 0;
463             m_scan_list[0].components[1].dc_table_selector = 1;
464             m_scan_list[0].components[2].dc_table_selector = 1;
465             m_scan_list[0].components[0].ac_table_selector = 0;
466             m_scan_list[0].components[1].ac_table_selector = 1;
467             m_scan_list[0].components[2].ac_table_selector = 1;
468         }
469     }
470 #endif
471 
472     return sts;
473 }
474 
Close()475 void ExecuteBuffers::Close()
476 {
477     if (m_payload_base.data)
478     {
479         delete [] m_payload_base.data;
480         m_payload_base.data = 0;
481         m_payload_base.length = 0;
482         m_payload_base.maxLength = 0;
483     }
484     m_dht_list.clear();
485     m_dqt_list.clear();
486     m_scan_list.clear();
487     m_payload_list.clear();
488 }
489 
TaskManager()490 TaskManager::TaskManager()
491 {
492     m_pTaskList = 0;
493     m_TaskNum   = 0;
494 }
495 
~TaskManager()496 TaskManager::~TaskManager()
497 {
498     UMC::AutomaticUMCMutex guard(m_mutex);
499 
500     Close();
501 }
502 
Init(mfxU32 maxTaskNum)503 mfxStatus TaskManager::Init(mfxU32 maxTaskNum)
504 {
505     UMC::AutomaticUMCMutex guard(m_mutex);
506 
507     if (maxTaskNum > 0 &&
508         maxTaskNum < JPEG_DDITASK_MAX_NUM)
509     {
510         m_TaskNum = maxTaskNum;
511         m_pTaskList = new DdiTask[m_TaskNum];
512         memset(m_pTaskList, 0, m_TaskNum * sizeof(DdiTask));
513         for (mfxU32 i = 0; i < m_TaskNum; i++)
514         {
515             m_pTaskList[i].m_idx = i;
516             m_pTaskList[i].m_idxBS = i;
517         }
518         return MFX_ERR_NONE;
519     }
520     else
521     {
522         m_pTaskList = 0;
523         m_TaskNum   = 0;
524         return MFX_ERR_INVALID_VIDEO_PARAM;
525     }
526 }
527 
Reset()528 mfxStatus TaskManager::Reset()
529 {
530     UMC::AutomaticUMCMutex guard(m_mutex);
531 
532     if (m_pTaskList)
533     {
534         for (mfxU32 i = 0; i < m_TaskNum; i++)
535         {
536             if(m_pTaskList[i].m_pDdiData)
537             {
538                 m_pTaskList[i].m_pDdiData->Close();
539                 delete m_pTaskList[i].m_pDdiData;
540                 m_pTaskList[i].m_pDdiData = NULL;
541             }
542             vm_interlocked_xchg32(&m_pTaskList[i].lInUse, 0);
543             m_pTaskList[i].surface = 0;
544             m_pTaskList[i].bs      = 0;
545         }
546     }
547 
548     return MFX_ERR_NONE;
549 }
550 
Close()551 mfxStatus TaskManager::Close()
552 {
553     if (m_pTaskList)
554     {
555         for (mfxU32 i = 0; i < m_TaskNum; i++)
556         {
557             if(m_pTaskList[i].m_pDdiData)
558             {
559                 m_pTaskList[i].m_pDdiData->Close();
560                 delete m_pTaskList[i].m_pDdiData;
561                 m_pTaskList[i].m_pDdiData = NULL;
562             }
563         }
564         delete [] m_pTaskList;
565         m_pTaskList = 0;
566     }
567 
568     return MFX_ERR_NONE;
569 }
570 
AssignTask(DdiTask * & newTask)571 mfxStatus TaskManager::AssignTask(DdiTask *& newTask)
572 {
573     UMC::AutomaticUMCMutex guard(m_mutex);
574 
575     if (m_pTaskList)
576     {
577         mfxU32 i;
578         for (i = 0; i < m_TaskNum; i++)
579         {
580             if (m_pTaskList[i].lInUse == 0)
581                 break;
582         }
583         if (i < m_TaskNum)
584         {
585             newTask = &m_pTaskList[i];
586             vm_interlocked_xchg32(&newTask->lInUse, 1);
587             return MFX_ERR_NONE;
588         }
589         else
590         {
591             return MFX_WRN_DEVICE_BUSY;
592         }
593     }
594     else
595     {
596         return MFX_ERR_NULL_PTR;
597     }
598 }
599 
RemoveTask(DdiTask & task)600 mfxStatus TaskManager::RemoveTask(DdiTask & task)
601 {
602     UMC::AutomaticUMCMutex guard(m_mutex);
603 
604     if (m_pTaskList)
605     {
606         vm_interlocked_xchg32(&task.lInUse, 0);
607         task.surface = 0;
608         task.bs      = 0;
609         return MFX_ERR_NONE;
610     }
611     else
612     {
613         return MFX_ERR_NULL_PTR;
614     }
615 }
616 
617 #endif // #if defined (MFX_ENABLE_MJPEG_VIDEO_ENCODE) && defined (MFX_VA)
618