Bug 508082: Implement a raw video decoder. r=doublec

--HG--
extra : rebase_source : 2ffc36ceb9cb8407531efa6e7b1f0548e81c170c
This commit is contained in:
Kyle Huey 2010-06-17 17:36:57 -07:00
Родитель 78056f9387
Коммит 0d120276b1
18 изменённых файлов: 677 добавлений и 14 удалений

Просмотреть файл

@ -154,6 +154,7 @@ MOZ_MORK = @MOZ_MORK@
MOZ_MORKREADER = @MOZ_MORKREADER@ MOZ_MORKREADER = @MOZ_MORKREADER@
MOZ_NO_FAST_LOAD = @MOZ_NO_FAST_LOAD@ MOZ_NO_FAST_LOAD = @MOZ_NO_FAST_LOAD@
MOZ_OGG = @MOZ_OGG@ MOZ_OGG = @MOZ_OGG@
MOZ_RAW = @MOZ_RAW@
MOZ_SYDNEYAUDIO = @MOZ_SYDNEYAUDIO@ MOZ_SYDNEYAUDIO = @MOZ_SYDNEYAUDIO@
MOZ_WAVE = @MOZ_WAVE@ MOZ_WAVE = @MOZ_WAVE@
MOZ_MEDIA = @MOZ_MEDIA@ MOZ_MEDIA = @MOZ_MEDIA@

Просмотреть файл

@ -4907,6 +4907,7 @@ MOZ_NO_ACTIVEX_SUPPORT=1
MOZ_NO_INSPECTOR_APIS= MOZ_NO_INSPECTOR_APIS=
MOZ_NO_FAST_LOAD= MOZ_NO_FAST_LOAD=
MOZ_OGG=1 MOZ_OGG=1
MOZ_RAW=1
MOZ_SYDNEYAUDIO= MOZ_SYDNEYAUDIO=
MOZ_VORBIS= MOZ_VORBIS=
MOZ_WAVE=1 MOZ_WAVE=1
@ -5856,6 +5857,9 @@ if test -n "$MOZ_NO_FAST_LOAD"; then
AC_DEFINE(MOZ_NO_FAST_LOAD) AC_DEFINE(MOZ_NO_FAST_LOAD)
fi fi
AC_SUBST(MOZ_RAW)
AC_DEFINE(MOZ_RAW)
dnl ======================================================== dnl ========================================================
dnl = Disable Ogg Codecs dnl = Disable Ogg Codecs
dnl ======================================================== dnl ========================================================

Просмотреть файл

