Bug 480058. Handle non-square Theora pixel-aspect-ratio property. r=doublec

--HG--
extra : rebase_source : 0a43b053b52a9b1e300f7f516517722c44040992
This commit is contained in:
Robert O'Callahan 2009-05-19 11:07:19 +12:00
parent 507f48d89a
commit 2a3bc2dc98
3 changed files with 49 additions and 8 deletions

View File

@ -244,12 +244,14 @@ protected:
// Stop progress information timer.
nsresult StopProgress();
// Set the RGB width, height and framerate. Ownership of the passed RGB
// buffer is transferred to the decoder. This is the only nsMediaDecoder
// method that may be called from threads other than the main thread.
// Set the RGB width, height, pixel aspect ratio, and framerate.
// Ownership of the passed RGB buffer is transferred to the decoder.
// This is the only nsMediaDecoder method that may be called from
// threads other than the main thread.
void SetRGBData(PRInt32 aWidth,
PRInt32 aHeight,
float aFramerate,
float aAspectRatio,
unsigned char* aRGBBuffer);
protected:
@ -295,6 +297,9 @@ protected:
// expressed in numbers of frames per second.
float mFramerate;
// Pixel aspect ratio (ratio of the pixel width to pixel height)
float mAspectRatio;
// Has our size changed since the last repaint?
PRPackedBool mSizeChanged;

View File

@ -72,6 +72,7 @@ nsMediaDecoder::nsMediaDecoder() :
mDataTime(),
mVideoUpdateLock(nsnull),
mFramerate(0.0),
mAspectRatio(1.0),
mSizeChanged(PR_FALSE),
mShuttingDown(PR_FALSE),
mStopping(PR_FALSE)
@ -114,6 +115,14 @@ nsresult nsMediaDecoder::InitLogger()
return NS_OK;
}
static PRInt32 ConditionDimension(float aValue, PRInt32 aDefault)
{
// This will exclude NaNs and infinities
if (aValue >= 1.0 && aValue <= 10000.0)
return PRInt32(NS_round(aValue));
return aDefault;
}
void nsMediaDecoder::Invalidate()
{
if (!mElement)
@ -124,7 +133,20 @@ void nsMediaDecoder::Invalidate()
{
nsAutoLock lock(mVideoUpdateLock);
if (mSizeChanged) {
mElement->UpdateMediaSize(nsIntSize(mRGBWidth, mRGBHeight));
nsIntSize scaledSize(mRGBWidth, mRGBHeight);
// Apply the aspect ratio to produce the intrinsic size we report
// to the element.
if (mAspectRatio > 1.0) {
// Increase the intrinsic width
scaledSize.width =
ConditionDimension(mAspectRatio*scaledSize.width, scaledSize.width);
} else {
// Increase the intrinsic height
scaledSize.height =
ConditionDimension(scaledSize.height/mAspectRatio, scaledSize.height);
}
mElement->UpdateMediaSize(scaledSize);
mSizeChanged = PR_FALSE;
if (frame) {
nsPresContext* presContext = frame->PresContext();
@ -200,13 +222,16 @@ nsresult nsMediaDecoder::StopProgress()
return rv;
}
void nsMediaDecoder::SetRGBData(PRInt32 aWidth, PRInt32 aHeight, float aFramerate, unsigned char* aRGBBuffer)
void nsMediaDecoder::SetRGBData(PRInt32 aWidth, PRInt32 aHeight, float aFramerate,
float aAspectRatio, unsigned char* aRGBBuffer)
{
nsAutoLock lock(mVideoUpdateLock);
if (mRGBWidth != aWidth || mRGBHeight != aHeight) {
if (mRGBWidth != aWidth || mRGBHeight != aHeight ||
mAspectRatio != aAspectRatio) {
mRGBWidth = aWidth;
mRGBHeight = aHeight;
mAspectRatio = aAspectRatio;
mSizeChanged = PR_TRUE;
}
mFramerate = aFramerate;

View File

@ -473,6 +473,7 @@ private:
// They are only accessed from the decoder thread.
PRInt32 mVideoTrack;
float mFramerate;
float mAspectRatio;
// Audio data. These are initially set when the metadata is loaded.
// They are only accessed from the decoder thread.
@ -660,6 +661,7 @@ nsOggDecodeStateMachine::nsOggDecodeStateMachine(nsOggDecoder* aDecoder) :
mCallbackPeriod(1.0),
mVideoTrack(-1),
mFramerate(0.0),
mAspectRatio(1.0),
mAudioRate(0),
mAudioChannels(0),
mAudioTrack(-1),
@ -933,7 +935,8 @@ void nsOggDecodeStateMachine::PlayVideo(FrameData* aFrame)
oggplay_yuv2bgra(&yuv, &rgb);
mDecoder->SetRGBData(aFrame->mVideoWidth, aFrame->mVideoHeight, mFramerate, buffer.forget());
mDecoder->SetRGBData(aFrame->mVideoWidth, aFrame->mVideoHeight,
mFramerate, mAspectRatio, buffer.forget());
}
}
@ -1550,10 +1553,18 @@ void nsOggDecodeStateMachine::LoadOggHeaders(nsChannelReader* aReader)
mCallbackPeriod = 1.0 / mFramerate;
LOG(PR_LOG_DEBUG, ("Frame rate: %f", mFramerate));
int aspectd, aspectn;
// this can return E_OGGPLAY_UNINITIALIZED if the video has
// no aspect ratio data. We assume 1.0 in that case.
OggPlayErrorCode r =
oggplay_get_video_aspect_ratio(mPlayer, i, &aspectd, &aspectn);
mAspectRatio = r == E_OGGPLAY_OK && aspectd > 0 ?
float(aspectn)/float(aspectd) : 1.0;
int y_width;
int y_height;
oggplay_get_video_y_size(mPlayer, i, &y_width, &y_height);
mDecoder->SetRGBData(y_width, y_height, mFramerate, nsnull);
mDecoder->SetRGBData(y_width, y_height, mFramerate, mAspectRatio, nsnull);
}
else if (mAudioTrack == -1 && oggplay_get_track_type(mPlayer, i) == OGGZ_CONTENT_VORBIS) {
mAudioTrack = i;