1 // Copyright (c) 2017-2018 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 "umc_defs.h"
22 #if defined (MFX_ENABLE_H264_VIDEO_DECODE)
23 
24 #include <memory>
25 
26 #include "umc_h264_au_splitter.h"
27 #include "umc_h264_nal_spl.h"
28 
29 namespace UMC
30 {
31 
32 /****************************************************************************************************/
33 // SeiPayloadArray class routine
34 /****************************************************************************************************/
SeiPayloadArray()35 SeiPayloadArray::SeiPayloadArray()
36 {
37     m_payloads.reserve(3);
38 }
39 
SeiPayloadArray(const SeiPayloadArray & payloads)40 SeiPayloadArray::SeiPayloadArray(const SeiPayloadArray & payloads)
41 :m_payloads()
42 {
43     size_t count = payloads.GetPayloadCount();
44     for (size_t i = 0; i < count; i++)
45     {
46         AddPayload(payloads.GetPayload(i));
47     }
48 }
49 
~SeiPayloadArray()50 SeiPayloadArray::~SeiPayloadArray()
51 {
52     Release();
53 }
54 
GetPayloadCount() const55 size_t SeiPayloadArray::GetPayloadCount() const
56 {
57     return m_payloads.size();
58 }
59 
GetPayload(size_t pos) const60 UMC_H264_DECODER::H264SEIPayLoad* SeiPayloadArray::GetPayload(size_t pos) const
61 {
62     if (pos >= m_payloads.size())
63         return 0;
64 
65     return m_payloads[pos];
66 }
67 
FindPayload(SEI_TYPE type) const68 UMC_H264_DECODER::H264SEIPayLoad* SeiPayloadArray::FindPayload(SEI_TYPE type) const
69 {
70     int32_t pos = FindPayloadPos(type);
71     return (pos < 0) ? 0 : GetPayload(pos);
72 }
73 
FindPayloadPos(SEI_TYPE type) const74 int32_t SeiPayloadArray::FindPayloadPos(SEI_TYPE type) const
75 {
76     size_t count = m_payloads.size();
77     for (size_t i = 0; i < count; i++)
78     {
79         UMC_H264_DECODER::H264SEIPayLoad* payload = m_payloads[i];
80         if (payload->payLoadType == type)
81             return (int32_t)i;
82     }
83 
84     return -1;
85 }
86 
MovePayloadsFrom(SeiPayloadArray & payloads)87 void SeiPayloadArray::MovePayloadsFrom(SeiPayloadArray &payloads)
88 {
89     size_t count = payloads.GetPayloadCount();
90     for (size_t i = 0; i < count; i++)
91     {
92         AddPayload(payloads.GetPayload(i));
93     }
94 
95     payloads.Release();
96 }
97 
Release()98 void SeiPayloadArray::Release()
99 {
100     PayloadArray::iterator iter = m_payloads.begin();
101     PayloadArray::iterator iter_end = m_payloads.end();
102     for (; iter != iter_end; ++iter)
103     {
104         UMC_H264_DECODER::H264SEIPayLoad* payload = *iter;
105         payload->DecrementReference();
106     }
107 
108     m_payloads.clear();
109 }
110 
AddPayload(UMC_H264_DECODER::H264SEIPayLoad * payload)111 void SeiPayloadArray::AddPayload(UMC_H264_DECODER::H264SEIPayLoad* payload)
112 {
113     if (!payload)
114         return;
115 
116     payload->IncrementReference();
117     int32_t pos = FindPayloadPos(payload->payLoadType);
118     if (pos >= 0) // always use last payload
119     {
120         m_payloads[pos]->DecrementReference();
121         m_payloads[pos] = payload;
122         return;
123     }
124 
125     m_payloads.push_back(payload);
126 }
127 
128 /****************************************************************************************************/
129 // SetOfSlices class routine
130 /****************************************************************************************************/
SetOfSlices()131 SetOfSlices::SetOfSlices()
132     : m_frame(0)
133     , m_isCompleted(false)
134     , m_isFull(false)
135 {
136 }
137 
SetOfSlices(const SetOfSlices & set)138 SetOfSlices::SetOfSlices(const SetOfSlices& set)
139     : m_frame(set.m_frame)
140     , m_isCompleted(set.m_isCompleted)
141     , m_isFull(set.m_isFull)
142     , m_payloads(set.m_payloads)
143     , m_pSliceQueue(set.m_pSliceQueue)
144 {
145     for (auto pSlice : m_pSliceQueue)
146     {
147         pSlice->IncrementReference();
148     }
149 }
150 
~SetOfSlices()151 SetOfSlices::~SetOfSlices()
152 {
153     Release();
154 }
155 
operator =(const SetOfSlices & set)156 SetOfSlices& SetOfSlices::operator=(const SetOfSlices& set)
157 {
158     if (this == &set)
159     {
160         return *this;
161     }
162 
163     *this = set;
164     for (auto pSlice : m_pSliceQueue)
165     {
166         pSlice->IncrementReference();
167     }
168 
169     return *this;
170 }
171 
GetSlice(size_t pos) const172 H264Slice * SetOfSlices::GetSlice(size_t pos) const
173 {
174     if (pos >= m_pSliceQueue.size())
175         return nullptr;
176 
177     return m_pSliceQueue[pos];
178 }
179 
GetSliceCount() const180 size_t SetOfSlices::GetSliceCount() const
181 {
182     return m_pSliceQueue.size();
183 }
184 
AddSlice(H264Slice * slice)185 void SetOfSlices::AddSlice(H264Slice * slice)
186 {
187     m_pSliceQueue.push_back(slice);
188 }
189 
Release()190 void SetOfSlices::Release()
191 {
192     size_t count = m_pSliceQueue.size();
193     for (size_t sliceId = 0; sliceId < count; sliceId++)
194     {
195         H264Slice * slice = m_pSliceQueue[sliceId];
196         slice->DecrementReference();
197     }
198 
199     Reset();
200 }
201 
Reset()202 void SetOfSlices::Reset()
203 {
204     m_frame = 0;
205     m_isCompleted = false;
206     m_isFull = false;
207     m_pSliceQueue.clear();
208     m_payloads.Release();
209 }
210 
AddSet(const SetOfSlices * set)211 void SetOfSlices::AddSet(const SetOfSlices *set)
212 {
213     size_t count = set->GetSliceCount();
214     for (size_t sliceId = 0; sliceId < count; sliceId++)
215     {
216         AddSlice(set->GetSlice(sliceId));
217     }
218 }
219 
CleanUseless()220 void SetOfSlices::CleanUseless()
221 {
222     size_t count = m_pSliceQueue.size();
223     for (size_t sliceId = 0; sliceId < count; sliceId++)
224     {
225         H264Slice * curSlice = m_pSliceQueue[sliceId];
226         if (curSlice->m_bDecoded)
227         {
228             m_pSliceQueue.erase(m_pSliceQueue.begin() + sliceId); // remove
229             count = m_pSliceQueue.size();
230             --sliceId;
231             curSlice->Release();
232             curSlice->DecrementReference();
233         }
234     }
235 }
236 
SortSlices()237 void SetOfSlices::SortSlices()
238 {
239     static int32_t MAX_MB_NUMBER = 0x7fffffff;
240 
241     if (!m_pSliceQueue.empty() && m_pSliceQueue[0]->IsSliceGroups())
242         return;
243 
244     size_t count = m_pSliceQueue.size();
245     for (size_t sliceId = 0; sliceId < count; sliceId++)
246     {
247         H264Slice * curSlice = m_pSliceQueue[sliceId];
248         int32_t minFirst = MAX_MB_NUMBER;
249         size_t minSlice = 0;
250 
251         for (size_t j = sliceId; j < count; j++)
252         {
253             H264Slice * slice = m_pSliceQueue[j];
254             if (slice->GetStreamFirstMB() < curSlice->GetStreamFirstMB() && minFirst > slice->GetStreamFirstMB() &&
255                 curSlice->GetSliceHeader()->nal_ext.svc.dependency_id == slice->GetSliceHeader()->nal_ext.svc.dependency_id &&
256                 curSlice->GetSliceHeader()->nal_ext.svc.quality_id == slice->GetSliceHeader()->nal_ext.svc.quality_id)
257             {
258                 minFirst = slice->GetStreamFirstMB();
259                 minSlice = j;
260             }
261         }
262 
263         if (minFirst != MAX_MB_NUMBER)
264         {
265             H264Slice * temp = m_pSliceQueue[sliceId];
266             m_pSliceQueue[sliceId] = m_pSliceQueue[minSlice];
267             m_pSliceQueue[minSlice] = temp;
268         }
269     }
270 
271     for (size_t sliceId = 0; sliceId < count - 1; sliceId++)
272     {
273         H264Slice * slice     = m_pSliceQueue[sliceId];
274         H264Slice * nextSlice = m_pSliceQueue[sliceId + 1];
275 
276         if (nextSlice->IsSliceGroups() || slice->IsSliceGroups())
277             continue;
278 
279         if (nextSlice->GetSliceHeader()->nal_ext.svc.quality_id == slice->GetSliceHeader()->nal_ext.svc.quality_id)
280             slice->SetMaxMB(nextSlice->GetStreamFirstMB());
281 
282         if (slice->GetStreamFirstMB() == slice->GetMaxMB())
283         {
284             count--;
285             for (size_t i = sliceId; i < count; i++)
286             {
287                 m_pSliceQueue[i] = m_pSliceQueue[i + 1];
288             }
289 
290             m_pSliceQueue.resize(count);
291             slice->DecrementReference();
292 
293             sliceId = uint32_t(-1);
294             continue;
295         }
296     }
297 }
298 
299 /****************************************************************************************************/
300 // AccessUnit class routine
301 /****************************************************************************************************/
AccessUnit()302 AccessUnit::AccessUnit()
303     : m_isInitialized(false)
304     , m_isFullAU(false)
305     , m_auCounter(0)
306 {
307 }
308 
~AccessUnit()309 AccessUnit::~AccessUnit()
310 {
311 }
312 
GetAUIndentifier() const313 uint32_t AccessUnit::GetAUIndentifier() const
314 {
315     return m_auCounter;
316 }
317 
GetLayersCount() const318 size_t AccessUnit::GetLayersCount() const
319 {
320     return m_layers.size();
321 }
322 
CleanUseless()323 void AccessUnit::CleanUseless()
324 {
325     size_t count = m_layers.size();
326     for (size_t pos = 0; pos < count; pos++)
327     {
328         SetOfSlices * set = &m_layers[pos];
329         set->CleanUseless();
330         if (!set->GetSliceCount())
331         {
332             m_layers.erase(m_layers.begin() + pos);
333             count = m_layers.size();
334             pos--;
335         }
336     }
337 }
338 
FindLayerByDependency(int32_t dependency)339 int32_t AccessUnit::FindLayerByDependency(int32_t dependency)
340 {
341     size_t count = m_layers.size();
342     for (size_t i = 0; i < count; i++)
343     {
344         SetOfSlices * set = &m_layers[i];
345         if (set->GetSlice(0) && set->GetSlice(0)->GetSliceHeader()->nal_ext.svc.dependency_id == dependency)
346             return (int32_t)i;
347     }
348 
349     return -1;
350 }
351 
GetLastLayer()352 SetOfSlices * AccessUnit::GetLastLayer()
353 {
354     if (m_layers.empty())
355         return nullptr;
356 
357     return &m_layers.back();
358 }
359 
GetLayer(size_t pos)360 SetOfSlices * AccessUnit::GetLayer(size_t pos)
361 {
362     if (pos >= m_layers.size())
363         return nullptr;
364 
365     return &m_layers[pos];
366 }
367 
CombineSets()368 void AccessUnit::CombineSets()
369 {
370     if (m_layers.empty())
371         return;
372 
373     SetOfSlices * setOfSlices = &m_layers[0];
374     size_t count = m_layers.size();
375     for (size_t i = 1; i < count; i++)
376     {
377         SetOfSlices * set = &m_layers[i];
378         setOfSlices->AddSet(set);
379         set->Reset();
380     }
381 
382     m_layers.resize(1);
383 }
384 
IsFullAU() const385 bool AccessUnit::IsFullAU() const
386 {
387     return m_isFullAU;
388 }
389 
CompleteLastLayer()390 void AccessUnit::CompleteLastLayer()
391 {
392     if (!m_layers.empty())
393         m_layers.back().m_isFull = true;
394 }
395 
AddSlice(H264Slice * slice)396 bool AccessUnit::AddSlice(H264Slice * slice)
397 {
398     if (!slice)
399     {
400         if (!m_layers.empty())
401         {
402             m_isFullAU = true;
403         }
404 
405         return false;
406     }
407 
408     SetOfSlices * setOfSlices = GetLayerBySlice(slice);
409     if (!setOfSlices)
410     {
411         if (!m_layers.empty())
412         {
413             SetOfSlices * lastSetOfSlices = GetLastLayer();
414             if (lastSetOfSlices->GetSlice(0)->GetSliceHeader()->nal_ext.svc.dependency_id > slice->GetSliceHeader()->nal_ext.svc.dependency_id)
415             {
416                 m_isFullAU = true;
417                 return false;
418             }
419         }
420 
421         setOfSlices = AddLayer(slice);
422         setOfSlices->m_payloads.MovePayloadsFrom(m_payloads);
423     }
424 
425     H264Slice * lastSlice = setOfSlices->GetSlice(setOfSlices->GetSliceCount() - 1);
426     if (!IsPictureTheSame(lastSlice, slice) || setOfSlices->m_isFull)
427     {
428         m_isFullAU = true;
429         return false;
430     }
431 
432     m_payloads.Release();
433 
434     setOfSlices->AddSlice(slice);
435     return true;
436 }
437 
Release()438 void AccessUnit::Release()
439 {
440     for (auto & set: m_layers)
441     {
442        set.Release();
443     }
444 
445     Reset();
446     m_payloads.Release();
447 }
448 
Reset()449 void AccessUnit::Reset()
450 {
451     for (auto & set: m_layers)
452     {
453        set.Reset();
454     }
455 
456     m_layers.clear();
457     m_auCounter++;
458     m_isFullAU = false;
459     m_isInitialized = false;
460 }
461 
SortforASO()462 void AccessUnit::SortforASO()
463 {
464     for (auto & set: m_layers)
465     {
466        set.SortSlices();
467     }
468 }
469 
AddLayer(H264Slice *)470 SetOfSlices * AccessUnit::AddLayer(H264Slice * )
471 {
472     SetOfSlices setofSlices;
473     m_layers.push_back(setofSlices);
474     return &m_layers.back();
475 }
476 
IsItSliceOfThisAU(H264Slice * slice)477 bool AccessUnit::IsItSliceOfThisAU(H264Slice * slice)
478 {
479     SetOfSlices * setOfSlices = GetLayerBySlice(slice);
480     if (!setOfSlices)
481         return false;
482 
483     H264Slice * lastSlice = setOfSlices->GetSlice(0);
484     return IsPictureTheSame(lastSlice, slice);
485 }
486 
GetLayerBySlice(H264Slice * slice)487 SetOfSlices * AccessUnit::GetLayerBySlice(H264Slice * slice)
488 {
489     if (!slice)
490         return nullptr;
491 
492     size_t count = m_layers.size();
493     for (size_t i = 0; i < count; i++)
494     {
495         H264Slice * temp = m_layers[i].GetSlice(0);
496         if (!temp)
497             continue;
498 
499         if (temp->GetSliceHeader()->nal_ext.mvc.view_id == slice->GetSliceHeader()->nal_ext.mvc.view_id &&
500             temp->GetSliceHeader()->nal_ext.svc.dependency_id == slice->GetSliceHeader()->nal_ext.svc.dependency_id)
501             return &m_layers[i];
502     }
503 
504     return nullptr;
505 }
506 
AU_Splitter(H264_Heap_Objects * objectHeap)507 AU_Splitter::AU_Splitter(H264_Heap_Objects *objectHeap)
508     : m_Headers(objectHeap)
509     , m_objHeap(objectHeap)
510 {
511 }
512 
~AU_Splitter()513 AU_Splitter::~AU_Splitter()
514 {
515     Close();
516 }
517 
Init()518 void AU_Splitter::Init()
519 {
520     Close();
521 
522     m_pNALSplitter.reset(new NALUnitSplitter());
523     m_pNALSplitter->Init();
524 }
525 
Close()526 void AU_Splitter::Close()
527 {
528     m_pNALSplitter.reset(0);
529 }
530 
Reset()531 void AU_Splitter::Reset()
532 {
533     if (m_pNALSplitter.get())
534         m_pNALSplitter->Reset();
535 
536     m_Headers.Reset();
537 }
538 
GetNalUnit(MediaData * src)539 NalUnit * AU_Splitter::GetNalUnit(MediaData * src)
540 {
541     return m_pNALSplitter->GetNalUnits(src);
542 }
543 
GetNalUnitSplitter()544 NALUnitSplitter * AU_Splitter::GetNalUnitSplitter()
545 {
546     return m_pNALSplitter.get();
547 }
548 
549 } // namespace UMC
550 #endif // MFX_ENABLE_H264_VIDEO_DECODE
551