2023-12-01 17:32:19 +00:00
|
|
|
// Copyright 2016 Google LLC. All rights reserved.
|
2016-02-05 19:08:07 +00:00
|
|
|
//
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file or at
|
|
|
|
// https://developers.google.com/open-source/licenses/bsd
|
|
|
|
|
2017-12-20 00:56:36 +00:00
|
|
|
#ifndef PACKAGER_MEDIA_CODECS_NALU_READER_H_
|
|
|
|
#define PACKAGER_MEDIA_CODECS_NALU_READER_H_
|
2016-02-05 19:08:07 +00:00
|
|
|
|
2023-12-01 17:32:19 +00:00
|
|
|
#include <cstdint>
|
|
|
|
#include <cstdlib>
|
2016-02-05 19:08:07 +00:00
|
|
|
|
2023-12-01 17:32:19 +00:00
|
|
|
#include <packager/macros/classes.h>
|
|
|
|
#include <packager/media/base/decrypt_config.h>
|
2016-02-05 19:08:07 +00:00
|
|
|
|
2016-05-20 21:19:33 +00:00
|
|
|
namespace shaka {
|
2016-02-05 19:08:07 +00:00
|
|
|
namespace media {
|
|
|
|
|
|
|
|
// Used as the |nalu_length_size| argument to NaluReader to indicate to use
|
|
|
|
// AnnexB byte streams. An AnnexB byte stream starts with 3 or 4 byte start
|
|
|
|
// codes instead of a fixed size NAL unit length.
|
|
|
|
const uint8_t kIsAnnexbByteStream = 0;
|
|
|
|
|
|
|
|
/// For explanations of each struct and its members, see H.264 specification
|
|
|
|
/// at http://www.itu.int/rec/T-REC-H.264.
|
|
|
|
class Nalu {
|
|
|
|
public:
|
|
|
|
enum H264NaluType {
|
|
|
|
H264_Unspecified = 0,
|
|
|
|
H264_NonIDRSlice = 1,
|
|
|
|
H264_IDRSlice = 5,
|
|
|
|
H264_SEIMessage = 6,
|
|
|
|
H264_SPS = 7,
|
|
|
|
H264_PPS = 8,
|
|
|
|
H264_AUD = 9,
|
|
|
|
H264_EOSeq = 10,
|
2016-03-22 00:39:22 +00:00
|
|
|
H264_FillerData = 12,
|
|
|
|
H264_SPSExtension = 13,
|
2016-03-31 19:48:16 +00:00
|
|
|
H264_PrefixNALUnit = 14,
|
2016-03-22 00:39:22 +00:00
|
|
|
H264_SubsetSPS = 15,
|
2016-03-31 19:48:16 +00:00
|
|
|
H264_DepthParameterSet = 16,
|
2016-03-22 00:39:22 +00:00
|
|
|
H264_Reserved17 = 17,
|
|
|
|
H264_Reserved18 = 18,
|
2016-02-05 19:08:07 +00:00
|
|
|
H264_CodedSliceExtension = 20,
|
2016-03-22 00:39:22 +00:00
|
|
|
H264_Reserved22 = 22,
|
2016-02-05 19:08:07 +00:00
|
|
|
};
|
2016-02-26 22:34:14 +00:00
|
|
|
enum H265NaluType {
|
|
|
|
H265_TRAIL_N = 0,
|
2016-05-04 21:19:40 +00:00
|
|
|
H265_TRAIL_R = 1,
|
2016-03-22 00:39:22 +00:00
|
|
|
H265_TSA_N = 2,
|
|
|
|
H265_TSA_R = 3,
|
|
|
|
H265_STSA_N = 4,
|
|
|
|
H265_STSA_R = 5,
|
2016-02-26 22:34:14 +00:00
|
|
|
H265_RASL_R = 9,
|
|
|
|
|
2016-03-22 00:39:22 +00:00
|
|
|
H265_RSV_VCL_N10 = 10,
|
|
|
|
H265_RSV_VCL_R15 = 15,
|
|
|
|
|
2016-02-26 22:34:14 +00:00
|
|
|
H265_BLA_W_LP = 16,
|
|
|
|
H265_IDR_W_RADL = 19,
|
|
|
|
H265_IDR_N_LP = 20,
|
|
|
|
H265_CRA_NUT = 21,
|
2016-03-22 00:39:22 +00:00
|
|
|
|
|
|
|
H265_RSV_IRAP_VCL22 = 22,
|
2016-02-26 22:34:14 +00:00
|
|
|
H265_RSV_IRAP_VCL23 = 23,
|
2016-03-22 00:39:22 +00:00
|
|
|
H265_RSV_VCL31 = 31,
|
2016-02-26 22:34:14 +00:00
|
|
|
|
|
|
|
H265_VPS = 32,
|
|
|
|
H265_SPS = 33,
|
|
|
|
H265_PPS = 34,
|
|
|
|
H265_AUD = 35,
|
2016-03-22 00:39:22 +00:00
|
|
|
|
|
|
|
H265_EOS = 36,
|
|
|
|
H265_EOB = 37,
|
2016-05-04 21:19:40 +00:00
|
|
|
H265_FD = 38,
|
2016-03-22 00:39:22 +00:00
|
|
|
|
2016-03-31 19:48:16 +00:00
|
|
|
H265_PREFIX_SEI = 39,
|
|
|
|
|
2016-03-22 00:39:22 +00:00
|
|
|
H265_RSV_NVCL41 = 41,
|
2016-03-31 19:48:16 +00:00
|
|
|
H265_RSV_NVCL44 = 44,
|
|
|
|
H265_UNSPEC48 = 48,
|
|
|
|
H265_UNSPEC55 = 55,
|
2016-02-26 22:34:14 +00:00
|
|
|
};
|
2016-04-21 20:35:49 +00:00
|
|
|
enum CodecType {
|
|
|
|
kH264,
|
|
|
|
kH265,
|
|
|
|
};
|
2016-02-05 19:08:07 +00:00
|
|
|
|
|
|
|
Nalu();
|
|
|
|
|
2023-12-01 17:32:19 +00:00
|
|
|
[[nodiscard]] bool Initialize(CodecType type,
|
|
|
|
const uint8_t* data,
|
|
|
|
uint64_t size);
|
2016-02-26 22:34:14 +00:00
|
|
|
|
2016-04-27 07:51:51 +00:00
|
|
|
/// This is the pointer to the Nalu data, pointing to the header.
|
2016-02-05 19:08:07 +00:00
|
|
|
const uint8_t* data() const { return data_; }
|
2016-04-27 07:51:51 +00:00
|
|
|
|
|
|
|
/// The size of the header, e.g. 1 for H.264.
|
2016-02-05 19:08:07 +00:00
|
|
|
uint64_t header_size() const { return header_size_; }
|
2016-04-27 07:51:51 +00:00
|
|
|
/// Size of this Nalu minus header_size().
|
2016-02-26 22:49:57 +00:00
|
|
|
uint64_t payload_size() const { return payload_size_; }
|
2016-02-05 19:08:07 +00:00
|
|
|
|
2016-02-26 22:34:14 +00:00
|
|
|
// H.264 Specific:
|
2016-02-05 19:08:07 +00:00
|
|
|
int ref_idc() const { return ref_idc_; }
|
2016-02-26 22:34:14 +00:00
|
|
|
|
|
|
|
// H.265 Specific:
|
|
|
|
int nuh_layer_id() const { return nuh_layer_id_; }
|
|
|
|
int nuh_temporal_id() const { return nuh_temporal_id_; }
|
|
|
|
|
2016-04-27 07:51:51 +00:00
|
|
|
/// H264NaluType and H265NaluType enums may be used to compare against the
|
|
|
|
/// return value.
|
2016-02-05 19:08:07 +00:00
|
|
|
int type() const { return type_; }
|
2016-08-25 22:44:25 +00:00
|
|
|
bool is_aud() const { return is_aud_; }
|
2017-03-01 02:10:28 +00:00
|
|
|
bool is_vcl() const { return is_vcl_; }
|
|
|
|
/// Slice data partition NALs are not considered as slice NALs.
|
2016-02-05 19:08:07 +00:00
|
|
|
bool is_video_slice() const { return is_video_slice_; }
|
2016-03-31 19:48:16 +00:00
|
|
|
bool can_start_access_unit() const { return can_start_access_unit_; }
|
2016-02-05 19:08:07 +00:00
|
|
|
|
|
|
|
private:
|
2016-04-21 20:35:49 +00:00
|
|
|
bool InitializeFromH264(const uint8_t* data, uint64_t size);
|
|
|
|
bool InitializeFromH265(const uint8_t* data, uint64_t size);
|
|
|
|
|
2016-02-05 19:08:07 +00:00
|
|
|
// A pointer to the NALU (i.e. points to the header). This pointer is not
|
|
|
|
// owned by this instance.
|
2016-08-25 22:44:25 +00:00
|
|
|
const uint8_t* data_ = nullptr;
|
2016-02-26 22:49:57 +00:00
|
|
|
// NALU header size (e.g. 1 byte for H.264). Note that it does not include
|
|
|
|
// header extension data in some NAL units.
|
2016-08-25 22:44:25 +00:00
|
|
|
uint64_t header_size_ = 0;
|
2016-02-26 22:49:57 +00:00
|
|
|
// Size of data after the header.
|
2016-08-25 22:44:25 +00:00
|
|
|
uint64_t payload_size_ = 0;
|
|
|
|
|
|
|
|
int ref_idc_ = 0;
|
|
|
|
int nuh_layer_id_ = 0;
|
|
|
|
int nuh_temporal_id_ = 0;
|
|
|
|
int type_ = 0;
|
|
|
|
bool is_aud_ = false;
|
2017-03-01 02:10:28 +00:00
|
|
|
bool is_vcl_ = false;
|
2016-08-25 22:44:25 +00:00
|
|
|
bool is_video_slice_ = false;
|
|
|
|
bool can_start_access_unit_ = false;
|
2016-02-05 19:08:07 +00:00
|
|
|
|
2016-02-26 22:34:14 +00:00
|
|
|
// Don't use DISALLOW_COPY_AND_ASSIGN since it is just numbers and a pointer
|
|
|
|
// it does not own. This allows Nalus to be stored in a vector.
|
2016-02-05 19:08:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// Helper class used to read NAL units based on several formats:
|
|
|
|
/// * Annex B H.264/h.265
|
|
|
|
/// * NAL Unit Stream
|
|
|
|
class NaluReader {
|
|
|
|
public:
|
|
|
|
enum Result {
|
|
|
|
kOk,
|
|
|
|
kInvalidStream, // error in stream
|
|
|
|
kEOStream, // end of stream
|
|
|
|
};
|
|
|
|
|
|
|
|
/// @param nalu_length_size should be set to 0 for AnnexB byte streams;
|
|
|
|
/// otherwise, it indicates the size of NAL unit length for the NAL
|
|
|
|
/// unit stream.
|
2016-04-21 20:35:49 +00:00
|
|
|
NaluReader(Nalu::CodecType type,
|
2016-02-26 22:34:14 +00:00
|
|
|
uint8_t nal_length_size,
|
2016-02-05 19:08:07 +00:00
|
|
|
const uint8_t* stream,
|
|
|
|
uint64_t stream_size);
|
2017-05-19 22:21:02 +00:00
|
|
|
|
|
|
|
/// @param type is the codec type of the NALU unit.
|
|
|
|
/// @param nalu_length_size should be set to 0 for AnnexB byte streams;
|
|
|
|
/// otherwise, it indicates the size of NAL unit length for the NAL
|
|
|
|
/// unit stream.
|
|
|
|
/// @param stream is the input stream.
|
|
|
|
/// @param stream_size is the size of @a stream.
|
|
|
|
/// @param subsamples specifies the clear and encrypted sections of the
|
|
|
|
/// @a stream starting from the beginning of the @a stream. If
|
|
|
|
/// @a subsamples doesn't cover the entire stream, then the rest is
|
|
|
|
/// assumed to be in the clear.
|
|
|
|
NaluReader(Nalu::CodecType type,
|
|
|
|
uint8_t nal_length_size,
|
|
|
|
const uint8_t* stream,
|
|
|
|
uint64_t stream_size,
|
|
|
|
const std::vector<SubsampleEntry>& subsamples);
|
2016-02-05 19:08:07 +00:00
|
|
|
~NaluReader();
|
|
|
|
|
|
|
|
// Find offset from start of data to next NALU start code
|
|
|
|
// and size of found start code (3 or 4 bytes).
|
|
|
|
// If no start code is found, offset is pointing to the first unprocessed byte
|
|
|
|
// (i.e. the first byte that was not considered as a possible start of a start
|
|
|
|
// code) and |*start_code_size| is set to 0.
|
|
|
|
// Postconditions:
|
|
|
|
// - |*offset| is between 0 and |data_size| included.
|
|
|
|
// It is strictly less than |data_size| if |data_size| > 0.
|
|
|
|
// - |*start_code_size| is either 0, 3 or 4.
|
|
|
|
static bool FindStartCode(const uint8_t* data,
|
|
|
|
uint64_t data_size,
|
|
|
|
uint64_t* offset,
|
|
|
|
uint8_t* start_code_size);
|
|
|
|
|
2017-05-19 22:21:02 +00:00
|
|
|
/// Same as FindStartCode() but also specify the subsamples. This searches for
|
|
|
|
/// start codes in the clear section and will not scan for start codes in the
|
|
|
|
/// encrypted section. Even if there is a real NALU start code in the
|
|
|
|
/// encrypted section, this will skip them.
|
|
|
|
/// @param subsamples starting from the start of @a data. If @a subsamples
|
|
|
|
/// does not cover the whole @a data, the rest is assumed to be in the
|
|
|
|
/// clear.
|
|
|
|
/// @return true if it finds a NALU. false otherwise.
|
|
|
|
static bool FindStartCodeInClearRange(
|
|
|
|
const uint8_t* data,
|
|
|
|
uint64_t data_size,
|
|
|
|
uint64_t* offset,
|
|
|
|
uint8_t* start_code_size,
|
|
|
|
const std::vector<SubsampleEntry>& subsamples);
|
|
|
|
|
2016-02-05 19:08:07 +00:00
|
|
|
/// Reads a NALU from the stream into |*nalu|, if one exists, and then
|
|
|
|
/// advances to the next NALU.
|
|
|
|
/// @param nalu contains the NALU read if it exists.
|
|
|
|
/// @return kOk if a NALU is read; kEOStream if the stream is at the
|
|
|
|
/// end-of-stream; kInvalidStream on error.
|
|
|
|
Result Advance(Nalu* nalu);
|
|
|
|
|
2016-02-22 19:11:29 +00:00
|
|
|
/// @returns true if the current position points to a start code.
|
|
|
|
bool StartsWithStartCode();
|
|
|
|
|
2016-02-05 19:08:07 +00:00
|
|
|
private:
|
|
|
|
enum Format {
|
|
|
|
kAnnexbByteStreamFormat,
|
|
|
|
kNalUnitStreamFormat
|
|
|
|
};
|
|
|
|
|
|
|
|
// Move the stream pointer to the beginning of the next NALU,
|
|
|
|
// i.e. pointing at the next start code.
|
|
|
|
// Return true if a NALU has been found.
|
|
|
|
// If a NALU is found:
|
|
|
|
// - its size in bytes is returned in |*nalu_size| and includes
|
|
|
|
// the start code as well as the trailing zero bits.
|
|
|
|
// - the size in bytes of the start code is returned in |*start_code_size|.
|
|
|
|
bool LocateNaluByStartCode(uint64_t* nalu_size, uint8_t* start_code_size);
|
|
|
|
|
|
|
|
// Pointer to the current NALU in the stream.
|
|
|
|
const uint8_t* stream_;
|
|
|
|
// The remaining size of the stream.
|
|
|
|
uint64_t stream_size_;
|
2016-02-26 22:34:14 +00:00
|
|
|
// The type of NALU being read.
|
2016-04-21 20:35:49 +00:00
|
|
|
Nalu::CodecType nalu_type_;
|
2016-02-05 19:08:07 +00:00
|
|
|
// The number of bytes the prefix length is; only valid if format is
|
|
|
|
// kAnnexbByteStreamFormat.
|
|
|
|
uint8_t nalu_length_size_;
|
|
|
|
// The format of the stream.
|
|
|
|
Format format_;
|
|
|
|
|
2017-05-19 22:21:02 +00:00
|
|
|
// subsamples left in stream_.
|
|
|
|
std::vector<SubsampleEntry> subsamples_;
|
|
|
|
|
2016-02-05 19:08:07 +00:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(NaluReader);
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace media
|
2016-05-20 21:19:33 +00:00
|
|
|
} // namespace shaka
|
2016-02-05 19:08:07 +00:00
|
|
|
|
2017-12-20 00:56:36 +00:00
|
|
|
#endif // PACKAGER_MEDIA_CODECS_NALU_READER_H_
|