1 // Copyright (c) 2019 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 #ifndef __MFX_MPEG2_ENC_COMMON_H__
22 #define __MFX_MPEG2_ENC_COMMON_H__
23 
24 // functions for VideoEditing
25 
26 #include "mfx_common.h"
27 #include "mfxvideo.h"
28 
29 class SHParametersEx
30 {
31 public:
SHParametersEx()32     SHParametersEx()
33     {
34         m_pBuffer = 0;
35         m_bufLen  = 0;
36     }
~SHParametersEx()37     ~SHParametersEx()
38     {
39         if (m_pBuffer)
40         {
41             delete [] m_pBuffer;
42         }
43     }
GetSH(mfxU8 ** pSH,mfxU32 * len)44     void GetSH (mfxU8 **pSH, mfxU32 *len)
45     {
46         *pSH = m_pBuffer;
47         *len = m_bufLen;
48     }
CheckSHParameters(mfxU8 * pSH,mfxU32 len,mfxU32 & real_len,mfxVideoParam * par,mfxExtCodingOption * extOpt)49     static bool CheckSHParameters (mfxU8 *pSH, mfxU32 len, mfxU32 &real_len, mfxVideoParam *par, mfxExtCodingOption * extOpt)
50     {
51         real_len = 0;
52         return DecodeSequenceHeader (pSH,len, par, extOpt, real_len);
53     }
FillSHParameters(mfxVideoParam * par,mfxExtCodingOption * extOpt)54     mfxStatus FillSHParameters (mfxVideoParam* par, mfxExtCodingOption * extOpt)
55     {
56         mfxU8 *pSH      = nullptr;
57         mfxU32 len      = 0;
58         mfxU32 real_len = 0;
59 
60         if (GetSPSBuffer(par, &pSH, &len))
61         {
62             if (!DecodeSequenceHeader (pSH,len, par, extOpt, real_len))
63                 return MFX_ERR_INCOMPATIBLE_VIDEO_PARAM;
64 
65             delete [] m_pBuffer;
66             m_pBuffer = new mfxU8 [real_len];
67 
68             std::copy(pSH, pSH + real_len, m_pBuffer);
69             m_bufLen  = real_len;
70         }
71         return MFX_ERR_NONE;
72     }
GetSPSBuffer(mfxVideoParam * par,mfxU8 ** ppSH,mfxU32 * pLen)73     static bool GetSPSBuffer(mfxVideoParam* par, mfxU8 **ppSH, mfxU32 *pLen)
74     {
75         mfxExtCodingOptionSPSPPS* pCO = GetExtCodingOptionsSPSPPS(par->ExtParam, par->NumExtParam);
76         if (pCO)
77         {
78             if (pCO->SPSBuffer && pCO->SPSBufSize!=0)
79             {
80                 *ppSH = pCO->SPSBuffer;
81                 *pLen = pCO->SPSBufSize;
82                 return true;
83             }
84         }
85         *ppSH = 0;
86         *pLen = 0;
87         return false;
88     }
GetExtCodingOptionsSPSPPS(mfxExtBuffer ** ebuffers,mfxU32 nbuffers)89     static mfxExtCodingOptionSPSPPS* GetExtCodingOptionsSPSPPS(mfxExtBuffer** ebuffers, mfxU32 nbuffers)
90     {
91         if (ebuffers)
92         {
93           for(mfxU32 i=0; i<nbuffers; i++)
94           {
95             if((*(ebuffers+i))->BufferId == MFX_EXTBUFF_CODING_OPTION_SPSPPS)
96             {
97               return (mfxExtCodingOptionSPSPPS*)(*(ebuffers+i));
98             }
99           }
100         }
101         return 0;
102     }
103 protected:
104 
105 // VideoEncode methods
106 #define _GetBits(n,out)   \
107     {\
108         mfxU32 bitreaded = 0;\
109         \
110         out = 0;\
111         if (ptr - pSH > (mfxI32)len - ((n+7)>>3))\
112             return false;\
113         \
114         while (n > bitreaded)\
115         {\
116             mfxU32 t = ((*ptr) << bitpos) &0xff;\
117             if (n - bitreaded >=  8 - bitpos)\
118             {\
119                 uint32_t num_bits = 8 - bitpos;\
120                 t = t >> (8-num_bits);\
121                 out = (out <<num_bits)|t;\
122                 bitreaded += num_bits;\
123                 bitpos = 0;\
124                 ptr ++;\
125             }\
126             else\
127             {\
128                 uint32_t num_bits = n - bitreaded;\
129                 t = t >> (8-num_bits);\
130                 out = (out <<num_bits)|t;\
131                 bitpos += num_bits;  \
132                 bitreaded += num_bits; \
133             \
134             }   \
135         }\
136     }
DARtoPAR(mfxU32 width,mfxU32 height,mfxU32 dar_h,mfxU32 dar_v,mfxU16 * par_h,mfxU16 * par_v)137     static bool DARtoPAR(mfxU32 width, mfxU32 height, mfxU32 dar_h, mfxU32 dar_v,
138                         mfxU16 *par_h, mfxU16 *par_v)
139     {
140       // (width*par_h) / (height*par_v) == dar_h/dar_v =>
141       // par_h / par_v == dar_h * height / (dar_v * width)
142       mfxU32 simple_tab[] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59};
143       mfxU32 i, denom;
144 
145       // suppose no overflow of 32s
146       mfxU32 h = dar_h * height;
147       mfxU32 v = dar_v * width;
148       // remove common multipliers
149       while( ((h|v)&1) == 0 ) {
150         h>>=1;
151         v>>=1;
152       }
153 
154       for(i=0;i<sizeof(simple_tab)/sizeof(simple_tab[0]);i++) {
155         denom = simple_tab[i];
156         while(h%denom==0 && v%denom==0) {
157           v /= denom;
158           h /= denom;
159         }
160         if(v<=denom || h<=denom)
161           break;
162       }
163       *par_h = (mfxU16)h;
164       *par_v = (mfxU16)v;
165       // can don't reach minimum, no problem
166      // if(i<sizeof(simple_tab)/sizeof(simple_tab[0]))
167      //   return false;
168       return true;
169     }
170 
DecodeSequenceHeader(mfxU8 * pSH,mfxU32 len,mfxVideoParam * par,mfxExtCodingOption * extOpt,mfxU32 & real_len)171     static bool DecodeSequenceHeader(
172         mfxU8 *              pSH,
173         mfxU32               len,
174         mfxVideoParam *      par,
175         mfxExtCodingOption * extOpt,
176         mfxU32 &             real_len)
177     {
178         mfxU32 bitpos = 0;
179         mfxU8* ptr = pSH;
180         mfxU32 temp = 0;
181         mfxU32 w = 0, h = 0;
182         mfxU32 aspect_ratio = 0;
183         mfxU32 frame_rate_code = 0;
184         mfxU32 frame_rate_code_n = 0;
185         mfxU32 frame_rate_code_d = 0;
186         mfxU32 vbv_buffer_size = 0;
187 
188         static const mfxU32 frame_rate_value_n [9] = {0, 24000, 24,25,30000,30,50,60000,60};
189         static const mfxU32 frame_rate_value_d [9] = {0, 1001,  1,  1, 1001, 1, 1, 1001, 1};
190 
191         real_len = 0;
192 
193         while ( *ptr == 0 && ptr - pSH < (mfxI32)len)
194         {
195             ptr ++;
196         }
197         _GetBits (8,temp);
198         if (temp != 0x01)
199             return false;
200 
201         _GetBits (8,temp);  // start code
202         if (temp != 0xB3)
203             return false;
204 
205         _GetBits (12, w);  // start code
206         _GetBits (12, h);  // start code
207 
208         if (!w || !h)
209             return false;
210 
211         _GetBits (4,aspect_ratio);
212         if (aspect_ratio > 4 || !aspect_ratio)
213             return false;
214 
215 
216        switch(aspect_ratio)
217        {
218        case 1:
219         par->mfx.FrameInfo.AspectRatioH = 1;
220         par->mfx.FrameInfo.AspectRatioW = 1;
221         break;
222        case 2:
223         DARtoPAR(w, h, 4, 3, &par->mfx.FrameInfo.AspectRatioW , &par->mfx.FrameInfo.AspectRatioH);
224         break;
225        case 3:
226         DARtoPAR(w, h, 16, 9, &par->mfx.FrameInfo.AspectRatioW , &par->mfx.FrameInfo.AspectRatioH);
227         break;
228        case 4:
229         DARtoPAR(w, h, 221, 100, &par->mfx.FrameInfo.AspectRatioW , &par->mfx.FrameInfo.AspectRatioH);
230         break;
231        default:
232          return false;
233        }
234         _GetBits (4,frame_rate_code);
235         if (frame_rate_code > 8 || !frame_rate_code)
236             return false;
237 
238         _GetBits (18,temp); //bitrate
239 
240         temp = ((temp)*400)/1000;
241         if (temp > 0x0000FFFF)
242             return false;
243         if (temp != 0)
244         {
245             par->mfx.TargetKbps = (mfxU16)temp;
246             par->mfx.RateControlMethod = MFX_RATECONTROL_CBR;
247         }
248 
249         _GetBits (1,temp);
250         if (!temp)
251             return false;
252 
253         _GetBits (10, vbv_buffer_size);
254 
255         _GetBits (1,temp);
256         if (temp)
257             return false;
258 
259         _GetBits (1,temp); // intra quant matrix
260         if (temp)
261             return false;
262 
263         _GetBits (1,temp); // inter quant matrix
264         if (temp)
265             return false;
266 
267         if (bitpos!=0)
268         {
269             ptr ++;
270             bitpos = 0;
271 
272         }
273         while ( *ptr == 0 && ptr - pSH < (mfxI32)len)
274         {
275             ptr ++;
276         }
277         temp = 0;
278         if (ptr - pSH >= (mfxI32)len - 3)
279           return false;
280 
281         _GetBits (8,temp);
282         if (temp != 0x01)
283             return false;
284 
285         _GetBits (12,temp);  // start code
286         if (temp != 0x0B51)
287             return false;
288 
289        _GetBits (1,temp); // escape bit
290 
291        _GetBits (3,temp); // profile
292 
293         switch(temp)
294         {
295         case 5:
296             par->mfx.CodecProfile = MFX_PROFILE_MPEG2_SIMPLE;
297             break;
298         case 4:
299             par->mfx.CodecProfile = MFX_PROFILE_MPEG2_MAIN;
300             break;
301         case 6:
302             par->mfx.CodecProfile = MFX_PROFILE_MPEG2_HIGH;
303             break;
304         default:
305              return false;
306         }
307 
308        _GetBits (4,temp); // level
309 
310         switch(temp)
311         {
312         case 10:
313             par->mfx.CodecLevel = MFX_LEVEL_MPEG2_LOW;
314             break;
315         case 8:
316              par->mfx.CodecLevel = MFX_LEVEL_MPEG2_MAIN;
317              break;
318         case 6:
319              par->mfx.CodecLevel = MFX_LEVEL_MPEG2_HIGH1440;
320              break;
321         case 4:
322              par->mfx.CodecLevel = MFX_LEVEL_MPEG2_HIGH;
323              break;
324         default:
325              return false;
326         }
327 
328         _GetBits (1,temp); // progressive
329 
330         if (temp == 1)
331         {
332             par->mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
333         }
334         else
335         {
336             par->mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_UNKNOWN;
337 
338             if (extOpt)
339                 extOpt->FramePicture = MFX_CODINGOPTION_ON;
340         }
341 
342         _GetBits (2,temp); //chroma format
343         if (temp != 1)
344             return false;
345 
346         par->mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
347 
348         _GetBits (2,temp); // ext h
349          if (temp != 0)
350             return false;
351 
352         _GetBits (2,temp); // ext w
353          if (temp != 0)
354             return false;
355 
356         _GetBits (12,temp); //bitrate ex
357         if (temp != 0)
358             return false;
359 
360         _GetBits (1,temp);
361         if (temp != 1)
362             return false;
363 
364         _GetBits (8,temp); // vbv_buffer_size_ext
365         vbv_buffer_size |= (temp << 10);
366         par->mfx.BufferSizeInKB = mfxU16(std::min<mfxU32>(0xffff, 2 * vbv_buffer_size));
367 
368         _GetBits (1,temp); //low delay
369         if (temp == 1)
370             return false;
371 
372         _GetBits (2,frame_rate_code_n);
373         _GetBits (5,frame_rate_code_d);
374 
375         if (bitpos!=0)
376         {
377             ptr ++;
378             bitpos = 0;
379         }
380         while ( *ptr == 0 && ptr - pSH < (mfxI32)len)
381         {
382             ptr ++;
383         }
384         temp = 0;
385         if (ptr - pSH < (mfxI32)len - 3)
386         {
387             _GetBits (8,temp);
388             if (temp != 0x01)
389                 return false;
390             _GetBits (12,temp);  // start code
391         }
392 
393         par->mfx.FrameInfo.CropX = 0;
394         par->mfx.FrameInfo.CropY = 0;
395         par->mfx.FrameInfo.CropW = (mfxU16) w;
396         par->mfx.FrameInfo.CropH = (mfxU16) h;
397 
398         par->mfx.FrameInfo.Width  = par->mfx.FrameInfo.Width > (mfxU16)(((w+15)/16)*16)? par->mfx.FrameInfo.Width : (mfxU16)(((w+15)/16)*16);
399         if (par->mfx.FrameInfo.PicStruct == MFX_PICSTRUCT_PROGRESSIVE)
400         {
401             par->mfx.FrameInfo.Height = par->mfx.FrameInfo.Height> (mfxU16)(((h+15)/16)*16)? par->mfx.FrameInfo.Height: (mfxU16)(((h+15)/16)*16);
402         }
403         else
404         {
405             par->mfx.FrameInfo.Height = par->mfx.FrameInfo.Height> (mfxU16)(((h+31)/32)*32)? par->mfx.FrameInfo.Height: (mfxU16)(((h+31)/32)*32);
406         }
407         par->mfx.FrameInfo.FrameRateExtD = (frame_rate_code_d + 1)*frame_rate_value_d[frame_rate_code];
408         par->mfx.FrameInfo.FrameRateExtN = (frame_rate_code_n + 1)*frame_rate_value_n[frame_rate_code];
409 
410         if (temp == 0x0B52)
411         {
412               _GetBits (3,temp); //video format
413              if (temp > 5)
414                  return false;
415 
416              _GetBits (1,temp); //colour_description
417 
418              if (temp)
419              {
420                  _GetBits (24,temp);
421              }
422              _GetBits (14,temp);
423              if (temp != w)
424                  return false;
425 
426              _GetBits (1,temp);
427              if (temp != 1)
428                  return false;
429 
430              _GetBits (14,temp);
431              if (temp != h)
432                  return false;
433 
434              if (bitpos!=0)
435              {
436                 ptr ++;
437                 bitpos = 0;
438              }
439         }
440         real_len = (mfxU32)(ptr - pSH);
441         return true;
442 
443     }
444 #undef _GetBits
445 
446 
447 private:
448     mfxU8*        m_pBuffer;
449     mfxU32        m_bufLen;
450 
451     // Declare private copy constructor to avoid accidental assignment
452     // and klocwork complaining.
453     SHParametersEx (const SHParametersEx &);
454     SHParametersEx & operator = (const SHParametersEx &);
455 };
456 
457 #endif