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:
kthelgason
2016-10-26 02:48:16 -07:00
committed by Commit bot
parent 12ba1867a2
commit b906172e02
11 changed files with 13 additions and 13 deletions

View File

@ -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",

View File

@ -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"

View File

@ -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)

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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',