@ -96,6 +96,9 @@
#ifdef MOZ_WEBM #ifdef MOZ_WEBM
#include "nsWebMDecoder.h" #include "nsWebMDecoder.h"
#endif #endif
#ifdef MOZ_RAW
#include "nsRawDecoder.h"
#endif
#ifdef PR_LOGGING #ifdef PR_LOGGING
static PRLogModuleInfo* gMediaElementLog; static PRLogModuleInfo* gMediaElementLog;
@ -1184,7 +1187,36 @@ void nsHTMLMediaElement::UnbindFromTree(PRBool aDeep,
Pause(); Pause();
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent); nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
} }
#ifdef MOZ_RAW
static const char gRawTypes[][16] = {
"video/x-raw",
"video/x-raw-yuv"
};
static const char* gRawCodecs[] = {
nsnull
};
static const char* gRawMaybeCodecs[] = {
nsnull
};
static PRBool IsRawEnabled()
{
return nsContentUtils::GetBoolPref("media.raw.enabled");
}
static PRBool IsRawType(const nsACString& aType)
{
if (!IsRawEnabled())
return PR_FALSE;
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(gRawTypes); ++i) {
if (aType.EqualsASCII(gRawTypes[i]))
return PR_TRUE;
}
return PR_FALSE;
}
#endif
#ifdef MOZ_OGG #ifdef MOZ_OGG
// See http://www.rfc-editor.org/rfc/rfc5334.txt for the definitions // See http://www.rfc-editor.org/rfc/rfc5334.txt for the definitions
// of Ogg media types and codec types // of Ogg media types and codec types
@ -1285,6 +1317,12 @@ nsHTMLMediaElement::CanPlayStatus
nsHTMLMediaElement::CanHandleMediaType(const char* aMIMEType, nsHTMLMediaElement::CanHandleMediaType(const char* aMIMEType,
const char*** aCodecList) const char*** aCodecList)
{ {
#ifdef MOZ_RAW
if (IsRawType(nsDependentCString(aMIMEType))) {
*aCodecList = gRawCodecs;
return CANPLAY_MAYBE;
}
#endif
#ifdef MOZ_OGG #ifdef MOZ_OGG
if (IsOggType(nsDependentCString(aMIMEType))) { if (IsOggType(nsDependentCString(aMIMEType))) {
*aCodecList = gOggCodecs; *aCodecList = gOggCodecs;
@ -1309,6 +1347,10 @@ nsHTMLMediaElement::CanHandleMediaType(const char* aMIMEType,
/* static */ /* static */
PRBool nsHTMLMediaElement::ShouldHandleMediaType(const char* aMIMEType) PRBool nsHTMLMediaElement::ShouldHandleMediaType(const char* aMIMEType)
{ {
#ifdef MOZ_RAW
if (IsRawType(nsDependentCString(aMIMEType)))
return PR_TRUE;
#endif
#ifdef MOZ_OGG #ifdef MOZ_OGG
if (IsOggType(nsDependentCString(aMIMEType))) if (IsOggType(nsDependentCString(aMIMEType)))
return PR_TRUE; return PR_TRUE;
@ -1425,6 +1467,11 @@ void nsHTMLMediaElement::ShutdownMediaTypes()
nsresult rv; nsresult rv;
nsCOMPtr<nsICategoryManager> catMan(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv)); nsCOMPtr<nsICategoryManager> catMan(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv));
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
#ifdef MOZ_RAW
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(gRawTypes); i++) {
catMan->DeleteCategoryEntry("Gecko-Content-Viewers", gRawTypes[i], PR_FALSE);
}
#endif
#ifdef MOZ_OGG #ifdef MOZ_OGG
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(gOggTypes); i++) { for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(gOggTypes); i++) {
catMan->DeleteCategoryEntry("Gecko-Content-Viewers", gOggTypes[i], PR_FALSE); catMan->DeleteCategoryEntry("Gecko-Content-Viewers", gOggTypes[i], PR_FALSE);
@ -1446,6 +1493,14 @@ void nsHTMLMediaElement::ShutdownMediaTypes()
already_AddRefed<nsMediaDecoder> already_AddRefed<nsMediaDecoder>
nsHTMLMediaElement::CreateDecoder(const nsACString& aType) nsHTMLMediaElement::CreateDecoder(const nsACString& aType)
{ {
#ifdef MOZ_RAW
if (IsRawType(aType)) {
nsRefPtr<nsRawDecoder> decoder = new nsRawDecoder();
if (decoder && decoder->Init(this)) {
return decoder.forget().get();
}
}
#endif
#ifdef MOZ_OGG #ifdef MOZ_OGG
if (IsOggType(aType)) { if (IsOggType(aType)) {
nsRefPtr<nsOggDecoder> decoder = new nsOggDecoder(); nsRefPtr<nsOggDecoder> decoder = new nsOggDecoder();

Просмотреть файл

@ -73,6 +73,10 @@ CPPSRCS += \
$(NULL) $(NULL)
endif endif
ifdef MOZ_RAW
PARALLEL_DIRS += raw
endif
ifdef MOZ_OGG ifdef MOZ_OGG
PARALLEL_DIRS += ogg PARALLEL_DIRS += ogg
endif endif

Просмотреть файл

@ -59,6 +59,18 @@
#define PR_INT64_MIN (-PR_INT64_MAX - 1) #define PR_INT64_MIN (-PR_INT64_MAX - 1)
#define PR_UINT64_MAX (~(PRUint64)(0)) #define PR_UINT64_MAX (~(PRUint64)(0))
static PRBool MulOverflow32(PRUint32 a, PRUint32 b, PRUint32 &aResult)
{
PRUint64 rl = static_cast<PRUint64>(a) * static_cast<PRUint64>(b);
if (rl > PR_UINT32_MAX) {
return PR_FALSE;
}
aResult = static_cast<PRUint32>(rl);
return PR_TRUE;
}
// This belongs in xpcom/monitor/Monitor.h, once we've made // This belongs in xpcom/monitor/Monitor.h, once we've made
// mozilla::Monitor non-reentrant. // mozilla::Monitor non-reentrant.

Просмотреть файл

@ -61,20 +61,6 @@ static PRBool AddOverflow(PRInt64 a, PRInt64 b, PRInt64& aResult);
// in an integer overflow. // in an integer overflow.
static PRBool MulOverflow(PRInt64 a, PRInt64 b, PRInt64& aResult); static PRBool MulOverflow(PRInt64 a, PRInt64 b, PRInt64& aResult);
static PRBool MulOverflow32(PRUint32 a, PRUint32 b, PRUint32& aResult)
{
// 32 bit integer multiplication with overflow checking. Returns PR_TRUE
// if the multiplication was successful, or PR_FALSE if the operation resulted
// in an integer overflow.
PRUint64 a64 = a;
PRUint64 b64 = b;
PRUint64 r64 = a64 * b64;
if (r64 > PR_UINT32_MAX)
return PR_FALSE;
aResult = static_cast<PRUint32>(r64);
return PR_TRUE;
}
nsOggCodecState* nsOggCodecState*
nsOggCodecState::Create(ogg_page* aPage) nsOggCodecState::Create(ogg_page* aPage)
{ {

Просмотреть файл

@ -0,0 +1,67 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Mozilla Raw Decoder code.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2010
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Brad Lassey <blassey@mozilla.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = content
LIBRARY_NAME = gkconraw_s
LIBXUL_LIBRARY = 1
EXPORTS += \
nsRawDecoder.h \
nsRawReader.h \
$(NULL)
CPPSRCS += \
nsRawDecoder.cpp \
nsRawReader.cpp \
$(NULL)
FORCE_STATIC_LIB = 1
include $(topsrcdir)/config/rules.mk
INCLUDES += \
-I$(srcdir)/../../base/src \
-I$(srcdir)/../../html/content/src \
$(NULL)

Просмотреть файл

@ -0,0 +1,44 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Raw Decoder code.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsBuiltinDecoderStateMachine.h"
#include "nsRawReader.h"
#include "nsRawDecoder.h"
nsDecoderStateMachine* nsRawDecoder::CreateStateMachine()
{
return new nsBuiltinDecoderStateMachine(this, new nsRawReader(this));
}

Просмотреть файл

@ -0,0 +1,49 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Raw Decoder code.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#if !defined(nsRawDecoder_h_)
#define nsRawDecoder_h_
#include "nsBuiltinDecoder.h"
class nsRawDecoder : public nsBuiltinDecoder
{
public:
virtual nsMediaDecoder* Clone() { return new nsRawDecoder(); }
virtual nsDecoderStateMachine* CreateStateMachine();
};
#endif

Просмотреть файл

@ -0,0 +1,299 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla code.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brad Lassey <blassey@mozilla.com>
* Kyle Huey <me@kylehuey.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsBuiltinDecoderStateMachine.h"
#include "nsBuiltinDecoder.h"
#include "nsRawReader.h"
#include "nsRawDecoder.h"
#include "VideoUtils.h"
#define RAW_ID 0x595556
nsRawReader::nsRawReader(nsBuiltinDecoder* aDecoder)
: nsBuiltinDecoderReader(aDecoder),
mCurrentFrame(0)
{
MOZ_COUNT_CTOR(nsRawReader);
}
nsRawReader::~nsRawReader()
{
MOZ_COUNT_DTOR(nsRawReader);
}
nsresult nsRawReader::Init()
{
return NS_OK;
}
nsresult nsRawReader::ResetDecode()
{
mCurrentFrame = 0;
return nsBuiltinDecoderReader::ResetDecode();
}
nsresult nsRawReader::ReadMetadata()
{
NS_ASSERTION(mDecoder->OnStateMachineThread(),
"Should be on state machine thread.");
mozilla::MonitorAutoEnter autoEnter(mMonitor);
nsMediaStream* stream = mDecoder->GetCurrentStream();
NS_ASSERTION(stream, "Decoder has no media stream");
if (!ReadFromStream(stream, reinterpret_cast<PRUint8*>(&mMetadata),
sizeof(mMetadata)))
return NS_ERROR_FAILURE;
// Validate the header
if (!(mMetadata.headerPacketID == 0 /* Packet ID of 0 for the header*/ &&
mMetadata.codecID == RAW_ID /* "YUV" */ &&
mMetadata.majorVersion == 0 &&
mMetadata.minorVersion == 1))
return NS_ERROR_FAILURE;
PRUint32 dummy;
if (!MulOverflow32(mMetadata.frameWidth, mMetadata.frameHeight, dummy))
return NS_ERROR_FAILURE;
mInfo.mHasVideo = PR_TRUE;
mInfo.mPicture.x = 0;
mInfo.mPicture.y = 0;
mInfo.mPicture.width = mMetadata.frameWidth;
mInfo.mPicture.height = mMetadata.frameHeight;
mInfo.mFrame.width = mMetadata.frameWidth;
mInfo.mFrame.height = mMetadata.frameHeight;
if (mMetadata.aspectDenominator == 0 ||
mMetadata.framerateDenominator == 0)
return NS_ERROR_FAILURE; // Invalid data
mInfo.mPixelAspectRatio = static_cast<float>(mMetadata.aspectNumerator) /
mMetadata.aspectDenominator;
mInfo.mDataOffset = sizeof(nsRawVideoHeader) + 1;
mInfo.mHasAudio = PR_FALSE;
mFrameRate = static_cast<float>(mMetadata.framerateNumerator) /
mMetadata.framerateDenominator;
// Make some sanity checks
if (mFrameRate > 45 ||
mFrameRate == 0 ||
mInfo.mPixelAspectRatio == 0 ||
mMetadata.frameWidth > 2000 ||
mMetadata.frameHeight > 2000 ||
mMetadata.chromaChannelBpp != 4 ||
mMetadata.lumaChannelBpp != 8 ||
mMetadata.colorspace != 1 /* 4:2:0 */)
return NS_ERROR_FAILURE;
mFrameSize = mMetadata.frameWidth * mMetadata.frameHeight *
(mMetadata.lumaChannelBpp + mMetadata.chromaChannelBpp) / 8.0 +
sizeof(nsRawPacketHeader);
PRInt64 length = stream->GetLength();
if (length != -1) {
mozilla::MonitorAutoExit autoExitMonitor(mMonitor);
mozilla::MonitorAutoEnter autoMonitor(mDecoder->GetMonitor());
mDecoder->GetStateMachine()->SetDuration(1000 *
(length - sizeof(nsRawVideoHeader)) /
(mFrameSize * mFrameRate));
}
return NS_OK;
}
PRBool nsRawReader::DecodeAudioData()
{
NS_ASSERTION(mDecoder->OnStateMachineThread() || mDecoder->OnDecodeThread(),
"Should be on state machine thread or decode thread.");
return PR_FALSE;
}
// Helper method that either reads until it gets aLength bytes
// or returns PR_FALSE
PRBool nsRawReader::ReadFromStream(nsMediaStream *aStream, PRUint8* aBuf,
PRUint32 aLength)
{
while (aLength > 0) {
PRUint32 bytesRead = 0;
nsresult rv;
rv = aStream->Read(reinterpret_cast<char*>(aBuf), aLength, &bytesRead);
NS_ENSURE_SUCCESS(rv, PR_FALSE);
if (bytesRead == 0) {
return PR_FALSE;
}
aLength -= bytesRead;
aBuf += bytesRead;
}
return PR_TRUE;
}
PRBool nsRawReader::DecodeVideoFrame(PRBool &aKeyframeSkip,
PRInt64 aTimeThreshold)
{
mozilla::MonitorAutoEnter autoEnter(mMonitor);
NS_ASSERTION(mDecoder->OnStateMachineThread() || mDecoder->OnDecodeThread(),
"Should be on state machine thread or decode thread.");
PRInt64 currentFrameTime = 1000 * mCurrentFrame / mFrameRate;
PRUint32 length = mFrameSize - sizeof(nsRawPacketHeader);
nsAutoPtr<PRUint8> buffer(new PRUint8[length]);
nsMediaStream* stream = mDecoder->GetCurrentStream();
NS_ASSERTION(stream, "Decoder has no media stream");
// We're always decoding one frame when called
while(true) {
nsRawPacketHeader header;
// Read in a packet header and validate
if (!(ReadFromStream(stream, reinterpret_cast<PRUint8*>(&header),
sizeof(header))) ||
!(header.packetID == 0xFF && header.codecID == RAW_ID /* "YUV" */)) {
return PR_FALSE;
}
if (!ReadFromStream(stream, buffer, length)) {
return PR_FALSE;
}
if (currentFrameTime >= aTimeThreshold)
break;
mCurrentFrame++;
currentFrameTime += 1000.0 / mFrameRate;
}
VideoData::YCbCrBuffer b;
b.mPlanes[0].mData = buffer;
b.mPlanes[0].mStride = mMetadata.frameWidth * mMetadata.lumaChannelBpp / 8.0;
b.mPlanes[0].mHeight = mMetadata.frameHeight;
b.mPlanes[0].mWidth = mMetadata.frameWidth;
PRUint32 cbcrStride = mMetadata.frameWidth * mMetadata.chromaChannelBpp / 8.0;
b.mPlanes[1].mData = buffer + mMetadata.frameHeight * b.mPlanes[0].mStride;
b.mPlanes[1].mStride = cbcrStride;
b.mPlanes[1].mHeight = mMetadata.frameHeight / 2;
b.mPlanes[1].mWidth = mMetadata.frameWidth / 2;
b.mPlanes[2].mData = b.mPlanes[1].mData + mMetadata.frameHeight * cbcrStride / 2;
b.mPlanes[2].mStride = cbcrStride;
b.mPlanes[2].mHeight = mMetadata.frameHeight / 2;
b.mPlanes[2].mWidth = mMetadata.frameWidth / 2;
VideoData *v = VideoData::Create(mInfo,
mDecoder->GetImageContainer(),
-1,
currentFrameTime,
currentFrameTime + (1000 / mFrameRate),
b,
1, // In raw video every frame is a keyframe
-1);
if (!v)
return PR_FALSE;
mVideoQueue.Push(v);
mCurrentFrame++;
currentFrameTime += 1000 / mFrameRate;
return PR_TRUE;
}
nsresult nsRawReader::Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime)
{
mozilla::MonitorAutoEnter autoEnter(mMonitor);
NS_ASSERTION(mDecoder->OnStateMachineThread(),
"Should be on state machine thread.");
nsMediaStream *stream = mDecoder->GetCurrentStream();
NS_ASSERTION(stream, "Decoder has no media stream");
PRUint32 frame = mCurrentFrame;
if (aTime >= UINT_MAX)
return NS_ERROR_FAILURE;
mCurrentFrame = aTime * mFrameRate / 1000;
PRUint32 offset;
if (!MulOverflow32(mCurrentFrame, mFrameSize, offset))
return NS_ERROR_FAILURE;
offset += sizeof(nsRawVideoHeader);
nsresult rv = stream->Seek(nsISeekableStream::NS_SEEK_SET, offset);
NS_ENSURE_SUCCESS(rv, rv);
mVideoQueue.Erase();
while(mVideoQueue.GetSize() == 0) {
PRBool keyframeSkip = PR_FALSE;
if (!DecodeVideoFrame(keyframeSkip, 0)) {
mCurrentFrame = frame;
return NS_ERROR_FAILURE;
}
{
mozilla::MonitorAutoExit autoMonitorExit(mMonitor);
mozilla::MonitorAutoEnter autoMonitor(mDecoder->GetMonitor());
if (mDecoder->GetDecodeState() ==
nsBuiltinDecoderStateMachine::DECODER_STATE_SHUTDOWN) {
mCurrentFrame = frame;
return NS_ERROR_FAILURE;
}
}
nsAutoPtr<VideoData> video(mVideoQueue.PeekFront());
if (video && video->mEndTime < aTime) {
mVideoQueue.PopFront();
video = nsnull;
} else {
video.forget();
}
}
return NS_OK;
}
PRInt64 nsRawReader::FindEndTime(PRInt64 aEndTime)
{
return -1;
}

Просмотреть файл

@ -0,0 +1,127 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla code.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brad Lassey
* Kyle Huey <me@kylehuey.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#if !defined(nsRawReader_h_)
#define nsRawReader_h_
#include "nsBuiltinDecoderReader.h"
struct nsRawVideo_PRUint24 {
operator PRUint32() const { return value[2] << 16 | value[1] << 8 | value[0]; }
private:
PRUint8 value[3];
};
struct nsRawPacketHeader {
typedef nsRawVideo_PRUint24 PRUint24;
PRUint8 packetID;
PRUint24 codecID;
};
// This is Arc's draft from wiki.xiph.org/OggYUV
struct nsRawVideoHeader {
typedef nsRawVideo_PRUint24 PRUint24;
PRUint8 headerPacketID; // Header Packet ID (always 0)
PRUint24 codecID; // Codec identifier (always "YUV")
PRUint8 majorVersion; // Version Major (breaks backwards compat)
PRUint8 minorVersion; // Version Minor (preserves backwards compat)
PRUint16 options; // Bit 1: Color (false = B/W)
// Bits 2-4: Chroma Pixel Shape
// Bit 5: 50% horizontal offset for Cr samples
// Bit 6: 50% vertical ...
// Bits 7-8: Chroma Blending
// Bit 9: Packed (false = Planar)
// Bit 10: Cr Staggered Horizontally
// Bit 11: Cr Staggered Vertically
// Bit 12: Unused (format is always little endian)
// Bit 13: Interlaced (false = Progressive)
// Bits 14-16: Interlace options (undefined)
PRUint8 alphaChannelBpp;
PRUint8 lumaChannelBpp;
PRUint8 chromaChannelBpp;
PRUint8 colorspace;
PRUint24 frameWidth;
PRUint24 frameHeight;
PRUint24 aspectNumerator;
PRUint24 aspectDenominator;
PRUint32 framerateNumerator;
PRUint32 framerateDenominator;
};
class nsRawReader : public nsBuiltinDecoderReader
{
public:
nsRawReader(nsBuiltinDecoder* aDecoder);
~nsRawReader();
virtual nsresult Init();
virtual nsresult ResetDecode();
virtual PRBool DecodeAudioData();
virtual PRBool DecodeVideoFrame(PRBool &aKeyframeSkip,
PRInt64 aTimeThreshold);
virtual PRBool HasAudio()
{
return PR_FALSE;
}
virtual PRBool HasVideo()
{
return PR_TRUE;
}
virtual nsresult ReadMetadata();
virtual nsresult Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime);
virtual PRInt64 FindEndTime(PRInt64 aEndOffset);
private:
PRBool ReadFromStream(nsMediaStream *aStream, PRUint8 *aBuf,
PRUint32 aLength);
nsRawVideoHeader mMetadata;
PRUint32 mCurrentFrame;
double mFrameRate;
PRUint32 mFrameSize;
};
#endif

Просмотреть файл

@ -194,6 +194,7 @@ _TEST_FILES += \
dirac.ogg \ dirac.ogg \
seek.ogv \ seek.ogv \
seek.webm \ seek.webm \
seek.yuv \
short-video.ogv \ short-video.ogv \
small-shot.ogg \ small-shot.ogg \
sound.ogg \ sound.ogg \

Просмотреть файл

@ -102,6 +102,9 @@ var gPlayTests = [
// Test playback of a webm file // Test playback of a webm file
{ name:"seek.webm", type:"video/webm", duration:3.966 }, { name:"seek.webm", type:"video/webm", duration:3.966 },
// Test playback of a raw file
{ name:"seek.yuv", type:"video/x-raw-yuv", duration:1.833 },
{ name:"bogus.duh", type:"bogus/duh", duration:Number.NaN } { name:"bogus.duh", type:"bogus/duh", duration:Number.NaN }
]; ];

Двоичные данные
content/media/test/seek.yuv Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -131,6 +131,12 @@ SHARED_LIBRARY_LIBS += \
$(NULL) $(NULL)
endif endif
ifdef MOZ_RAW
SHARED_LIBRARY_LIBS += \
$(DEPTH)/content/media/raw/$(LIB_PREFIX)gkconraw_s.$(LIB_SUFFIX)\
$(NULL)
endif
ifdef MOZ_WEBM ifdef MOZ_WEBM
SHARED_LIBRARY_LIBS += \ SHARED_LIBRARY_LIBS += \
$(DEPTH)/content/media/webm/$(LIB_PREFIX)gkconwebm_s.$(LIB_SUFFIX) \ $(DEPTH)/content/media/webm/$(LIB_PREFIX)gkconwebm_s.$(LIB_SUFFIX) \

Просмотреть файл

@ -156,6 +156,9 @@ pref("media.enforce_same_site_origin", false);
// Media cache size in kilobytes // Media cache size in kilobytes
pref("media.cache_size", 512000); pref("media.cache_size", 512000);
#ifdef MOZ_RAW
pref("media.raw.enabled", true);
#endif
#ifdef MOZ_OGG #ifdef MOZ_OGG
pref("media.ogg.enabled", true); pref("media.ogg.enabled", true);
#endif #endif

Просмотреть файл

@ -156,6 +156,7 @@
#define TEXT_XSL "text/xsl" #define TEXT_XSL "text/xsl"
#define VIDEO_MPEG "video/mpeg" #define VIDEO_MPEG "video/mpeg"
#define VIDEO_RAW "video/x-raw-yuv"
#define VIDEO_OGG "video/ogg" #define VIDEO_OGG "video/ogg"
#define VIDEO_WEBM "video/webm" #define VIDEO_WEBM "video/webm"
#define APPLICATION_OGG "application/ogg" #define APPLICATION_OGG "application/ogg"

Просмотреть файл

@ -544,6 +544,7 @@ static nsExtraMimeTypeEntry extraMimeEntries [] =
{ VIDEO_WEBM, "webm", "Web Media Video" }, { VIDEO_WEBM, "webm", "Web Media Video" },
{ AUDIO_WEBM, "webm", "Web Media Audio" }, { AUDIO_WEBM, "webm", "Web Media Audio" },
#endif #endif
{ VIDEO_RAW, "yuv", "Raw YUV Video" },
{ AUDIO_WAV, "wav", "Waveform Audio" }, { AUDIO_WAV, "wav", "Waveform Audio" },
}; };