Reland of Move bitstream parser to more appropriate directory. (patchset #1 id:1 of https://codereview.webrtc.org/2430353004/ )
Reason for revert: Internal project has been fixed Original issue's description: > Revert of Move bitstream parser to more appropriate directory. (patchset #4 id:60001 of https://codereview.webrtc.org/2370853005/ ) > > Reason for revert: > Breaks internal project > > Original issue's description: > > Move current bitstream parser to more appropriate directory. > > > > This CL groups together the code that has to do with parsing H264 bitstreams. > > This code logically belongs together, and having it in the same directory not > > only simplifies things from a project structure perspective, but also makes it > > easier to refactor out common parts incrementally. > > An added benefit is that this simplifies modular compilation, where for example > > one would like a build of WebRTC without the H264 codec-specific parts. > > > > BUG=webrtc:6338 > > > > Committed: https://crrev.com/cc6817e9ce4a5ffc73efb660cf0368afbc7d9a4f > > Cr-Commit-Position: refs/heads/master@{#14684} > > TBR=magjed@webrtc.org,stefan@webrtc.org > # Skipping CQ checks because original CL landed less than 1 days ago. > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=webrtc:6338 > > Committed: https://crrev.com/f04f14e772f803de39f8a6128e5157127cd35103 > Cr-Commit-Position: refs/heads/master@{#14685} TBR=magjed@webrtc.org,stefan@webrtc.org # Skipping CQ checks because original CL landed less than 1 days ago. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=webrtc:6338 Review-Url: https://codereview.webrtc.org/2434043002 Cr-Commit-Position: refs/heads/master@{#14783}
This commit is contained in:
@ -98,8 +98,6 @@ rtc_static_library("video_coding_utility") {
|
||||
sources = [
|
||||
"utility/frame_dropper.cc",
|
||||
"utility/frame_dropper.h",
|
||||
"utility/h264_bitstream_parser.cc",
|
||||
"utility/h264_bitstream_parser.h",
|
||||
"utility/ivf_file_writer.cc",
|
||||
"utility/ivf_file_writer.h",
|
||||
"utility/moving_average.cc",
|
||||
|
||||
@ -15,8 +15,8 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/common_video/h264/h264_bitstream_parser.h"
|
||||
#include "webrtc/modules/video_coding/codecs/h264/include/h264.h"
|
||||
#include "webrtc/modules/video_coding/utility/h264_bitstream_parser.h"
|
||||
#include "webrtc/modules/video_coding/utility/quality_scaler.h"
|
||||
|
||||
#include "third_party/openh264/src/codec/api/svc/codec_app_def.h"
|
||||
|
||||
@ -13,10 +13,10 @@
|
||||
#define WEBRTC_MODULES_VIDEO_CODING_CODECS_H264_H264_VIDEO_TOOLBOX_ENCODER_H_
|
||||
|
||||
#include "webrtc/base/criticalsection.h"
|
||||
#include "webrtc/common_video/h264/h264_bitstream_parser.h"
|
||||
#include "webrtc/common_video/include/bitrate_adjuster.h"
|
||||
#include "webrtc/common_video/rotation.h"
|
||||
#include "webrtc/modules/video_coding/codecs/h264/include/h264.h"
|
||||
#include "webrtc/modules/video_coding/utility/h264_bitstream_parser.h"
|
||||
#include "webrtc/modules/video_coding/utility/quality_scaler.h"
|
||||
|
||||
#if defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED)
|
||||
|
||||
@ -1,293 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 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 "webrtc/modules/video_coding/utility/h264_bitstream_parser.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/base/bitbuffer.h"
|
||||
#include "webrtc/base/bytebuffer.h"
|
||||
#include "webrtc/base/checks.h"
|
||||
|
||||
#include "webrtc/common_video/h264/h264_common.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
#define RETURN_FALSE_ON_FAIL(x) \
|
||||
if (!(x)) { \
|
||||
LOG_F(LS_ERROR) << "FAILED: " #x; \
|
||||
return false; \
|
||||
}
|
||||
|
||||
H264BitstreamParser::H264BitstreamParser() {}
|
||||
H264BitstreamParser::~H264BitstreamParser() {}
|
||||
|
||||
bool H264BitstreamParser::ParseNonParameterSetNalu(const uint8_t* source,
|
||||
size_t source_length,
|
||||
uint8_t nalu_type) {
|
||||
RTC_CHECK(sps_);
|
||||
RTC_CHECK(pps_);
|
||||
last_slice_qp_delta_ = rtc::Optional<int32_t>();
|
||||
std::unique_ptr<rtc::Buffer> slice_rbsp(
|
||||
H264::ParseRbsp(source, source_length));
|
||||
rtc::BitBuffer slice_reader(slice_rbsp->data() + H264::kNaluTypeSize,
|
||||
slice_rbsp->size() - H264::kNaluTypeSize);
|
||||
// Check to see if this is an IDR slice, which has an extra field to parse
|
||||
// out.
|
||||
bool is_idr = (source[0] & 0x0F) == H264::NaluType::kIdr;
|
||||
uint8_t nal_ref_idc = (source[0] & 0x60) >> 5;
|
||||
uint32_t golomb_tmp;
|
||||
uint32_t bits_tmp;
|
||||
|
||||
// first_mb_in_slice: ue(v)
|
||||
RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
|
||||
// slice_type: ue(v)
|
||||
uint32_t slice_type;
|
||||
RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&slice_type));
|
||||
// slice_type's 5..9 range is used to indicate that all slices of a picture
|
||||
// have the same value of slice_type % 5, we don't care about that, so we map
|
||||
// to the corresponding 0..4 range.
|
||||
slice_type %= 5;
|
||||
// pic_parameter_set_id: ue(v)
|
||||
RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
|
||||
if (sps_->separate_colour_plane_flag == 1) {
|
||||
// colour_plane_id
|
||||
RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(&bits_tmp, 2));
|
||||
}
|
||||
// frame_num: u(v)
|
||||
// Represented by log2_max_frame_num_minus4 + 4 bits.
|
||||
RETURN_FALSE_ON_FAIL(
|
||||
slice_reader.ReadBits(&bits_tmp, sps_->log2_max_frame_num_minus4 + 4));
|
||||
uint32_t field_pic_flag = 0;
|
||||
if (sps_->frame_mbs_only_flag == 0) {
|
||||
// field_pic_flag: u(1)
|
||||
RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(&field_pic_flag, 1));
|
||||
if (field_pic_flag != 0) {
|
||||
// bottom_field_flag: u(1)
|
||||
RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(&bits_tmp, 1));
|
||||
}
|
||||
}
|
||||
if (is_idr) {
|
||||
// idr_pic_id: ue(v)
|
||||
RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
|
||||
}
|
||||
// pic_order_cnt_lsb: u(v)
|
||||
// Represented by sps_.log2_max_pic_order_cnt_lsb_minus4 + 4 bits.
|
||||
if (sps_->pic_order_cnt_type == 0) {
|
||||
RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(
|
||||
&bits_tmp, sps_->log2_max_pic_order_cnt_lsb_minus4 + 4));
|
||||
if (pps_->bottom_field_pic_order_in_frame_present_flag &&
|
||||
field_pic_flag == 0) {
|
||||
// delta_pic_order_cnt_bottom: se(v)
|
||||
RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
|
||||
}
|
||||
}
|
||||
if (sps_->pic_order_cnt_type == 1 &&
|
||||
!sps_->delta_pic_order_always_zero_flag) {
|
||||
// delta_pic_order_cnt[0]: se(v)
|
||||
RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
|
||||
if (pps_->bottom_field_pic_order_in_frame_present_flag && !field_pic_flag) {
|
||||
// delta_pic_order_cnt[1]: se(v)
|
||||
RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
|
||||
}
|
||||
}
|
||||
if (pps_->redundant_pic_cnt_present_flag) {
|
||||
// redundant_pic_cnt: ue(v)
|
||||
RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
|
||||
}
|
||||
if (slice_type == H264::SliceType::kB) {
|
||||
// direct_spatial_mv_pred_flag: u(1)
|
||||
RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(&bits_tmp, 1));
|
||||
}
|
||||
switch (slice_type) {
|
||||
case H264::SliceType::kP:
|
||||
case H264::SliceType::kB:
|
||||
case H264::SliceType::kSp:
|
||||
uint32_t num_ref_idx_active_override_flag;
|
||||
// num_ref_idx_active_override_flag: u(1)
|
||||
RETURN_FALSE_ON_FAIL(
|
||||
slice_reader.ReadBits(&num_ref_idx_active_override_flag, 1));
|
||||
if (num_ref_idx_active_override_flag != 0) {
|
||||
// num_ref_idx_l0_active_minus1: ue(v)
|
||||
RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
|
||||
if (slice_type == H264::SliceType::kB) {
|
||||
// num_ref_idx_l1_active_minus1: ue(v)
|
||||
RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// assume nal_unit_type != 20 && nal_unit_type != 21:
|
||||
RTC_CHECK_NE(nalu_type, 20);
|
||||
RTC_CHECK_NE(nalu_type, 21);
|
||||
// if (nal_unit_type == 20 || nal_unit_type == 21)
|
||||
// ref_pic_list_mvc_modification()
|
||||
// else
|
||||
{
|
||||
// ref_pic_list_modification():
|
||||
// |slice_type| checks here don't use named constants as they aren't named
|
||||
// in the spec for this segment. Keeping them consistent makes it easier to
|
||||
// verify that they are both the same.
|
||||
if (slice_type % 5 != 2 && slice_type % 5 != 4) {
|
||||
// ref_pic_list_modification_flag_l0: u(1)
|
||||
uint32_t ref_pic_list_modification_flag_l0;
|
||||
RETURN_FALSE_ON_FAIL(
|
||||
slice_reader.ReadBits(&ref_pic_list_modification_flag_l0, 1));
|
||||
if (ref_pic_list_modification_flag_l0) {
|
||||
uint32_t modification_of_pic_nums_idc;
|
||||
do {
|
||||
// modification_of_pic_nums_idc: ue(v)
|
||||
RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(
|
||||
&modification_of_pic_nums_idc));
|
||||
if (modification_of_pic_nums_idc == 0 ||
|
||||
modification_of_pic_nums_idc == 1) {
|
||||
// abs_diff_pic_num_minus1: ue(v)
|
||||
RETURN_FALSE_ON_FAIL(
|
||||
slice_reader.ReadExponentialGolomb(&golomb_tmp));
|
||||
} else if (modification_of_pic_nums_idc == 2) {
|
||||
// long_term_pic_num: ue(v)
|
||||
RETURN_FALSE_ON_FAIL(
|
||||
slice_reader.ReadExponentialGolomb(&golomb_tmp));
|
||||
}
|
||||
} while (modification_of_pic_nums_idc != 3);
|
||||
}
|
||||
}
|
||||
if (slice_type % 5 == 1) {
|
||||
// ref_pic_list_modification_flag_l1: u(1)
|
||||
uint32_t ref_pic_list_modification_flag_l1;
|
||||
RETURN_FALSE_ON_FAIL(
|
||||
slice_reader.ReadBits(&ref_pic_list_modification_flag_l1, 1));
|
||||
if (ref_pic_list_modification_flag_l1) {
|
||||
uint32_t modification_of_pic_nums_idc;
|
||||
do {
|
||||
// modification_of_pic_nums_idc: ue(v)
|
||||
RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(
|
||||
&modification_of_pic_nums_idc));
|
||||
if (modification_of_pic_nums_idc == 0 ||
|
||||
modification_of_pic_nums_idc == 1) {
|
||||
// abs_diff_pic_num_minus1: ue(v)
|
||||
RETURN_FALSE_ON_FAIL(
|
||||
slice_reader.ReadExponentialGolomb(&golomb_tmp));
|
||||
} else if (modification_of_pic_nums_idc == 2) {
|
||||
// long_term_pic_num: ue(v)
|
||||
RETURN_FALSE_ON_FAIL(
|
||||
slice_reader.ReadExponentialGolomb(&golomb_tmp));
|
||||
}
|
||||
} while (modification_of_pic_nums_idc != 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO(pbos): Do we need support for pred_weight_table()?
|
||||
RTC_CHECK(
|
||||
!((pps_->weighted_pred_flag && (slice_type == H264::SliceType::kP ||
|
||||
slice_type == H264::SliceType::kSp)) ||
|
||||
(pps_->weighted_bipred_idc != 0 && slice_type == H264::SliceType::kB)))
|
||||
<< "Missing support for pred_weight_table().";
|
||||
// if ((weighted_pred_flag && (slice_type == P || slice_type == SP)) ||
|
||||
// (weighted_bipred_idc == 1 && slice_type == B)) {
|
||||
// pred_weight_table()
|
||||
// }
|
||||
if (nal_ref_idc != 0) {
|
||||
// dec_ref_pic_marking():
|
||||
if (is_idr) {
|
||||
// no_output_of_prior_pics_flag: u(1)
|
||||
// long_term_reference_flag: u(1)
|
||||
RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(&bits_tmp, 2));
|
||||
} else {
|
||||
// adaptive_ref_pic_marking_mode_flag: u(1)
|
||||
uint32_t adaptive_ref_pic_marking_mode_flag;
|
||||
RETURN_FALSE_ON_FAIL(
|
||||
slice_reader.ReadBits(&adaptive_ref_pic_marking_mode_flag, 1));
|
||||
if (adaptive_ref_pic_marking_mode_flag) {
|
||||
uint32_t memory_management_control_operation;
|
||||
do {
|
||||
// memory_management_control_operation: ue(v)
|
||||
RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(
|
||||
&memory_management_control_operation));
|
||||
if (memory_management_control_operation == 1 ||
|
||||
memory_management_control_operation == 3) {
|
||||
// difference_of_pic_nums_minus1: ue(v)
|
||||
RETURN_FALSE_ON_FAIL(
|
||||
slice_reader.ReadExponentialGolomb(&golomb_tmp));
|
||||
}
|
||||
if (memory_management_control_operation == 2) {
|
||||
// long_term_pic_num: ue(v)
|
||||
RETURN_FALSE_ON_FAIL(
|
||||
slice_reader.ReadExponentialGolomb(&golomb_tmp));
|
||||
}
|
||||
if (memory_management_control_operation == 3 ||
|
||||
memory_management_control_operation == 6) {
|
||||
// long_term_frame_idx: ue(v)
|
||||
RETURN_FALSE_ON_FAIL(
|
||||
slice_reader.ReadExponentialGolomb(&golomb_tmp));
|
||||
}
|
||||
if (memory_management_control_operation == 4) {
|
||||
// max_long_term_frame_idx_plus1: ue(v)
|
||||
RETURN_FALSE_ON_FAIL(
|
||||
slice_reader.ReadExponentialGolomb(&golomb_tmp));
|
||||
}
|
||||
} while (memory_management_control_operation != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
// cabac not supported: entropy_coding_mode_flag == 0 asserted above.
|
||||
// if (entropy_coding_mode_flag && slice_type != I && slice_type != SI)
|
||||
// cabac_init_idc
|
||||
int32_t last_slice_qp_delta;
|
||||
RETURN_FALSE_ON_FAIL(
|
||||
slice_reader.ReadSignedExponentialGolomb(&last_slice_qp_delta));
|
||||
last_slice_qp_delta_ = rtc::Optional<int32_t>(last_slice_qp_delta);
|
||||
return true;
|
||||
}
|
||||
|
||||
void H264BitstreamParser::ParseSlice(const uint8_t* slice, size_t length) {
|
||||
H264::NaluType nalu_type = H264::ParseNaluType(slice[0]);
|
||||
switch (nalu_type) {
|
||||
case H264::NaluType::kSps: {
|
||||
sps_ = SpsParser::ParseSps(slice + H264::kNaluTypeSize,
|
||||
length - H264::kNaluTypeSize);
|
||||
if (!sps_)
|
||||
FATAL() << "Unable to parse SPS from H264 bitstream.";
|
||||
break;
|
||||
}
|
||||
case H264::NaluType::kPps: {
|
||||
pps_ = PpsParser::ParsePps(slice + H264::kNaluTypeSize,
|
||||
length - H264::kNaluTypeSize);
|
||||
if (!pps_)
|
||||
FATAL() << "Unable to parse PPS from H264 bitstream.";
|
||||
break;
|
||||
}
|
||||
default:
|
||||
RTC_CHECK(ParseNonParameterSetNalu(slice, length, nalu_type))
|
||||
<< "Failed to parse picture slice.";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void H264BitstreamParser::ParseBitstream(const uint8_t* bitstream,
|
||||
size_t length) {
|
||||
std::vector<H264::NaluIndex> nalu_indices =
|
||||
H264::FindNaluIndices(bitstream, length);
|
||||
RTC_CHECK(!nalu_indices.empty());
|
||||
for (const H264::NaluIndex& index : nalu_indices)
|
||||
ParseSlice(&bitstream[index.payload_start_offset], index.payload_size);
|
||||
}
|
||||
|
||||
bool H264BitstreamParser::GetLastSliceQp(int* qp) const {
|
||||
if (!last_slice_qp_delta_ || !pps_)
|
||||
return false;
|
||||
*qp = 26 + pps_->pic_init_qp_minus26 + *last_slice_qp_delta_;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 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 WEBRTC_MODULES_VIDEO_CODING_UTILITY_H264_BITSTREAM_PARSER_H_
|
||||
#define WEBRTC_MODULES_VIDEO_CODING_UTILITY_H264_BITSTREAM_PARSER_H_
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "webrtc/base/optional.h"
|
||||
#include "webrtc/common_video/h264/pps_parser.h"
|
||||
#include "webrtc/common_video/h264/sps_parser.h"
|
||||
|
||||
namespace rtc {
|
||||
class BitBufferWriter;
|
||||
}
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Stateful H264 bitstream parser (due to SPS/PPS). Used to parse out QP values
|
||||
// from the bitstream.
|
||||
// TODO(pbos): Unify with RTP SPS parsing and only use one H264 parser.
|
||||
// TODO(pbos): If/when this gets used on the receiver side CHECKs must be
|
||||
// removed and gracefully abort as we have no control over receive-side
|
||||
// bitstreams.
|
||||
class H264BitstreamParser {
|
||||
public:
|
||||
H264BitstreamParser();
|
||||
virtual ~H264BitstreamParser();
|
||||
|
||||
// Parse an additional chunk of H264 bitstream.
|
||||
void ParseBitstream(const uint8_t* bitstream, size_t length);
|
||||
|
||||
// Get the last extracted QP value from the parsed bitstream.
|
||||
bool GetLastSliceQp(int* qp) const;
|
||||
|
||||
protected:
|
||||
void ParseSlice(const uint8_t* slice, size_t length);
|
||||
bool ParseNonParameterSetNalu(const uint8_t* source,
|
||||
size_t source_length,
|
||||
uint8_t nalu_type);
|
||||
|
||||
// SPS/PPS state, updated when parsing new SPS/PPS, used to parse slices.
|
||||
rtc::Optional<SpsParser::SpsState> sps_;
|
||||
rtc::Optional<PpsParser::PpsState> pps_;
|
||||
|
||||
// Last parsed slice QP.
|
||||
rtc::Optional<int32_t> last_slice_qp_delta_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_VIDEO_CODING_UTILITY_H264_BITSTREAM_PARSER_H_
|
||||
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 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 "webrtc/modules/video_coding/utility/h264_bitstream_parser.h"
|
||||
|
||||
#include "webrtc/test/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// SPS/PPS part of below chunk.
|
||||
uint8_t kH264SpsPps[] = {0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x80, 0x20, 0xda,
|
||||
0x01, 0x40, 0x16, 0xe8, 0x06, 0xd0, 0xa1, 0x35, 0x00,
|
||||
0x00, 0x00, 0x01, 0x68, 0xce, 0x06, 0xe2};
|
||||
|
||||
// Contains enough of the image slice to contain slice QP.
|
||||
uint8_t kH264BitstreamChunk[] = {
|
||||
0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x80, 0x20, 0xda, 0x01, 0x40, 0x16,
|
||||
0xe8, 0x06, 0xd0, 0xa1, 0x35, 0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x06,
|
||||
0xe2, 0x00, 0x00, 0x00, 0x01, 0x65, 0xb8, 0x40, 0xf0, 0x8c, 0x03, 0xf2,
|
||||
0x75, 0x67, 0xad, 0x41, 0x64, 0x24, 0x0e, 0xa0, 0xb2, 0x12, 0x1e, 0xf8,
|
||||
};
|
||||
|
||||
// Contains enough of the image slice to contain slice QP.
|
||||
uint8_t kH264BitstreamNextImageSliceChunk[] = {
|
||||
0x00, 0x00, 0x00, 0x01, 0x41, 0xe2, 0x01, 0x16, 0x0e, 0x3e, 0x2b, 0x86,
|
||||
};
|
||||
|
||||
TEST(H264BitstreamParserTest, ReportsNoQpWithoutParsedSlices) {
|
||||
H264BitstreamParser h264_parser;
|
||||
int qp;
|
||||
EXPECT_FALSE(h264_parser.GetLastSliceQp(&qp));
|
||||
}
|
||||
|
||||
TEST(H264BitstreamParserTest, ReportsNoQpWithOnlyParsedPpsAndSpsSlices) {
|
||||
H264BitstreamParser h264_parser;
|
||||
h264_parser.ParseBitstream(kH264SpsPps, sizeof(kH264SpsPps));
|
||||
int qp;
|
||||
EXPECT_FALSE(h264_parser.GetLastSliceQp(&qp));
|
||||
}
|
||||
|
||||
TEST(H264BitstreamParserTest, ReportsLastSliceQpForImageSlices) {
|
||||
H264BitstreamParser h264_parser;
|
||||
h264_parser.ParseBitstream(kH264BitstreamChunk, sizeof(kH264BitstreamChunk));
|
||||
int qp;
|
||||
ASSERT_TRUE(h264_parser.GetLastSliceQp(&qp));
|
||||
EXPECT_EQ(35, qp);
|
||||
|
||||
// Parse an additional image slice.
|
||||
h264_parser.ParseBitstream(kH264BitstreamNextImageSliceChunk,
|
||||
sizeof(kH264BitstreamNextImageSliceChunk));
|
||||
ASSERT_TRUE(h264_parser.GetLastSliceQp(&qp));
|
||||
EXPECT_EQ(37, qp);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
@ -21,8 +21,6 @@
|
||||
'sources': [
|
||||
'frame_dropper.cc',
|
||||
'frame_dropper.h',
|
||||
'h264_bitstream_parser.cc',
|
||||
'h264_bitstream_parser.h',
|
||||
'ivf_file_writer.cc',
|
||||
'ivf_file_writer.h',
|
||||
'moving_average.cc',
|
||||
|
||||
Reference in New Issue
Block a user