Bug 970774 - Add display width/height for track encoder. r=rillian

This commit is contained in:
Benjamin Chen 2014-02-21 14:27:41 +08:00
parent 3b5a19f7a3
commit ae286efd04
14 changed files with 123 additions and 9 deletions

View File

@ -26,11 +26,14 @@ namespace mozilla {
#define GET_ENCODED_VIDEO_FRAME_TIMEOUT 100000 // microseconds
nsresult
OmxVideoTrackEncoder::Init(int aWidth, int aHeight, TrackRate aTrackRate)
OmxVideoTrackEncoder::Init(int aWidth, int aHeight, int aDisplayWidth,
int aDisplayHeight, TrackRate aTrackRate)
{
mFrameWidth = aWidth;
mFrameHeight = aHeight;
mTrackRate = aTrackRate;
mDisplayWidth = aDisplayWidth;
mDisplayHeight = aDisplayHeight;
mEncoder = OMXCodecWrapper::CreateAVCEncoder();
NS_ENSURE_TRUE(mEncoder, NS_ERROR_FAILURE);

View File

@ -35,7 +35,9 @@ public:
nsresult GetEncodedTrack(EncodedFrameContainer& aData) MOZ_OVERRIDE;
protected:
nsresult Init(int aWidth, int aHeight, TrackRate aTrackRate) MOZ_OVERRIDE;
nsresult Init(int aWidth, int aHeight,
int aDisplayWidth, int aDisplayHeight,
TrackRate aTrackRate) MOZ_OVERRIDE;
private:
nsAutoPtr<android::OMXVideoEncoder> mEncoder;

View File

@ -163,7 +163,10 @@ VideoTrackEncoder::NotifyQueuedTrackChanges(MediaStreamGraph* aGraph,
VideoChunk chunk = *iter;
if (!chunk.IsNull()) {
gfx::IntSize imgsize = chunk.mFrame.GetImage()->GetSize();
nsresult rv = Init(imgsize.width, imgsize.height, aTrackRate);
gfxIntSize intrinsicSize = chunk.mFrame.GetIntrinsicSize();
nsresult rv = Init(imgsize.width, imgsize.height,
intrinsicSize.width, intrinsicSize.height,
aTrackRate);
if (NS_FAILED(rv)) {
LOG("[VideoTrackEncoder]: Fail to initialize the encoder!");
NotifyCancel();
@ -214,7 +217,8 @@ VideoTrackEncoder::NotifyEndOfStream()
// If source video track is muted till the end of encoding, initialize the
// encoder with default frame width, frame height, and track rate.
if (!mCanceled && !mInitialized) {
Init(DEFAULT_FRAME_WIDTH, DEFAULT_FRAME_HEIGHT, DEFAULT_TRACK_RATE);
Init(DEFAULT_FRAME_WIDTH, DEFAULT_FRAME_HEIGHT,
DEFAULT_FRAME_WIDTH, DEFAULT_FRAME_HEIGHT, DEFAULT_TRACK_RATE);
}
ReentrantMonitorAutoEnter mon(mReentrantMonitor);

View File

@ -222,6 +222,8 @@ public:
: TrackEncoder()
, mFrameWidth(0)
, mFrameHeight(0)
, mDisplayWidth(0)
, mDisplayHeight(0)
, mTrackRate(0)
, mTotalFrameDuration(0)
{}
@ -244,7 +246,8 @@ protected:
* mReentrantMonitor will be notified after it has successfully initialized,
* and this method is called on the MediaStramGraph thread.
*/
virtual nsresult Init(int aWidth, int aHeight, TrackRate aTrackRate) = 0;
virtual nsresult Init(int aWidth, int aHeight, int aDisplayWidth,
int aDisplayHeight, TrackRate aTrackRate) = 0;
/**
* Appends source video frames to mRawSegment. We only append the source chunk
@ -275,6 +278,16 @@ protected:
*/
int mFrameHeight;
/**
* The display width of source video frame.
*/
int mDisplayWidth;
/**
* The display height of source video frame.
*/
int mDisplayHeight;
/**
* The track rate of source video.
*/

View File

@ -53,9 +53,11 @@ VP8TrackEncoder::~VP8TrackEncoder()
}
nsresult
VP8TrackEncoder::Init(int32_t aWidth, int32_t aHeight, TrackRate aTrackRate)
VP8TrackEncoder::Init(int32_t aWidth, int32_t aHeight, int32_t aDisplayWidth,
int32_t aDisplayHeight,TrackRate aTrackRate)
{
if (aWidth < 1 || aHeight < 1 || aTrackRate <= 0) {
if (aWidth < 1 || aHeight < 1 || aDisplayWidth < 1 || aDisplayHeight < 1
|| aTrackRate <= 0) {
return NS_ERROR_FAILURE;
}
@ -66,6 +68,8 @@ VP8TrackEncoder::Init(int32_t aWidth, int32_t aHeight, TrackRate aTrackRate)
mEncodedFrameDuration = mTrackRate / mEncodedFrameRate;
mFrameWidth = aWidth;
mFrameHeight = aHeight;
mDisplayWidth = aDisplayWidth;
mDisplayHeight = aDisplayHeight;
// Encoder configuration structure.
vpx_codec_enc_cfg_t config;
@ -153,6 +157,8 @@ VP8TrackEncoder::GetMetadata()
nsRefPtr<VP8Metadata> meta = new VP8Metadata();
meta->mWidth = mFrameWidth;
meta->mHeight = mFrameHeight;
meta->mDisplayWidth = mDisplayWidth;
meta->mDisplayHeight = mDisplayHeight;
meta->mEncodedFrameRate = mEncodedFrameRate;
return meta.forget();

View File

@ -38,6 +38,7 @@ public:
protected:
nsresult Init(int32_t aWidth, int32_t aHeight,
int32_t aDisplayWidth, int32_t aDisplayHeight,
TrackRate aTrackRate) MOZ_FINAL MOZ_OVERRIDE;
private:

View File

@ -41,7 +41,8 @@ void EbmlComposer::GenerateHeader()
// Video
if (mWidth > 0 && mHeight > 0) {
writeVideoTrack(&ebml, 0x1, 0, "V_VP8",
mWidth, mHeight, mFrameRate);
mWidth, mHeight,
mDisplayWidth, mDisplayHeight, mFrameRate);
}
// Audio
if (mCodecPrivateData.Length() > 0) {
@ -123,13 +124,18 @@ EbmlComposer::WriteSimpleBlock(EncodedFrame* aFrame)
void
EbmlComposer::SetVideoConfig(uint32_t aWidth, uint32_t aHeight,
uint32_t aDisplayWidth, uint32_t aDisplayHeight,
float aFrameRate)
{
MOZ_ASSERT(aWidth > 0, "Width should > 0");
MOZ_ASSERT(aHeight > 0, "Height should > 0");
MOZ_ASSERT(aDisplayWidth > 0, "DisplayWidth should > 0");
MOZ_ASSERT(aDisplayHeight > 0, "DisplayHeight should > 0");
MOZ_ASSERT(aFrameRate > 0, "FrameRate should > 0");
mWidth = aWidth;
mHeight = aHeight;
mDisplayWidth = aDisplayWidth;
mDisplayHeight = aDisplayHeight;
mFrameRate = aFrameRate;
}

View File

@ -19,7 +19,8 @@ public:
/*
* Assign the parameter which header required.
*/
void SetVideoConfig(uint32_t aWidth, uint32_t aHeight, float aFrameRate);
void SetVideoConfig(uint32_t aWidth, uint32_t aHeight, uint32_t aDisplayWidth,
uint32_t aDisplayHeight, float aFrameRate);
void SetAudioConfig(uint32_t aSampleFreq, uint32_t aChannels,
uint32_t bitDepth);
@ -64,6 +65,8 @@ private:
// Video configuration
int mWidth;
int mHeight;
int mDisplayWidth;
int mDisplayHeight;
float mFrameRate;
// Audio configuration
float mSampleFreq;

View File

@ -43,6 +43,7 @@ WebMWriter::SetMetadata(TrackMetadataBase* aMetadata)
VP8Metadata* meta = static_cast<VP8Metadata*>(aMetadata);
MOZ_ASSERT(meta, "Cannot find vp8 encoder metadata");
mEbmlComposer->SetVideoConfig(meta->mWidth, meta->mHeight,
meta->mDisplayWidth, meta->mDisplayHeight,
meta->mEncodedFrameRate);
mMetadataRequiredFlag = mMetadataRequiredFlag & ~ContainerWriter::CREATE_VIDEO_TRACK;
}

View File

@ -29,6 +29,8 @@ class VP8Metadata : public TrackMetadataBase
public:
int32_t mWidth;
int32_t mHeight;
int32_t mDisplayWidth;
int32_t mDisplayHeight;
int32_t mEncodedFrameRate;
MetadataKind GetKind() const MOZ_OVERRIDE { return METADATA_VP8; }
};

View File

@ -57,6 +57,7 @@ static UInt64 generateTrackID(unsigned int trackNumber) {
void writeVideoTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
const char *codecId, unsigned int pixelWidth, unsigned int pixelHeight,
unsigned int displayWidth, unsigned int displayHeight,
double frameRate) {
EbmlLoc start;
UInt64 trackID;
@ -73,6 +74,12 @@ void writeVideoTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
Ebml_StartSubElement(glob, &videoStart, Video);
Ebml_SerializeUnsigned(glob, PixelWidth, pixelWidth);
Ebml_SerializeUnsigned(glob, PixelHeight, pixelHeight);
if (pixelWidth != displayWidth) {
Ebml_SerializeUnsigned(glob, DisplayWidth, displayWidth);
}
if (pixelHeight != displayHeight) {
Ebml_SerializeUnsigned(glob, DisplayHeight, displayHeight);
}
Ebml_SerializeFloat(glob, FrameRate, frameRate);
Ebml_EndSubElement(glob, &videoStart); // Video
}

View File

@ -21,6 +21,7 @@ void writeSegmentInformation(EbmlGlobal *ebml, EbmlLoc *startInfo, unsigned long
// this function is a helper only, it assumes a lot of defaults
void writeVideoTrack(EbmlGlobal *ebml, unsigned int trackNumber, int flagLacing,
const char *codecId, unsigned int pixelWidth, unsigned int pixelHeight,
unsigned int displayWidth, unsigned int displayHeight,
double frameRate);
void writeAudioTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
const char *codecId, double samplingFrequency, unsigned int channels,

View File

@ -0,0 +1,64 @@
diff --git a/media/libmkv/WebMElement.c b/media/libmkv/WebMElement.c
--- a/media/libmkv/WebMElement.c
+++ b/media/libmkv/WebMElement.c
@@ -52,32 +52,39 @@ static UInt64 generateTrackID(unsigned i
r = r << 32;
r += rand();
// UInt64 rval = t ^ r;
return t ^ r;
}
void writeVideoTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
const char *codecId, unsigned int pixelWidth, unsigned int pixelHeight,
+ unsigned int displayWidth, unsigned int displayHeight,
double frameRate) {
EbmlLoc start;
UInt64 trackID;
Ebml_StartSubElement(glob, &start, TrackEntry);
Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber);
trackID = generateTrackID(trackNumber);
Ebml_SerializeUnsigned(glob, TrackUID, trackID);
Ebml_SerializeString(glob, CodecName, "VP8"); // TODO shouldn't be fixed
Ebml_SerializeUnsigned(glob, TrackType, 1); // video is always 1
Ebml_SerializeString(glob, CodecID, codecId);
{
EbmlLoc videoStart;
Ebml_StartSubElement(glob, &videoStart, Video);
Ebml_SerializeUnsigned(glob, PixelWidth, pixelWidth);
Ebml_SerializeUnsigned(glob, PixelHeight, pixelHeight);
+ if (pixelWidth != displayWidth) {
+ Ebml_SerializeUnsigned(glob, DisplayWidth, displayWidth);
+ }
+ if (pixelHeight != displayHeight) {
+ Ebml_SerializeUnsigned(glob, DisplayHeight, displayHeight);
+ }
Ebml_SerializeFloat(glob, FrameRate, frameRate);
Ebml_EndSubElement(glob, &videoStart); // Video
}
Ebml_EndSubElement(glob, &start); // Track Entry
}
void writeAudioTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
const char *codecId, double samplingFrequency, unsigned int channels,
unsigned char *private, unsigned long privateSize) {
diff --git a/media/libmkv/WebMElement.h b/media/libmkv/WebMElement.h
--- a/media/libmkv/WebMElement.h
+++ b/media/libmkv/WebMElement.h
@@ -16,16 +16,17 @@ extern "C" {
#include "EbmlWriter.h"
// these are helper functions
void writeHeader(EbmlGlobal *ebml);
void writeSegmentInformation(EbmlGlobal *ebml, EbmlLoc *startInfo, unsigned long timeCodeScale, double duration);
// this function is a helper only, it assumes a lot of defaults
void writeVideoTrack(EbmlGlobal *ebml, unsigned int trackNumber, int flagLacing,
const char *codecId, unsigned int pixelWidth, unsigned int pixelHeight,
+ unsigned int displayWidth, unsigned int displayHeight,
double frameRate);
void writeAudioTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
const char *codecId, double samplingFrequency, unsigned int channels,
unsigned char *private_, unsigned long privateSize);
void writeSimpleBlock(EbmlGlobal *ebml, unsigned char trackNumber, short timeCode,
int isKeyframe, unsigned char lacingFlag, int discardable,
unsigned char *data, unsigned long dataLength);

View File

@ -35,3 +35,4 @@ patch -p1 < source_fix.patch
patch -p1 < gecko_fix.patch
patch -p1 < const_fix.patch
patch -p3 < bock_fix.patch
patch -p3 < bug970774.patch