Changed es_parser_h264 to wait for initial I-frame to start emitting samples.
Change-Id: I7b9ca4a73a8765501a1c29e467e877e1eee5f9d9
This commit is contained in:
parent
f609b2947c
commit
fc85154bca
|
@ -39,7 +39,8 @@ EsParserH264::EsParserH264(
|
||||||
next_access_unit_pos_(0),
|
next_access_unit_pos_(0),
|
||||||
stream_converter_(new H264ByteToUnitStreamConverter),
|
stream_converter_(new H264ByteToUnitStreamConverter),
|
||||||
decoder_config_check_pending_(false),
|
decoder_config_check_pending_(false),
|
||||||
pending_sample_duration_(0) {
|
pending_sample_duration_(0),
|
||||||
|
waiting_for_key_frame_(true) {
|
||||||
}
|
}
|
||||||
|
|
||||||
EsParserH264::~EsParserH264() {
|
EsParserH264::~EsParserH264() {
|
||||||
|
@ -102,6 +103,7 @@ void EsParserH264::Reset() {
|
||||||
decoder_config_check_pending_ = false;
|
decoder_config_check_pending_ = false;
|
||||||
pending_sample_ = scoped_refptr<MediaSample>();
|
pending_sample_ = scoped_refptr<MediaSample>();
|
||||||
pending_sample_duration_ = 0;
|
pending_sample_duration_ = 0;
|
||||||
|
waiting_for_key_frame_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EsParserH264::FindAUD(int64* stream_pos) {
|
bool EsParserH264::FindAUD(int64* stream_pos) {
|
||||||
|
@ -233,9 +235,14 @@ bool EsParserH264::ParseInternal() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (waiting_for_key_frame_) {
|
||||||
|
waiting_for_key_frame_ = !is_key_frame;
|
||||||
|
}
|
||||||
|
if (!waiting_for_key_frame_) {
|
||||||
// Emit a frame and move the stream to the next AUD position.
|
// Emit a frame and move the stream to the next AUD position.
|
||||||
RCHECK(EmitFrame(current_access_unit_pos_, access_unit_size,
|
RCHECK(EmitFrame(current_access_unit_pos_, access_unit_size,
|
||||||
is_key_frame, pps_id_for_access_unit));
|
is_key_frame, pps_id_for_access_unit));
|
||||||
|
}
|
||||||
current_access_unit_pos_ = next_access_unit_pos_;
|
current_access_unit_pos_ = next_access_unit_pos_;
|
||||||
es_queue_->Trim(current_access_unit_pos_);
|
es_queue_->Trim(current_access_unit_pos_);
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,9 @@ class EsParserH264 : public EsParser {
|
||||||
// Frame for which we do not yet have a duration.
|
// Frame for which we do not yet have a duration.
|
||||||
scoped_refptr<MediaSample> pending_sample_;
|
scoped_refptr<MediaSample> pending_sample_;
|
||||||
uint64 pending_sample_duration_;
|
uint64 pending_sample_duration_;
|
||||||
|
|
||||||
|
// Indicates whether waiting for first key frame.
|
||||||
|
bool waiting_for_key_frame_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mp2t
|
} // namespace mp2t
|
||||||
|
|
|
@ -117,20 +117,24 @@ void AppendAUD(
|
||||||
|
|
||||||
class EsParserH264Test : public testing::Test {
|
class EsParserH264Test : public testing::Test {
|
||||||
public:
|
public:
|
||||||
EsParserH264Test() : sample_count_(0) {
|
EsParserH264Test()
|
||||||
}
|
: sample_count_(0),
|
||||||
|
first_frame_is_key_frame_(false) {}
|
||||||
|
|
||||||
void LoadStream(const char* filename);
|
void LoadStream(const char* filename);
|
||||||
void ProcessPesPackets(const std::vector<Packet>& pes_packets);
|
void ProcessPesPackets(const std::vector<Packet>& pes_packets);
|
||||||
|
|
||||||
void EmitSample(uint32 pid, scoped_refptr<MediaSample>& sample) {
|
void EmitSample(uint32 pid, scoped_refptr<MediaSample>& sample) {
|
||||||
sample_count_++;
|
sample_count_++;
|
||||||
|
if (sample_count_ == 1)
|
||||||
|
first_frame_is_key_frame_ = sample->is_key_frame();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewVideoConfig(scoped_refptr<StreamInfo>& config) {
|
void NewVideoConfig(scoped_refptr<StreamInfo>& config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t sample_count() const { return sample_count_; }
|
size_t sample_count() const { return sample_count_; }
|
||||||
|
bool first_frame_is_key_frame() { return first_frame_is_key_frame_; }
|
||||||
|
|
||||||
// Stream with AUD NALUs.
|
// Stream with AUD NALUs.
|
||||||
std::vector<uint8> stream_;
|
std::vector<uint8> stream_;
|
||||||
|
@ -140,6 +144,7 @@ class EsParserH264Test : public testing::Test {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
size_t sample_count_;
|
size_t sample_count_;
|
||||||
|
bool first_frame_is_key_frame_;
|
||||||
};
|
};
|
||||||
|
|
||||||
void EsParserH264Test::LoadStream(const char* filename) {
|
void EsParserH264Test::LoadStream(const char* filename) {
|
||||||
|
@ -204,7 +209,8 @@ TEST_F(EsParserH264Test, OneAccessUnitPerPes) {
|
||||||
|
|
||||||
// Process each PES packet.
|
// Process each PES packet.
|
||||||
ProcessPesPackets(pes_packets);
|
ProcessPesPackets(pes_packets);
|
||||||
ASSERT_EQ(sample_count(), access_units_.size());
|
EXPECT_EQ(sample_count(), access_units_.size());
|
||||||
|
EXPECT_TRUE(first_frame_is_key_frame());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(EsParserH264Test, NonAlignedPesPacket) {
|
TEST_F(EsParserH264Test, NonAlignedPesPacket) {
|
||||||
|
@ -228,7 +234,8 @@ TEST_F(EsParserH264Test, NonAlignedPesPacket) {
|
||||||
|
|
||||||
// Process each PES packet.
|
// Process each PES packet.
|
||||||
ProcessPesPackets(pes_packets);
|
ProcessPesPackets(pes_packets);
|
||||||
ASSERT_EQ(sample_count(), access_units_.size());
|
EXPECT_EQ(sample_count(), access_units_.size());
|
||||||
|
EXPECT_TRUE(first_frame_is_key_frame());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(EsParserH264Test, SeveralPesPerAccessUnit) {
|
TEST_F(EsParserH264Test, SeveralPesPerAccessUnit) {
|
||||||
|
@ -258,7 +265,21 @@ TEST_F(EsParserH264Test, SeveralPesPerAccessUnit) {
|
||||||
|
|
||||||
// Process each PES packet.
|
// Process each PES packet.
|
||||||
ProcessPesPackets(pes_packets);
|
ProcessPesPackets(pes_packets);
|
||||||
ASSERT_EQ(sample_count(), access_units_.size());
|
EXPECT_EQ(sample_count(), access_units_.size());
|
||||||
|
EXPECT_TRUE(first_frame_is_key_frame());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(EsParserH264Test, NonIFrameStart) {
|
||||||
|
LoadStream("bear_no_iframe_start.h264");
|
||||||
|
|
||||||
|
// One to one equivalence between PES packets and access units.
|
||||||
|
std::vector<Packet> pes_packets(access_units_);
|
||||||
|
|
||||||
|
// Process each PES packet.
|
||||||
|
ProcessPesPackets(pes_packets);
|
||||||
|
// Ensure samples were emitted, but fewer than number of AUDs.
|
||||||
|
EXPECT_LT(sample_count(), access_units_.size());
|
||||||
|
EXPECT_TRUE(first_frame_is_key_frame());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mp2t
|
} // namespace mp2t
|
||||||
|
|
|
@ -75,5 +75,8 @@ bear.h264:
|
||||||
ffmpeg -i bear.mp4 -vcodec copy -vbsf h264_mp4toannexb \
|
ffmpeg -i bear.mp4 -vcodec copy -vbsf h264_mp4toannexb \
|
||||||
-an bear.h264
|
-an bear.h264
|
||||||
|
|
||||||
|
bear_no_i_frame_start.h264
|
||||||
|
Derived from bear.h264. Consists of 29-non-I-frames, followed by a single I-frame, and 29 non-I-frames.
|
||||||
|
|
||||||
avc-byte-stream-frame.h264 - Single IDR frame extracted from test-25fps.h264 in Annex B byte stream format.
|
avc-byte-stream-frame.h264 - Single IDR frame extracted from test-25fps.h264 in Annex B byte stream format.
|
||||||
avc-unit-stream-frame.h264 - Single IDR frame from avc-byte-stream-frame.h264 converted to unit stream format.
|
avc-unit-stream-frame.h264 - Single IDR frame from avc-byte-stream-frame.h264 converted to unit stream format.
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue