Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add h264 prefix NAL parser impl for enabling frame-marking #58

Merged
merged 1 commit into from
Jan 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions common_video/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ rtc_static_library("common_video") {
"h264/h264_common.h",
"h264/pps_parser.cc",
"h264/pps_parser.h",
"h264/prefix_parser.cc",
"h264/prefix_parser.h",
"h264/profile_level_id.h",
"h264/sps_parser.cc",
"h264/sps_parser.h",
Expand Down
1 change: 1 addition & 0 deletions common_video/h264/h264_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ enum NaluType : uint8_t {
kEndOfSequence = 10,
kEndOfStream = 11,
kFiller = 12,
kPrefix = 14,
kStapA = 24,
kFuA = 28
};
Expand Down
85 changes: 85 additions & 0 deletions common_video/h264/prefix_parser.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/

#include "common_video/h264/prefix_parser.h"

#include <cstdint>
#include <vector>

#include "common_video/h264/h264_common.h"
#include "rtc_base/bit_buffer.h"

namespace {
typedef absl::optional<webrtc::PrefixParser::PrefixState> OptionalPrefix;

#define RETURN_EMPTY_ON_FAIL(x) \
if (!(x)) { \
return OptionalPrefix(); \
}
} // namespace

namespace webrtc {

PrefixParser::PrefixState::PrefixState() = default;
PrefixParser::PrefixState::PrefixState(const PrefixState&) = default;
PrefixParser::PrefixState::~PrefixState() = default;

// General note: this is based off the 02/2016 version of the H.264 standard.
// You can find it on this page:
// http://www.itu.int/rec/T-REC-H.264

// Unpack RBSP and parse SVC extension state from the supplied buffer.
absl::optional<PrefixParser::PrefixState> PrefixParser::ParsePrefix(
const uint8_t* data,
size_t length) {
std::vector<uint8_t> unpacked_buffer = H264::ParseRbsp(data, length);
rtc::BitBuffer bit_buffer(unpacked_buffer.data(), unpacked_buffer.size());
return ParsePrefixUpToSvcExtension(&bit_buffer);
}

absl::optional<PrefixParser::PrefixState> PrefixParser::ParsePrefixUpToSvcExtension(
rtc::BitBuffer* buffer) {
// Now, we need to use a bit buffer to parse through the actual SVC extension
// format. See Section 7.3.1 ("NAL unit syntax") and 7.3.1.1 ("NAL unit header
// SVC extension syntax") of the H.264 standard for a complete description.

PrefixState svc_extension;

uint32_t svc_extension_flag = 0;
// Make sure the svc_extension_flag is on.
RETURN_EMPTY_ON_FAIL(buffer->ReadBits(&svc_extension_flag, 1));
if (!svc_extension_flag)
return OptionalPrefix();

// idr_flag: u(1)
RETURN_EMPTY_ON_FAIL(buffer->ReadBits(&svc_extension.idr_flag, 1));
// priority_id: u(6)
RETURN_EMPTY_ON_FAIL(buffer->ReadBits(&svc_extension.priority_id, 6));
// no_inter_layer_pred_flag: u(1)
RETURN_EMPTY_ON_FAIL(
buffer->ReadBits(&svc_extension.no_inter_layer_pred_flag, 1));
// dependency_id: u(3)
RETURN_EMPTY_ON_FAIL(buffer->ReadBits(&svc_extension.dependency_id, 3));
// quality_id: u(4)
RETURN_EMPTY_ON_FAIL(buffer->ReadBits(&svc_extension.quality_id, 4));
// temporal_id: u(3)
RETURN_EMPTY_ON_FAIL(buffer->ReadBits(&svc_extension.temporal_id, 3));
// use_ref_base_pic_flag: u(1)
RETURN_EMPTY_ON_FAIL(
buffer->ReadBits(&svc_extension.use_ref_base_pic_flag, 1));
// discardable_flag: u(1)
RETURN_EMPTY_ON_FAIL(buffer->ReadBits(&svc_extension.discardable_flag, 1));
// output_flag: u(1)
RETURN_EMPTY_ON_FAIL(buffer->ReadBits(&svc_extension.output_flag, 1));

return OptionalPrefix(svc_extension);
}

} // namespace webrtc
53 changes: 53 additions & 0 deletions common_video/h264/prefix_parser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/

#ifndef COMMON_VIDEO_H264_PREFIX_PARSER_H_
#define COMMON_VIDEO_H264_PREFIX_PARSER_H_

#include "absl/types/optional.h"

namespace rtc {
class BitBuffer;
}

namespace webrtc {

// A class for parsing out SVC extension data from an H264 prefix NALU
class PrefixParser {
public:
// The parsed state of the SVC extension. Only some select values are stored.
// Add more as they are actually needed.
struct PrefixState {
PrefixState();
PrefixState(const PrefixState&);
~PrefixState();

uint32_t idr_flag = 0;
uint32_t priority_id = 0;
uint32_t no_inter_layer_pred_flag = 1;
uint32_t dependency_id = 0;
uint32_t quality_id = 0;
uint32_t temporal_id = 0;
uint32_t use_ref_base_pic_flag = 0;
uint32_t discardable_flag = 1;
uint32_t output_flag = 1;
};

// Unpack RBSP and parse prefix state from the supplied buffer.
static absl::optional<PrefixState> ParsePrefix(const uint8_t* data, size_t length);

protected:
// Parse the prefix NAL, up till the SVC extension part, for a bit buffer where RBSP
// decoding has already been performed.
static absl::optional<PrefixState> ParsePrefixUpToSvcExtension(rtc::BitBuffer* buffer);
};

} // namespace webrtc
#endif // COMMON_VIDEO_H264_PREFIX_PARSER_H_