author | Benjamin Chen <bechen@mozilla.com> |
Wed, 23 Apr 2014 12:04:27 +0800 | |
changeset 179692 | 80dba24cc92979858f88cffdccde906a3b6d8308 |
parent 179691 | 0930742ce5c6e9c2ee97ef7e8037cbd7c7c853c0 |
child 179693 | 368a6f1f7eea8b7a99a2f89b32649aec499291ac |
push id | 42588 |
push user | cbook@mozilla.com |
push date | Wed, 23 Apr 2014 07:10:05 +0000 |
treeherder | mozilla-inbound@80dba24cc929 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | rillian |
bugs | 994557 |
milestone | 31.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
content/media/webm/EbmlComposer.cpp | file | annotate | diff | comparison | revisions | |
content/media/webm/EbmlComposer.h | file | annotate | diff | comparison | revisions |
--- a/content/media/webm/EbmlComposer.cpp +++ b/content/media/webm/EbmlComposer.cpp @@ -55,63 +55,83 @@ void EbmlComposer::GenerateHeader() Ebml_EndSubElement(&ebml, &trackLoc); } } // The Recording length is unknown and // ignore write the whole Segment element size } MOZ_ASSERT(ebml.offset <= DEFAULT_HEADER_SIZE + mCodecPrivateData.Length(), "write more data > EBML_BUFFER_SIZE"); - mClusterBuffs.AppendElement(); - mClusterBuffs.LastElement().SetLength(ebml.offset); - memcpy(mClusterBuffs.LastElement().Elements(), ebml.buf, ebml.offset); + auto block = mClusterBuffs.AppendElement(); + block->SetLength(ebml.offset); + memcpy(block->Elements(), ebml.buf, ebml.offset); + mFlushState |= FLUSH_METADATA; +} + +void EbmlComposer::FinishMetadata() +{ + if (mFlushState & FLUSH_METADATA) { + // We don't remove the first element of mClusterBuffs because the + // |mClusterHeaderIndex| may have value. + mClusterCanFlushBuffs.AppendElement()->SwapElements(mClusterBuffs[0]); + mFlushState &= ~FLUSH_METADATA; + } } void EbmlComposer::FinishCluster() { - MOZ_ASSERT(mClusterLengthLoc > 0 ); - MOZ_ASSERT(mClusterHeaderIndex > 0); - for (uint32_t i = 0; i < mClusterBuffs.Length(); i++) { - mClusterCanFlushBuffs.AppendElement()->SwapElements(mClusterBuffs[i]); + FinishMetadata(); + if (!(mFlushState & FLUSH_CLUSTER)) { + // No completed cluster available. + return; } - mClusterBuffs.Clear(); + + MOZ_ASSERT(mClusterLengthLoc > 0); EbmlGlobal ebml; EbmlLoc ebmlLoc; ebmlLoc.offset = mClusterLengthLoc; - ebml.offset = mClusterCanFlushBuffs[mClusterHeaderIndex].Length(); - ebml.buf = mClusterCanFlushBuffs[mClusterHeaderIndex].Elements(); + ebml.offset = mClusterBuffs[mClusterHeaderIndex].Length(); + ebml.buf = mClusterBuffs[mClusterHeaderIndex].Elements(); Ebml_EndSubElement(&ebml, &ebmlLoc); + // Move the mClusterBuffs data from mClusterHeaderIndex that we can skip + // the metadata and the rest P-frames after ContainerWriter::FLUSH_NEEDED. + for (uint32_t i = mClusterHeaderIndex; i < mClusterBuffs.Length(); i++) { + mClusterCanFlushBuffs.AppendElement()->SwapElements(mClusterBuffs[i]); + } + mClusterHeaderIndex = 0; mClusterLengthLoc = 0; + mClusterBuffs.Clear(); + mFlushState &= ~FLUSH_CLUSTER; } void EbmlComposer::WriteSimpleBlock(EncodedFrame* aFrame) { EbmlGlobal ebml; ebml.offset = 0; - if (aFrame->GetFrameType() == EncodedFrame::FrameType::VP8_I_FRAME && mClusterHeaderIndex > 0) { + if (aFrame->GetFrameType() == EncodedFrame::FrameType::VP8_I_FRAME) { FinishCluster(); } - mClusterBuffs.AppendElement(); - mClusterBuffs.LastElement().SetLength(aFrame->GetFrameData().Length() + DEFAULT_HEADER_SIZE); - ebml.buf = mClusterBuffs.LastElement().Elements(); + auto block = mClusterBuffs.AppendElement(); + block->SetLength(aFrame->GetFrameData().Length() + DEFAULT_HEADER_SIZE); + ebml.buf = block->Elements(); if (aFrame->GetFrameType() == EncodedFrame::FrameType::VP8_I_FRAME) { EbmlLoc ebmlLoc; Ebml_StartSubElement(&ebml, &ebmlLoc, Cluster); + MOZ_ASSERT(mClusterBuffs.Length() > 0); // current cluster header array index mClusterHeaderIndex = mClusterBuffs.Length() - 1; mClusterLengthLoc = ebmlLoc.offset; - if (aFrame->GetFrameType() != EncodedFrame::FrameType::VORBIS_AUDIO_FRAME) { - mClusterTimecode = aFrame->GetTimeStamp() / PR_USEC_PER_MSEC; - } + mClusterTimecode = aFrame->GetTimeStamp() / PR_USEC_PER_MSEC; Ebml_SerializeUnsigned(&ebml, Timecode, mClusterTimecode); + mFlushState |= FLUSH_CLUSTER; } if (aFrame->GetFrameType() != EncodedFrame::FrameType::VORBIS_AUDIO_FRAME) { short timeCode = aFrame->GetTimeStamp() / PR_USEC_PER_MSEC - mClusterTimecode; writeSimpleBlock(&ebml, 0x1, timeCode, aFrame->GetFrameType() == EncodedFrame::FrameType::VP8_I_FRAME, 0, 0, (unsigned char*)aFrame->GetFrameData().Elements(), @@ -119,17 +139,17 @@ EbmlComposer::WriteSimpleBlock(EncodedFr } else { writeSimpleBlock(&ebml, 0x2, 0, false, 0, 0, (unsigned char*)aFrame->GetFrameData().Elements(), aFrame->GetFrameData().Length()); } MOZ_ASSERT(ebml.offset <= DEFAULT_HEADER_SIZE + aFrame->GetFrameData().Length(), "write more data > EBML_BUFFER_SIZE"); - mClusterBuffs.LastElement().SetLength(ebml.offset); + block->SetLength(ebml.offset); } void EbmlComposer::SetVideoConfig(uint32_t aWidth, uint32_t aHeight, uint32_t aDisplayWidth, uint32_t aDisplayHeight, float aFrameRate) { MOZ_ASSERT(aWidth > 0, "Width should > 0"); @@ -155,28 +175,35 @@ EbmlComposer::SetAudioConfig(uint32_t aS mBitDepth = aBitDepth; mChannels = aChannels; } void EbmlComposer::ExtractBuffer(nsTArray<nsTArray<uint8_t> >* aDestBufs, uint32_t aFlag) { - if ((aFlag & ContainerWriter::FLUSH_NEEDED) && mClusterHeaderIndex > 0) { + if ((aFlag & ContainerWriter::FLUSH_NEEDED) || + (aFlag & ContainerWriter::GET_HEADER)) + { + FinishMetadata(); + } + if (aFlag & ContainerWriter::FLUSH_NEEDED) + { FinishCluster(); } // aDestBufs may have some element for (uint32_t i = 0; i < mClusterCanFlushBuffs.Length(); i++) { aDestBufs->AppendElement()->SwapElements(mClusterCanFlushBuffs[i]); } mClusterCanFlushBuffs.Clear(); } EbmlComposer::EbmlComposer() - : mClusterHeaderIndex(0) + : mFlushState(FLUSH_NONE) + , mClusterHeaderIndex(0) , mClusterLengthLoc(0) , mClusterTimecode(0) , mWidth(0) , mHeight(0) , mFrameRate(0) , mSampleFreq(0) , mBitDepth(0) , mChannels(0)
--- a/content/media/webm/EbmlComposer.h +++ b/content/media/webm/EbmlComposer.h @@ -41,23 +41,33 @@ public: */ void WriteSimpleBlock(EncodedFrame* aFrame); /* * Get valid cluster data. */ void ExtractBuffer(nsTArray<nsTArray<uint8_t> >* aDestBufs, uint32_t aFlag = 0); private: + // Move the metadata data to mClusterCanFlushBuffs. + void FinishMetadata(); // Close current cluster and move data to mClusterCanFlushBuffs. void FinishCluster(); // The temporary storage for cluster data. nsTArray<nsTArray<uint8_t> > mClusterBuffs; // The storage which contain valid cluster data. nsTArray<nsTArray<uint8_t> > mClusterCanFlushBuffs; - // Indicate the header index in mClusterBuffs. + + // Indicate the data types in mClusterBuffs. + enum { + FLUSH_NONE = 0, + FLUSH_METADATA = 1 << 0, + FLUSH_CLUSTER = 1 << 1 + }; + uint32_t mFlushState; + // Indicate the cluster header index in mClusterBuffs. uint32_t mClusterHeaderIndex; // The cluster length position. uint64_t mClusterLengthLoc; // Audio codec specific header data. nsTArray<uint8_t> mCodecPrivateData; // The timecode of the cluster. uint64_t mClusterTimecode;