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