Add MediaParser::Flush to flush the parser

Change-Id: Ic12a045dda47ccd270c8c3e9e83768e04a53ad58
This commit is contained in:
Kongqun Yang 2014-04-24 11:37:33 -07:00 committed by KongQun Yang
parent 77e9302aa9
commit 30cb6948e5
7 changed files with 49 additions and 20 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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;
/// @} /// @}

View File

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