Shaka Packager SDK
Loading...
Searching...
No Matches
h26x_byte_to_unit_stream_converter.cc
1// Copyright 2016 Google LLC. All rights reserved.
2//
3// Use of this source code is governed by a BSD-style
4// license that can be found in the LICENSE file or at
5// https://developers.google.com/open-source/licenses/bsd
6
7#include <packager/media/codecs/h26x_byte_to_unit_stream_converter.h>
8
9#include <cstddef>
10#include <cstdint>
11#include <cstring>
12#include <limits>
13#include <vector>
14
15#include <absl/flags/flag.h>
16#include <absl/log/check.h>
17#include <absl/log/log.h>
18#include <absl/strings/escaping.h>
19
20#include <packager/media/base/buffer_writer.h>
21#include <packager/media/base/video_stream_info.h>
22#include <packager/media/codecs/nalu_reader.h>
23#include <packager/utils/bytes_to_string_view.h>
24
25// TODO(kqyang): Move byte to unit stream convertion to muxer and make it a
26// muxer option.
27ABSL_FLAG(bool,
28 strip_parameter_set_nalus,
29 true,
30 "When converting from NAL byte stream (AnnexB stream) to NAL unit "
31 "stream, this flag determines whether to strip parameter sets NAL "
32 "units, i.e. SPS/PPS for H264 and SPS/PPS/VPS for H265, from the "
33 "frames. Note that avc1/hvc1 is generated if this flag is enabled; "
34 "otherwise avc3/hev1 is generated.");
35
36namespace shaka {
37namespace media {
38
39namespace {
40// Additional space to reserve for output frame. This value ought to be enough
41// to acommodate frames consisting of 100 NAL units with 3-byte start codes.
42const size_t kStreamConversionOverhead = 100;
43} // namespace
44
46 Nalu::CodecType type)
47 : type_(type),
48 stream_format_(
49 absl::GetFlag(FLAGS_strip_parameter_set_nalus)
50 ? H26xStreamFormat::kNalUnitStreamWithoutParameterSetNalus
51 : H26xStreamFormat::kNalUnitStreamWithParameterSetNalus) {}
52
54 Nalu::CodecType type,
55 H26xStreamFormat stream_format)
56 : type_(type), stream_format_(stream_format) {}
57
58H26xByteToUnitStreamConverter::~H26xByteToUnitStreamConverter() {}
59
61 const uint8_t* input_frame,
62 size_t input_frame_size,
63 std::vector<uint8_t>* output_frame) {
64 DCHECK(input_frame);
65 DCHECK(output_frame);
66
67 BufferWriter output_buffer(input_frame_size + kStreamConversionOverhead);
68
69 Nalu nalu;
70 NaluReader reader(type_, kIsAnnexbByteStream, input_frame, input_frame_size);
71 if (!reader.StartsWithStartCode()) {
72 LOG(ERROR) << "H.26x byte stream frame did not begin with start code.";
73 return false;
74 }
75
76 while (reader.Advance(&nalu) == NaluReader::kOk) {
77 const uint64_t nalu_size = nalu.payload_size() + nalu.header_size();
78 DCHECK_LE(nalu_size, std::numeric_limits<uint32_t>::max());
79
80 if (ProcessNalu(nalu))
81 continue;
82
83 // Append 4-byte length and NAL unit data to the buffer.
84 output_buffer.AppendInt(static_cast<uint32_t>(nalu_size));
85 output_buffer.AppendArray(nalu.data(), nalu_size);
86 }
87
88 output_buffer.SwapBuffer(output_frame);
89 return true;
90}
91
92void H26xByteToUnitStreamConverter::WarnIfNotMatch(
93 int nalu_type,
94 const uint8_t* nalu_ptr,
95 size_t nalu_size,
96 const std::vector<uint8_t>& vector) {
97 if (vector.empty())
98 return;
99 if (vector.size() != nalu_size ||
100 memcmp(vector.data(), nalu_ptr, nalu_size) != 0) {
101 LOG(WARNING) << "Seeing varying NAL unit of type " << nalu_type
102 << ". You may need to set --strip_parameter_set_nalus=false "
103 "during packaging to generate a playable stream.";
104 VLOG(1) << "Old: "
105 << absl::BytesToHexString(byte_vector_to_string_view(vector));
106 VLOG(1) << "New: "
107 << absl::BytesToHexString(
108 byte_array_to_string_view(nalu_ptr, nalu_size));
109 }
110}
111
112} // namespace media
113} // namespace shaka
bool ConvertByteStreamToNalUnitStream(const uint8_t *input_frame, size_t input_frame_size, std::vector< uint8_t > *output_frame)
Result Advance(Nalu *nalu)
uint64_t header_size() const
The size of the header, e.g. 1 for H.264.
const uint8_t * data() const
This is the pointer to the Nalu data, pointing to the header.
Definition nalu_reader.h:97
uint64_t payload_size() const
Size of this Nalu minus header_size().
All the methods that are virtual are virtual for mocking.
std::string_view byte_vector_to_string_view(const std::vector< uint8_t > &bytes)
Convert byte vector to string_view.
std::string_view byte_array_to_string_view(const uint8_t *bytes, size_t bytes_size)
Convert byte array to string_view.