Add MediaParser::Flush to flush the parser
Change-Id: Ic12a045dda47ccd270c8c3e9e83768e04a53ad58
This commit is contained in:
parent
77e9302aa9
commit
30cb6948e5
|
@ -146,9 +146,11 @@ Status Demuxer::Parse() {
|
||||||
|
|
||||||
int64 bytes_read = media_file_->Read(buffer_.get(), kBufSize);
|
int64 bytes_read = media_file_->Read(buffer_.get(), kBufSize);
|
||||||
if (bytes_read <= 0) {
|
if (bytes_read <= 0) {
|
||||||
return media_file_->Eof()
|
if (media_file_->Eof()) {
|
||||||
? Status(error::END_OF_STREAM, "End of stream.")
|
parser_->Flush();
|
||||||
: Status(error::FILE_FAILURE, "Cannot read file " + file_name_);
|
return Status(error::END_OF_STREAM, "");
|
||||||
|
}
|
||||||
|
return Status(error::FILE_FAILURE, "Cannot read file " + file_name_);
|
||||||
}
|
}
|
||||||
|
|
||||||
return parser_->Parse(buffer_.get(), bytes_read)
|
return parser_->Parse(buffer_.get(), bytes_read)
|
||||||
|
|
|
@ -55,6 +55,10 @@ class MediaParser {
|
||||||
const NewSampleCB& new_sample_cb,
|
const NewSampleCB& new_sample_cb,
|
||||||
const NeedKeyCB& need_key_cb) = 0;
|
const NeedKeyCB& need_key_cb) = 0;
|
||||||
|
|
||||||
|
/// Flush data currently in the parser and put the parser in a state where it
|
||||||
|
/// can receive data for a new seek point.
|
||||||
|
virtual void Flush() = 0;
|
||||||
|
|
||||||
/// Should be called when there is new data to parse.
|
/// Should be called when there is new data to parse.
|
||||||
/// @return true if successful.
|
/// @return true if successful.
|
||||||
virtual bool Parse(const uint8* buf, int size) = 0;
|
virtual bool Parse(const uint8* buf, int size) = 0;
|
||||||
|
|
|
@ -129,12 +129,12 @@ class MediaSample : public base::RefCountedThreadSafe<MediaSample> {
|
||||||
/// @return a human-readable string describing |*this|.
|
/// @return a human-readable string describing |*this|.
|
||||||
std::string ToString() const;
|
std::string ToString() const;
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
friend class base::RefCountedThreadSafe<MediaSample>;
|
friend class base::RefCountedThreadSafe<MediaSample>;
|
||||||
|
|
||||||
/// Create a MediaSample. Buffer will be padded and aligned as necessary.
|
// Create a MediaSample. Buffer will be padded and aligned as necessary.
|
||||||
/// @param data,side_data can be NULL, which indicates an empty sample.
|
// |data|,|side_data| can be NULL, which indicates an empty sample.
|
||||||
/// @param size,side_data_size should not be negative.
|
// |size|,|side_data_size| should not be negative.
|
||||||
MediaSample(const uint8* data,
|
MediaSample(const uint8* data,
|
||||||
size_t size,
|
size_t size,
|
||||||
const uint8* side_data,
|
const uint8* side_data,
|
||||||
|
@ -142,7 +142,6 @@ class MediaSample : public base::RefCountedThreadSafe<MediaSample> {
|
||||||
bool is_key_frame);
|
bool is_key_frame);
|
||||||
virtual ~MediaSample();
|
virtual ~MediaSample();
|
||||||
|
|
||||||
private:
|
|
||||||
// Decoding time stamp.
|
// Decoding time stamp.
|
||||||
int64 dts_;
|
int64 dts_;
|
||||||
// Presentation time stamp.
|
// Presentation time stamp.
|
||||||
|
|
|
@ -24,9 +24,6 @@ namespace {
|
||||||
// 3 bytes for the start code + 1 byte for the NALU type.
|
// 3 bytes for the start code + 1 byte for the NALU type.
|
||||||
const int kMinAUDSize = 4;
|
const int kMinAUDSize = 4;
|
||||||
|
|
||||||
// Size of H.264 NALU length output by this SDK.
|
|
||||||
const uint8 kCommonNaluLengthSize = 4;
|
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
EsParserH264::EsParserH264(
|
EsParserH264::EsParserH264(
|
||||||
|
|
|
@ -55,6 +55,12 @@ void MP4MediaParser::Reset() {
|
||||||
mdat_tail_ = 0;
|
mdat_tail_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MP4MediaParser::Flush() {
|
||||||
|
DCHECK_NE(state_, kWaitingForInit);
|
||||||
|
Reset();
|
||||||
|
ChangeState(kParsingBoxes);
|
||||||
|
}
|
||||||
|
|
||||||
bool MP4MediaParser::Parse(const uint8* buf, int size) {
|
bool MP4MediaParser::Parse(const uint8* buf, int size) {
|
||||||
DCHECK_NE(state_, kWaitingForInit);
|
DCHECK_NE(state_, kWaitingForInit);
|
||||||
|
|
||||||
|
@ -295,9 +301,11 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) {
|
||||||
|
|
||||||
bool MP4MediaParser::ParseMoof(BoxReader* reader) {
|
bool MP4MediaParser::ParseMoof(BoxReader* reader) {
|
||||||
// Must already have initialization segment.
|
// Must already have initialization segment.
|
||||||
RCHECK(moov_.get() && runs_.get());
|
RCHECK(moov_.get());
|
||||||
MovieFragment moof;
|
MovieFragment moof;
|
||||||
RCHECK(moof.Parse(reader));
|
RCHECK(moof.Parse(reader));
|
||||||
|
if (!runs_)
|
||||||
|
runs_.reset(new TrackRunIterator(moov_.get()));
|
||||||
RCHECK(runs_->Init(moof));
|
RCHECK(runs_->Init(moof));
|
||||||
EmitNeedKeyIfNecessary(moof.pssh);
|
EmitNeedKeyIfNecessary(moof.pssh);
|
||||||
ChangeState(kEmittingSamples);
|
ChangeState(kEmittingSamples);
|
||||||
|
|
|
@ -35,6 +35,7 @@ class MP4MediaParser : public MediaParser {
|
||||||
virtual void Init(const InitCB& init_cb,
|
virtual void Init(const InitCB& init_cb,
|
||||||
const NewSampleCB& new_sample_cb,
|
const NewSampleCB& new_sample_cb,
|
||||||
const NeedKeyCB& need_key_cb) OVERRIDE;
|
const NeedKeyCB& need_key_cb) OVERRIDE;
|
||||||
|
virtual void Flush() OVERRIDE;
|
||||||
virtual bool Parse(const uint8* buf, int size) OVERRIDE;
|
virtual bool Parse(const uint8* buf, int size) OVERRIDE;
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
|
@ -96,23 +96,41 @@ TEST_F(MP4MediaParserTest, MultiFragmentAppend) {
|
||||||
ParseMP4File("bear-1280x720-av_frag.mp4", 768432);
|
ParseMP4File("bear-1280x720-av_frag.mp4", 768432);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(MP4MediaParserTest, Flush) {
|
||||||
|
// Flush while reading sample data, then start a new stream.
|
||||||
|
InitializeParser();
|
||||||
|
|
||||||
|
std::vector<uint8> buffer = ReadTestDataFile("bear-1280x720-av_frag.mp4");
|
||||||
|
EXPECT_TRUE(AppendDataInPieces(buffer.data(), 65536, 512));
|
||||||
|
parser_->Flush();
|
||||||
|
EXPECT_TRUE(AppendDataInPieces(buffer.data(), buffer.size(), 512));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(MP4MediaParserTest, Reinitialization) {
|
TEST_F(MP4MediaParserTest, Reinitialization) {
|
||||||
InitializeParser();
|
InitializeParser();
|
||||||
|
|
||||||
std::vector<uint8> buffer =
|
std::vector<uint8> buffer = ReadTestDataFile("bear-1280x720-av_frag.mp4");
|
||||||
ReadTestDataFile("bear-1280x720-av_frag.mp4");
|
EXPECT_TRUE(AppendDataInPieces(buffer.data(), buffer.size(), 512));
|
||||||
EXPECT_TRUE(AppendDataInPieces(buffer.data(),
|
EXPECT_TRUE(AppendDataInPieces(buffer.data(), buffer.size(), 512));
|
||||||
buffer.size(),
|
|
||||||
512));
|
|
||||||
EXPECT_TRUE(AppendDataInPieces(buffer.data(),
|
|
||||||
buffer.size(),
|
|
||||||
512));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MP4MediaParserTest, MPEG2_AAC_LC) {
|
TEST_F(MP4MediaParserTest, MPEG2_AAC_LC) {
|
||||||
ParseMP4File("bear-mpeg2-aac-only_frag.mp4", 512);
|
ParseMP4File("bear-mpeg2-aac-only_frag.mp4", 512);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that a moov box is not always required after Flush() is called.
|
||||||
|
TEST_F(MP4MediaParserTest, NoMoovAfterFlush) {
|
||||||
|
InitializeParser();
|
||||||
|
|
||||||
|
std::vector<uint8> buffer = ReadTestDataFile("bear-1280x720-av_frag.mp4");
|
||||||
|
EXPECT_TRUE(AppendDataInPieces(buffer.data(), buffer.size(), 512));
|
||||||
|
parser_->Flush();
|
||||||
|
|
||||||
|
const int kFirstMoofOffset = 1307;
|
||||||
|
EXPECT_TRUE(AppendDataInPieces(
|
||||||
|
buffer.data() + kFirstMoofOffset, buffer.size() - kFirstMoofOffset, 512));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(MP4MediaParserTest, NON_FRAGMENTED_MP4) {
|
TEST_F(MP4MediaParserTest, NON_FRAGMENTED_MP4) {
|
||||||
ParseMP4File("bear-1280x720.mp4", 512);
|
ParseMP4File("bear-1280x720.mp4", 512);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue