Bug 1150853: Part2. Use new MediaRawObject across the board. r=cpearce.

This commit is contained in:
Jean-Yves Avenard 2015-04-09 21:14:55 +10:00
Родитель a441d92aa3
Коммит e6858f0af5
67 изменённых файлов: 503 добавлений и 639 удалений

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

@ -17,6 +17,7 @@
#include "prenv.h"
#include "mozilla/PodOperations.h"
#include "mozilla/CDMCallbackProxy.h"
#include "MediaData.h"
namespace mozilla {
@ -613,7 +614,7 @@ CDMProxy::Capabilites() {
}
void
CDMProxy::Decrypt(mp4_demuxer::MP4Sample* aSample,
CDMProxy::Decrypt(MediaRawData* aSample,
DecryptionClient* aClient)
{
nsAutoPtr<DecryptJob> job(new DecryptJob(aSample, aClient));
@ -636,8 +637,8 @@ CDMProxy::gmp_Decrypt(nsAutoPtr<DecryptJob> aJob)
aJob->mId = ++mDecryptionJobCount;
nsTArray<uint8_t> data;
data.AppendElements(aJob->mSample->data, aJob->mSample->size);
mCDM->Decrypt(aJob->mId, aJob->mSample->crypto, data);
data.AppendElements(aJob->mSample->mData, aJob->mSample->mSize);
mCDM->Decrypt(aJob->mId, aJob->mSample->mCrypto, data);
mDecryptionJobs.AppendElement(aJob.forget());
}
@ -650,19 +651,20 @@ CDMProxy::gmp_Decrypted(uint32_t aId,
for (size_t i = 0; i < mDecryptionJobs.Length(); i++) {
DecryptJob* job = mDecryptionJobs[i];
if (job->mId == aId) {
if (aDecryptedData.Length() != job->mSample->size) {
if (aDecryptedData.Length() != job->mSample->mSize) {
NS_WARNING("CDM returned incorrect number of decrypted bytes");
}
if (GMP_SUCCEEDED(aResult)) {
PodCopy(job->mSample->data,
nsAutoPtr<MediaRawDataWriter> writer(job->mSample->CreateWriter());
PodCopy(writer->mData,
aDecryptedData.Elements(),
std::min<size_t>(aDecryptedData.Length(), job->mSample->size));
job->mClient->Decrypted(GMPNoErr, job->mSample.forget());
std::min<size_t>(aDecryptedData.Length(), job->mSample->mSize));
job->mClient->Decrypted(GMPNoErr, job->mSample);
} else if (aResult == GMPNoKeyErr) {
NS_WARNING("CDM returned GMPNoKeyErr");
// We still have the encrypted sample, so we can re-enqueue it to be
// decrypted again once the key is usable again.
job->mClient->Decrypted(GMPNoKeyErr, job->mSample.forget());
job->mClient->Decrypted(GMPNoKeyErr, job->mSample);
} else {
nsAutoCString str("CDM returned decode failure GMPErr=");
str.AppendInt(aResult);

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

@ -14,10 +14,9 @@
#include "nsIThread.h"
#include "GMPDecryptorProxy.h"
#include "mozilla/CDMCaps.h"
#include "mp4_demuxer/DecoderData.h"
namespace mozilla {
class MediaRawData;
class CDMCallbackProxy;
namespace dom {
@ -28,7 +27,7 @@ class DecryptionClient {
public:
virtual ~DecryptionClient() {}
virtual void Decrypted(GMPErr aResult,
mp4_demuxer::MP4Sample* aSample) = 0;
MediaRawData* aSample) = 0;
};
// Proxies calls GMP/CDM, and proxies calls back.
@ -142,8 +141,7 @@ public:
const nsAString& aMsg);
// Threadsafe.
void Decrypt(mp4_demuxer::MP4Sample* aSample,
DecryptionClient* aSink);
void Decrypt(MediaRawData* aSample, DecryptionClient* aSink);
// Reject promise with DOMException corresponding to aExceptionCode.
// Can be called from any thread.
@ -236,14 +234,13 @@ private:
void gmp_RemoveSession(nsAutoPtr<SessionOpData> aData);
struct DecryptJob {
DecryptJob(mp4_demuxer::MP4Sample* aSample,
DecryptionClient* aClient)
DecryptJob(MediaRawData* aSample, DecryptionClient* aClient)
: mId(0)
, mSample(aSample)
, mClient(aClient)
{}
uint32_t mId;
nsAutoPtr<mp4_demuxer::MP4Sample> mSample;
nsRefPtr<MediaRawData> mSample;
nsAutoPtr<DecryptionClient> mClient;
};
// GMP thread only.

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

@ -41,7 +41,7 @@ public:
class OutputEvent : public nsRunnable {
public:
OutputEvent(mp4_demuxer::MP4Sample* aSample,
OutputEvent(MediaRawData* aSample,
MediaDataDecoderCallback* aCallback,
BlankMediaDataCreator* aCreator)
: mSample(aSample)
@ -51,19 +51,19 @@ public:
}
NS_IMETHOD Run() override
{
nsRefPtr<MediaData> data = mCreator->Create(mSample->composition_timestamp,
mSample->duration,
mSample->byte_offset);
nsRefPtr<MediaData> data = mCreator->Create(mSample->mTime,
mSample->mDuration,
mSample->mOffset);
mCallback->Output(data);
return NS_OK;
}
private:
nsAutoPtr<mp4_demuxer::MP4Sample> mSample;
nsRefPtr<MediaRawData> mSample;
BlankMediaDataCreator* mCreator;
MediaDataDecoderCallback* mCallback;
};
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) override
virtual nsresult Input(MediaRawData* aSample) override
{
// The MediaDataDecoder must delete the sample when we're finished
// with it, so the OutputEvent stores it in an nsAutoPtr and deletes

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

@ -6,6 +6,7 @@
#include "MP4Reader.h"
#include "MP4Stream.h"
#include "MediaData.h"
#include "MediaResource.h"
#include "nsPrintfCString.h"
#include "nsSize.h"
@ -70,7 +71,7 @@ TrackTypeToStr(TrackType aTrack)
#endif
bool
AccumulateSPSTelemetry(const ByteBuffer* aExtradata)
AccumulateSPSTelemetry(const DataBuffer* aExtradata)
{
SPSData spsdata;
if (H264::DecodeSPSFromExtraData(aExtradata, spsdata)) {
@ -778,16 +779,16 @@ MP4Reader::Update(TrackType aTrack)
decoder.mIsFlushing);
if (needInput) {
nsAutoPtr<MediaSample> sample(PopSample(aTrack));
nsRefPtr<MediaRawData> sample(PopSample(aTrack));
// Collect telemetry from h264 Annex B SPS.
if (!mFoundSPSForTelemetry && sample && AnnexB::HasSPS(sample->mMp4Sample)) {
nsRefPtr<ByteBuffer> extradata = AnnexB::ExtractExtraData(sample->mMp4Sample);
if (!mFoundSPSForTelemetry && sample && AnnexB::HasSPS(sample)) {
nsRefPtr<DataBuffer> extradata = AnnexB::ExtractExtraData(sample);
mFoundSPSForTelemetry = AccumulateSPSTelemetry(extradata);
}
if (sample) {
decoder.mDecoder->Input(sample->mMp4Sample.forget());
decoder.mDecoder->Input(sample);
if (aTrack == kVideo) {
a.mParsed++;
}
@ -831,31 +832,49 @@ MP4Reader::ReturnOutput(MediaData* aData, TrackType aTrack)
}
}
MediaSample*
already_AddRefed<MediaRawData>
MP4Reader::PopSample(TrackType aTrack)
{
MonitorAutoLock mon(mDemuxerMonitor);
return PopSampleLocked(aTrack);
}
MediaSample*
already_AddRefed<MediaRawData>
MP4Reader::PopSampleLocked(TrackType aTrack)
{
mDemuxerMonitor.AssertCurrentThreadOwns();
nsRefPtr<MediaRawData> sample;
switch (aTrack) {
case kAudio:
return InvokeAndRetry(mAudio.mTrackDemuxer.get(), &TrackDemuxer::DemuxSample, mStream, &mDemuxerMonitor);
sample =
InvokeAndRetry(this, &MP4Reader::DemuxAudioSample, mStream, &mDemuxerMonitor);
return sample.forget();
case kVideo:
if (mQueuedVideoSample) {
return mQueuedVideoSample.forget();
}
return InvokeAndRetry(mVideo.mTrackDemuxer.get(), &TrackDemuxer::DemuxSample, mStream, &mDemuxerMonitor);
sample =
InvokeAndRetry(this, &MP4Reader::DemuxVideoSample, mStream, &mDemuxerMonitor);
return sample.forget();
default:
return nullptr;
}
}
nsRefPtr<MediaRawData>
MP4Reader::DemuxAudioSample()
{
nsRefPtr<MediaRawData> sample = mAudio.mTrackDemuxer->DemuxSample();
return sample;
}
nsRefPtr<MediaRawData>
MP4Reader::DemuxVideoSample()
{
nsRefPtr<MediaRawData> sample = mVideo.mTrackDemuxer->DemuxSample();
return sample;
}
size_t
MP4Reader::SizeOfVideoQueueInFrames()
{
@ -1007,7 +1026,7 @@ MP4Reader::SkipVideoDemuxToNextKeyFrame(int64_t aTimeThreshold, uint32_t& parsed
// Loop until we reach the next keyframe after the threshold.
while (true) {
nsAutoPtr<MediaSample> compressed(PopSample(kVideo));
nsRefPtr<MediaRawData> compressed(PopSample(kVideo));
if (!compressed) {
// EOS, or error. This code assumes EOS, which may or may not be right.
MonitorAutoLock mon(mVideo.mMonitor);
@ -1015,8 +1034,8 @@ MP4Reader::SkipVideoDemuxToNextKeyFrame(int64_t aTimeThreshold, uint32_t& parsed
return false;
}
parsed++;
if (!compressed->mMp4Sample->is_sync_point ||
compressed->mMp4Sample->composition_timestamp < aTimeThreshold) {
if (!compressed->mKeyframe ||
compressed->mTime < aTimeThreshold) {
continue;
}
mQueuedVideoSample = compressed;
@ -1043,7 +1062,7 @@ MP4Reader::Seek(int64_t aTime, int64_t aEndTime)
mVideo.mTrackDemuxer->Seek(seekTime);
mQueuedVideoSample = PopSampleLocked(kVideo);
if (mQueuedVideoSample) {
seekTime = mQueuedVideoSample->mMp4Sample->composition_timestamp;
seekTime = mQueuedVideoSample->mTime;
}
}
if (mDemuxer->HasValidAudio()) {

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

@ -23,7 +23,7 @@ namespace dom {
class TimeRanges;
}
typedef std::deque<MediaSample*> MediaSampleQueue;
typedef std::deque<nsRefPtr<MediaRawData>> MediaSampleQueue;
class MP4Stream;
@ -121,8 +121,8 @@ private:
// Blocks until the demuxer produces an sample of specified type.
// Returns nullptr on error on EOS. Caller must delete sample.
MediaSample* PopSample(mp4_demuxer::TrackType aTrack);
MediaSample* PopSampleLocked(mp4_demuxer::TrackType aTrack);
already_AddRefed<MediaRawData> PopSample(mp4_demuxer::TrackType aTrack);
already_AddRefed<MediaRawData> PopSampleLocked(mp4_demuxer::TrackType aTrack);
bool SkipVideoDemuxToNextKeyFrame(int64_t aTimeThreshold, uint32_t& parsed);
@ -260,7 +260,7 @@ private:
// Queued samples extracted by the demuxer, but not yet sent to the platform
// decoder.
nsAutoPtr<MediaSample> mQueuedVideoSample;
nsRefPtr<MediaRawData> mQueuedVideoSample;
// Returns true when the decoder for this track needs input.
// aDecoder.mMonitor must be locked.
@ -276,6 +276,10 @@ private:
layers::LayersBackend mLayersBackendType;
// For use with InvokeAndRetry as an already_refed can't be converted to bool
nsRefPtr<MediaRawData> DemuxVideoSample();
nsRefPtr<MediaRawData> DemuxAudioSample();
// True if we've read the streams' metadata.
bool mDemuxerInitialized;

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

@ -17,12 +17,13 @@ namespace mp4_demuxer {
class TrackConfig;
class VideoDecoderConfig;
class AudioDecoderConfig;
class MP4Sample;
}
class nsIThreadPool;
namespace mozilla {
class MediaRawData;
class DataBuffer;
namespace layers {
class ImageContainer;
@ -219,10 +220,8 @@ public:
// be done here so that it can be canceled by calling Shutdown()!
virtual nsresult Init() = 0;
// Inserts a sample into the decoder's decode pipeline. The decoder must
// delete the sample once its been decoded. If Input() returns an error,
// aSample will be deleted by the caller.
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) = 0;
// Inserts a sample into the decoder's decode pipeline.
virtual nsresult Input(MediaRawData* aSample) = 0;
// Causes all samples in the decoding pipeline to be discarded. When
// this function returns, the decoder must be ready to accept new input

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

@ -218,7 +218,7 @@ SharedDecoderProxy::Init()
}
nsresult
SharedDecoderProxy::Input(mp4_demuxer::MP4Sample* aSample)
SharedDecoderProxy::Input(MediaRawData* aSample)
{
if (mManager->mActiveProxy != this) {
mManager->Select(this);

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

@ -69,7 +69,7 @@ public:
virtual ~SharedDecoderProxy();
virtual nsresult Init() override;
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) override;
virtual nsresult Input(MediaRawData* aSample) override;
virtual nsresult Flush() override;
virtual nsresult Drain() override;
virtual nsresult Shutdown() override;

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

@ -62,7 +62,7 @@ public:
mGLContext = nullptr;
}
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) override {
virtual nsresult Input(MediaRawData* aSample) override {
return MediaCodecDataDecoder::Input(aSample);
}
@ -397,7 +397,7 @@ void MediaCodecDataDecoder::DecoderLoop()
bool waitingEOF = false;
AutoLocalJNIFrame frame(GetJNIForThread(), 1);
mp4_demuxer::MP4Sample* sample = nullptr;
nsRefPtr<MediaRawData> sample;
MediaFormat::LocalRef outputFormat(frame.GetEnv());
nsresult res;
@ -464,7 +464,7 @@ void MediaCodecDataDecoder::DecoderLoop()
void* directBuffer = frame.GetEnv()->GetDirectBufferAddress(buffer.Get());
MOZ_ASSERT(frame.GetEnv()->GetDirectBufferCapacity(buffer.Get()) >= sample->size,
MOZ_ASSERT(frame.GetEnv()->GetDirectBufferCapacity(buffer.Get()) >= sample->mSize,
"Decoder buffer is not large enough for sample");
{
@ -473,14 +473,13 @@ void MediaCodecDataDecoder::DecoderLoop()
mQueue.pop();
}
PodCopy((uint8_t*)directBuffer, sample->data, sample->size);
PodCopy((uint8_t*)directBuffer, sample->mData, sample->mSize);
res = mDecoder->QueueInputBuffer(inputIndex, 0, sample->size,
sample->composition_timestamp, 0);
res = mDecoder->QueueInputBuffer(inputIndex, 0, sample->mSize,
sample->mTime, 0);
HANDLE_DECODER_ERROR();
mDurations.push(sample->duration);
delete sample;
mDurations.push(sample->mDuration);
sample = nullptr;
outputDone = false;
}
@ -572,7 +571,6 @@ void MediaCodecDataDecoder::ClearQueue()
{
mMonitor.AssertCurrentThreadOwns();
while (!mQueue.empty()) {
delete mQueue.front();
mQueue.pop();
}
while (!mDurations.empty()) {
@ -580,7 +578,7 @@ void MediaCodecDataDecoder::ClearQueue()
}
}
nsresult MediaCodecDataDecoder::Input(mp4_demuxer::MP4Sample* aSample) {
nsresult MediaCodecDataDecoder::Input(MediaRawData* aSample) {
MonitorAutoLock lock(mMonitor);
mQueue.push(aSample);
lock.NotifyAll();

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

@ -15,7 +15,7 @@
namespace mozilla {
typedef std::queue<mp4_demuxer::MP4Sample*> SampleQueue;
typedef std::queue<nsRefPtr<MediaRawData>> SampleQueue;
class AndroidDecoderModule : public PlatformDecoderModule {
public:
@ -55,7 +55,7 @@ public:
virtual nsresult Flush() override;
virtual nsresult Drain() override;
virtual nsresult Shutdown() override;
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample);
virtual nsresult Input(MediaRawData* aSample);
protected:
friend class AndroidDecoderModule;

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

@ -66,21 +66,21 @@ AppleATDecoder::Init()
}
nsresult
AppleATDecoder::Input(mp4_demuxer::MP4Sample* aSample)
AppleATDecoder::Input(MediaRawData* aSample)
{
LOG("mp4 input sample %p %lld us %lld pts%s %llu bytes audio",
aSample,
aSample->duration,
aSample->composition_timestamp,
aSample->is_sync_point ? " keyframe" : "",
(unsigned long long)aSample->size);
aSample->mDuration,
aSample->mTime,
aSample->mKeyframe ? " keyframe" : "",
(unsigned long long)aSample->mSize);
// Queue a task to perform the actual decoding on a separate thread.
mTaskQueue->Dispatch(
NS_NewRunnableMethodWithArg<nsAutoPtr<mp4_demuxer::MP4Sample>>(
NS_NewRunnableMethodWithArg<nsRefPtr<MediaRawData>>(
this,
&AppleATDecoder::SubmitSample,
nsAutoPtr<mp4_demuxer::MP4Sample>(aSample)));
nsRefPtr<MediaRawData>(aSample)));
return NS_OK;
}
@ -173,7 +173,7 @@ _PassthroughInputDataCallback(AudioConverterRef aAudioConverter,
}
void
AppleATDecoder::SubmitSample(nsAutoPtr<mp4_demuxer::MP4Sample> aSample)
AppleATDecoder::SubmitSample(MediaRawData* aSample)
{
nsresult rv = NS_OK;
if (!mConverter) {
@ -203,7 +203,7 @@ AppleATDecoder::SubmitSample(nsAutoPtr<mp4_demuxer::MP4Sample> aSample)
}
nsresult
AppleATDecoder::DecodeSample(mp4_demuxer::MP4Sample* aSample)
AppleATDecoder::DecodeSample(MediaRawData* aSample)
{
// Array containing the queued decoded audio frames, about to be output.
nsTArray<AudioDataValue> outputData;
@ -220,7 +220,7 @@ AppleATDecoder::DecodeSample(mp4_demuxer::MP4Sample* aSample)
// This API insists on having packets spoon-fed to it from a callback.
// This structure exists only to pass our state.
PassthroughUserData userData =
{ channels, (UInt32)aSample->size, aSample->data };
{ channels, (UInt32)aSample->mSize, aSample->mData };
// Decompressed audio buffer
nsAutoArrayPtr<AudioDataValue> decoded(new AudioDataValue[maxDecodedSamples]);
@ -272,14 +272,14 @@ AppleATDecoder::DecodeSample(mp4_demuxer::MP4Sample* aSample)
#ifdef LOG_SAMPLE_DECODE
LOG("pushed audio at time %lfs; duration %lfs\n",
(double)aSample->composition_timestamp / USECS_PER_S,
(double)aSample->mTime / USECS_PER_S,
(double)duration.value() / USECS_PER_S);
#endif
nsAutoArrayPtr<AudioDataValue> data(new AudioDataValue[outputData.Length()]);
PodCopy(data.get(), &outputData[0], outputData.Length());
nsRefPtr<AudioData> audio = new AudioData(aSample->byte_offset,
aSample->composition_timestamp,
nsRefPtr<AudioData> audio = new AudioData(aSample->mOffset,
aSample->mTime,
duration.value(),
numFrames,
data.forget(),
@ -364,7 +364,7 @@ AppleATDecoder::GetInputAudioDescription(AudioStreamBasicDescription& aDesc,
}
nsresult
AppleATDecoder::SetupDecoder(mp4_demuxer::MP4Sample* aSample)
AppleATDecoder::SetupDecoder(MediaRawData* aSample)
{
if (mFormatID == kAudioFormatMPEG4AAC &&
mConfig.extended_profile == 2) {
@ -461,10 +461,10 @@ _SampleCallback(void* aSBR,
}
nsresult
AppleATDecoder::GetImplicitAACMagicCookie(const mp4_demuxer::MP4Sample* aSample)
AppleATDecoder::GetImplicitAACMagicCookie(const MediaRawData* aSample)
{
// Prepend ADTS header to AAC audio.
nsAutoPtr<mp4_demuxer::MP4Sample> adtssample(aSample->Clone());
nsRefPtr<MediaRawData> adtssample(aSample->Clone());
if (!adtssample) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -490,8 +490,8 @@ AppleATDecoder::GetImplicitAACMagicCookie(const mp4_demuxer::MP4Sample* aSample)
}
OSStatus status = AudioFileStreamParseBytes(mStream,
adtssample->size,
adtssample->data,
adtssample->mSize,
adtssample->mData,
0 /* discontinuity */);
if (status) {
NS_WARNING("Couldn't parse sample");

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

@ -26,7 +26,7 @@ public:
virtual ~AppleATDecoder();
virtual nsresult Init() override;
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) override;
virtual nsresult Input(MediaRawData* aSample) override;
virtual nsresult Flush() override;
virtual nsresult Drain() override;
virtual nsresult Shutdown() override;
@ -47,16 +47,16 @@ private:
AudioStreamBasicDescription mOutputFormat;
UInt32 mFormatID;
AudioFileStreamID mStream;
nsTArray<nsAutoPtr<mp4_demuxer::MP4Sample>> mQueuedSamples;
nsTArray<nsRefPtr<MediaRawData>> mQueuedSamples;
void SubmitSample(nsAutoPtr<mp4_demuxer::MP4Sample> aSample);
nsresult DecodeSample(mp4_demuxer::MP4Sample* aSample);
void SubmitSample(MediaRawData* aSample);
nsresult DecodeSample(MediaRawData* aSample);
nsresult GetInputAudioDescription(AudioStreamBasicDescription& aDesc,
const nsTArray<uint8_t>& aExtraData);
// Setup AudioConverter once all information required has been gathered.
// Will return NS_ERROR_NOT_INITIALIZED if more data is required.
nsresult SetupDecoder(mp4_demuxer::MP4Sample* aSample);
nsresult GetImplicitAACMagicCookie(const mp4_demuxer::MP4Sample* aSample);
nsresult SetupDecoder(MediaRawData* aSample);
nsresult GetImplicitAACMagicCookie(const MediaRawData* aSample);
};
} // namespace mozilla

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

@ -104,20 +104,20 @@ AppleVDADecoder::Shutdown()
}
nsresult
AppleVDADecoder::Input(mp4_demuxer::MP4Sample* aSample)
AppleVDADecoder::Input(MediaRawData* aSample)
{
LOG("mp4 input sample %p pts %lld duration %lld us%s %d bytes",
aSample,
aSample->composition_timestamp,
aSample->duration,
aSample->is_sync_point ? " keyframe" : "",
aSample->size);
aSample->mTime,
aSample->mDuration,
aSample->mKeyframe ? " keyframe" : "",
aSample->mSize);
mTaskQueue->Dispatch(
NS_NewRunnableMethodWithArg<nsAutoPtr<mp4_demuxer::MP4Sample>>(
NS_NewRunnableMethodWithArg<nsRefPtr<MediaRawData>>(
this,
&AppleVDADecoder::SubmitFrame,
nsAutoPtr<mp4_demuxer::MP4Sample>(aSample)));
nsRefPtr<MediaRawData>(aSample)));
return NS_OK;
}
@ -224,7 +224,7 @@ PlatformCallback(void* decompressionOutputRefCon,
}
AppleVDADecoder::AppleFrameRef*
AppleVDADecoder::CreateAppleFrameRef(const mp4_demuxer::MP4Sample* aSample)
AppleVDADecoder::CreateAppleFrameRef(const MediaRawData* aSample)
{
MOZ_ASSERT(aSample);
return new AppleFrameRef(*aSample);
@ -307,10 +307,10 @@ AppleVDADecoder::OutputFrame(CVPixelBufferRef aImage,
}
nsresult
AppleVDADecoder::SubmitFrame(mp4_demuxer::MP4Sample* aSample)
AppleVDADecoder::SubmitFrame(MediaRawData* aSample)
{
AutoCFRelease<CFDataRef> block =
CFDataCreate(kCFAllocatorDefault, aSample->data, aSample->size);
CFDataCreate(kCFAllocatorDefault, aSample->mData, aSample->mSize);
if (!block) {
NS_ERROR("Couldn't create CFData");
return NS_ERROR_FAILURE;
@ -319,20 +319,20 @@ AppleVDADecoder::SubmitFrame(mp4_demuxer::MP4Sample* aSample)
AutoCFRelease<CFNumberRef> pts =
CFNumberCreate(kCFAllocatorDefault,
kCFNumberSInt64Type,
&aSample->composition_timestamp);
&aSample->mTime);
AutoCFRelease<CFNumberRef> dts =
CFNumberCreate(kCFAllocatorDefault,
kCFNumberSInt64Type,
&aSample->decode_timestamp);
&aSample->mTimecode);
AutoCFRelease<CFNumberRef> duration =
CFNumberCreate(kCFAllocatorDefault,
kCFNumberSInt64Type,
&aSample->duration);
&aSample->mDuration);
AutoCFRelease<CFNumberRef> byte_offset =
CFNumberCreate(kCFAllocatorDefault,
kCFNumberSInt64Type,
&aSample->byte_offset);
char keyframe = aSample->is_sync_point ? 1 : 0;
&aSample->mOffset);
char keyframe = aSample->mKeyframe ? 1 : 0;
AutoCFRelease<CFNumberRef> cfkeyframe =
CFNumberCreate(kCFAllocatorDefault,
kCFNumberSInt8Type,

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

@ -34,12 +34,12 @@ public:
int64_t byte_offset;
bool is_sync_point;
explicit AppleFrameRef(const mp4_demuxer::MP4Sample& aSample)
: decode_timestamp(aSample.decode_timestamp)
, composition_timestamp(aSample.composition_timestamp)
, duration(aSample.duration)
, byte_offset(aSample.byte_offset)
, is_sync_point(aSample.is_sync_point)
explicit AppleFrameRef(const MediaRawData& aSample)
: decode_timestamp(aSample.mTimecode)
, composition_timestamp(aSample.mTime)
, duration(aSample.mDuration)
, byte_offset(aSample.mOffset)
, is_sync_point(aSample.mKeyframe)
{
}
@ -48,11 +48,11 @@ public:
Microseconds aDuration,
int64_t aByte_offset,
bool aIs_sync_point)
: decode_timestamp(aDts)
, composition_timestamp(aPts)
, duration(aDuration)
, byte_offset(aByte_offset)
, is_sync_point(aIs_sync_point)
: decode_timestamp(aDts)
, composition_timestamp(aPts)
, duration(aDuration)
, byte_offset(aByte_offset)
, is_sync_point(aIs_sync_point)
{
}
};
@ -71,7 +71,7 @@ public:
layers::ImageContainer* aImageContainer);
virtual ~AppleVDADecoder();
virtual nsresult Init() override;
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) override;
virtual nsresult Input(MediaRawData* aSample) override;
virtual nsresult Flush() override;
virtual nsresult Drain() override;
virtual nsresult Shutdown() override;
@ -84,12 +84,12 @@ public:
nsAutoPtr<AppleFrameRef> aFrameRef);
protected:
AppleFrameRef* CreateAppleFrameRef(const mp4_demuxer::MP4Sample* aSample);
AppleFrameRef* CreateAppleFrameRef(const MediaRawData* aSample);
void DrainReorderedFrames();
void ClearReorderedFrames();
CFDictionaryRef CreateOutputConfiguration();
nsRefPtr<mp4_demuxer::ByteBuffer> mExtraData;
nsRefPtr<DataBuffer> mExtraData;
nsRefPtr<FlushableMediaTaskQueue> mTaskQueue;
MediaDataDecoderCallback* mCallback;
nsRefPtr<layers::ImageContainer> mImageContainer;
@ -105,7 +105,7 @@ private:
bool mIs106;
// Method to pass a frame to VideoToolbox for decoding.
nsresult SubmitFrame(mp4_demuxer::MP4Sample* aSample);
nsresult SubmitFrame(MediaRawData* aSample);
// Method to set up the decompression session.
nsresult InitializeSession();
CFDictionaryRef CreateDecoderSpecification();

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

@ -10,7 +10,6 @@
#include "AppleUtils.h"
#include "AppleVTDecoder.h"
#include "AppleVTLinker.h"
#include "mp4_demuxer/DecoderData.h"
#include "mp4_demuxer/H264.h"
#include "MediaData.h"
#include "MacIOSurfaceImage.h"
@ -82,14 +81,14 @@ AppleVTDecoder::Shutdown()
}
nsresult
AppleVTDecoder::Input(mp4_demuxer::MP4Sample* aSample)
AppleVTDecoder::Input(MediaRawData* aSample)
{
LOG("mp4 input sample %p pts %lld duration %lld us%s %d bytes",
aSample,
aSample->composition_timestamp,
aSample->duration,
aSample->is_sync_point ? " keyframe" : "",
aSample->size);
aSample->mTime,
aSample->mDuration,
aSample->mKeyframe ? " keyframe" : "",
aSample->mSize);
#ifdef LOG_MEDIA_SHA1
SHA1Sum hash;
@ -104,10 +103,10 @@ AppleVTDecoder::Input(mp4_demuxer::MP4Sample* aSample)
#endif // LOG_MEDIA_SHA1
mTaskQueue->Dispatch(
NS_NewRunnableMethodWithArg<nsAutoPtr<mp4_demuxer::MP4Sample>>(
NS_NewRunnableMethodWithArg<nsRefPtr<MediaRawData>>(
this,
&AppleVTDecoder::SubmitFrame,
nsAutoPtr<mp4_demuxer::MP4Sample>(aSample)));
nsRefPtr<MediaRawData>(aSample)));
return NS_OK;
}
@ -193,21 +192,21 @@ AppleVTDecoder::WaitForAsynchronousFrames()
// Helper to fill in a timestamp structure.
static CMSampleTimingInfo
TimingInfoFromSample(mp4_demuxer::MP4Sample* aSample)
TimingInfoFromSample(MediaRawData* aSample)
{
CMSampleTimingInfo timestamp;
timestamp.duration = CMTimeMake(aSample->duration, USECS_PER_S);
timestamp.duration = CMTimeMake(aSample->mDuration, USECS_PER_S);
timestamp.presentationTimeStamp =
CMTimeMake(aSample->composition_timestamp, USECS_PER_S);
CMTimeMake(aSample->mTime, USECS_PER_S);
timestamp.decodeTimeStamp =
CMTimeMake(aSample->decode_timestamp, USECS_PER_S);
CMTimeMake(aSample->mTimecode, USECS_PER_S);
return timestamp;
}
nsresult
AppleVTDecoder::SubmitFrame(mp4_demuxer::MP4Sample* aSample)
AppleVTDecoder::SubmitFrame(MediaRawData* aSample)
{
// For some reason this gives me a double-free error with stagefright.
AutoCFRelease<CMBlockBufferRef> block = nullptr;
@ -219,15 +218,15 @@ AppleVTDecoder::SubmitFrame(mp4_demuxer::MP4Sample* aSample)
// a custom block source which reuses the aSample buffer.
// But note that there may be a problem keeping the samples
// alive over multiple frames.
rv = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault // Struct allocator.
,aSample->data
,aSample->size
,kCFAllocatorNull // Block allocator.
,NULL // Block source.
,0 // Data offset.
,aSample->size
,false
,block.receive());
rv = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault, // Struct allocator.
const_cast<uint8_t*>(aSample->mData),
aSample->mSize,
kCFAllocatorNull, // Block allocator.
NULL, // Block source.
0, // Data offset.
aSample->mSize,
false,
block.receive());
if (rv != noErr) {
NS_ERROR("Couldn't create CMBlockBuffer");
return NS_ERROR_FAILURE;

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

@ -21,7 +21,7 @@ public:
layers::ImageContainer* aImageContainer);
virtual ~AppleVTDecoder();
virtual nsresult Init() override;
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) override;
virtual nsresult Input(MediaRawData* aSample) override;
virtual nsresult Flush() override;
virtual nsresult Drain() override;
virtual nsresult Shutdown() override;
@ -35,7 +35,7 @@ private:
VTDecompressionSessionRef mSession;
// Method to pass a frame to VideoToolbox for decoding.
nsresult SubmitFrame(mp4_demuxer::MP4Sample* aSample);
nsresult SubmitFrame(MediaRawData* aSample);
// Method to set up the decompression session.
nsresult InitializeSession();
nsresult WaitForAsynchronousFrames();

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

@ -12,11 +12,11 @@
#include "mozilla/CDMProxy.h"
#include "mozilla/unused.h"
#include "nsServiceManagerUtils.h"
#include "mp4_demuxer/DecoderData.h"
namespace mozilla {
class EMEDecryptor : public MediaDataDecoder {
typedef mp4_demuxer::MP4Sample MP4Sample;
public:
@ -49,12 +49,13 @@ public:
, mTaskQueue(aTaskQueue)
{}
virtual void Decrypted(GMPErr aResult,
mp4_demuxer::MP4Sample* aSample) override {
MediaRawData* aSample) override {
if (aResult == GMPNoKeyErr) {
RefPtr<nsIRunnable> task;
task = NS_NewRunnableMethodWithArg<MP4Sample*>(mDecryptor,
&EMEDecryptor::Input,
aSample);
task = NS_NewRunnableMethodWithArg<nsRefPtr<MediaRawData>>(
mDecryptor,
&EMEDecryptor::Input,
nsRefPtr<MediaRawData>(aSample));
mTaskQueue->Dispatch(task.forget());
} else if (GMP_FAILED(aResult)) {
if (mDecryptor->mCallback) {
@ -63,9 +64,10 @@ public:
MOZ_ASSERT(!aSample);
} else {
RefPtr<nsIRunnable> task;
task = NS_NewRunnableMethodWithArg<MP4Sample*>(mDecryptor,
&EMEDecryptor::Decrypted,
aSample);
task = NS_NewRunnableMethodWithArg<nsRefPtr<MediaRawData>>(
mDecryptor,
&EMEDecryptor::Decrypted,
nsRefPtr<MediaRawData>(aSample));
mTaskQueue->Dispatch(task.forget());
}
mTaskQueue = nullptr;
@ -76,7 +78,7 @@ public:
nsRefPtr<FlushableMediaTaskQueue> mTaskQueue;
};
virtual nsresult Input(MP4Sample* aSample) override {
virtual nsresult Input(MediaRawData* aSample) override {
MOZ_ASSERT(!mIsShutdown);
// We run the PDM on its own task queue. We can't run it on the decode
// task queue, because that calls into Input() in a loop and waits until
@ -89,20 +91,20 @@ public:
return NS_OK;
}
mProxy->GetSessionIdsForKeyId(aSample->crypto.key,
aSample->crypto.session_ids);
mProxy->GetSessionIdsForKeyId(aSample->mCrypto.key,
aSample->mCrypto.session_ids);
mProxy->Decrypt(aSample, new DeliverDecrypted(this, mTaskQueue));
return NS_OK;
}
void Decrypted(mp4_demuxer::MP4Sample* aSample) {
void Decrypted(MediaRawData* aSample) {
MOZ_ASSERT(!mIsShutdown);
nsresult rv = mTaskQueue->Dispatch(
NS_NewRunnableMethodWithArg<mp4_demuxer::MP4Sample*>(
NS_NewRunnableMethodWithArg<nsRefPtr<MediaRawData>>(
mDecoder,
&MediaDataDecoder::Input,
aSample));
nsRefPtr<MediaRawData>(aSample)));
unused << NS_WARN_IF(NS_FAILED(rv));
}
@ -169,7 +171,7 @@ public:
{
}
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) override;
virtual nsresult Input(MediaRawData* aSample) override;
virtual nsresult Shutdown() override;
private:
@ -178,14 +180,14 @@ private:
};
nsresult
EMEMediaDataDecoderProxy::Input(mp4_demuxer::MP4Sample* aSample)
EMEMediaDataDecoderProxy::Input(MediaRawData* aSample)
{
if (mSamplesWaitingForKey->WaitIfKeyNotUsable(aSample)) {
return NS_OK;
}
mProxy->GetSessionIdsForKeyId(aSample->crypto.key,
aSample->crypto.session_ids);
mProxy->GetSessionIdsForKeyId(aSample->mCrypto.key,
aSample->mCrypto.session_ids);
return MediaDataDecoderProxy::Input(aSample);
}

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

@ -7,6 +7,7 @@
#include "EMEVideoDecoder.h"
#include "GMPVideoEncodedFrameImpl.h"
#include "mozilla/CDMProxy.h"
#include "MediaData.h"
namespace mozilla {
@ -36,11 +37,11 @@ EMEVideoDecoder::GetNodeId()
}
GMPUnique<GMPVideoEncodedFrame>::Ptr
EMEVideoDecoder::CreateFrame(mp4_demuxer::MP4Sample* aSample)
EMEVideoDecoder::CreateFrame(MediaRawData* aSample)
{
GMPUnique<GMPVideoEncodedFrame>::Ptr frame = GMPVideoDecoder::CreateFrame(aSample);
if (frame && aSample->crypto.valid) {
static_cast<gmp::GMPVideoEncodedFrameImpl*>(frame.get())->InitCrypto(aSample->crypto);
if (frame && aSample->mCrypto.valid) {
static_cast<gmp::GMPVideoEncodedFrameImpl*>(frame.get())->InitCrypto(aSample->mCrypto);
}
return frame;
}

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

@ -44,7 +44,7 @@ public:
private:
virtual void InitTags(nsTArray<nsCString>& aTags) override;
virtual nsCString GetNodeId() override;
virtual GMPUnique<GMPVideoEncodedFrame>::Ptr CreateFrame(mp4_demuxer::MP4Sample* aSample) override;
virtual GMPUnique<GMPVideoEncodedFrame>::Ptr CreateFrame(MediaRawData* aSample) override;
nsRefPtr<CDMProxy> mProxy;
};

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

@ -7,6 +7,7 @@
#include "SamplesWaitingForKey.h"
#include "mozilla/CDMProxy.h"
#include "mozilla/CDMCaps.h"
#include "MediaData.h"
namespace mozilla {
@ -25,19 +26,19 @@ SamplesWaitingForKey::~SamplesWaitingForKey()
}
bool
SamplesWaitingForKey::WaitIfKeyNotUsable(MP4Sample* aSample)
SamplesWaitingForKey::WaitIfKeyNotUsable(MediaRawData* aSample)
{
if (!aSample || !aSample->crypto.valid || !mProxy) {
if (!aSample || !aSample->mCrypto.valid || !mProxy) {
return false;
}
CDMCaps::AutoLock caps(mProxy->Capabilites());
const auto& keyid = aSample->crypto.key;
const auto& keyid = aSample->mCrypto.key;
if (!caps.IsKeyUsable(keyid)) {
{
MutexAutoLock lock(mMutex);
mSamples.AppendElement(aSample);
}
caps.NotifyWhenKeyIdUsable(aSample->crypto.key, this);
caps.NotifyWhenKeyIdUsable(aSample->mCrypto.key, this);
return true;
}
return false;
@ -49,11 +50,11 @@ SamplesWaitingForKey::NotifyUsable(const CencKeyId& aKeyId)
MutexAutoLock lock(mMutex);
size_t i = 0;
while (i < mSamples.Length()) {
if (aKeyId == mSamples[i]->crypto.key) {
if (aKeyId == mSamples[i]->mCrypto.key) {
RefPtr<nsIRunnable> task;
task = NS_NewRunnableMethodWithArg<MP4Sample*>(mDecoder,
task = NS_NewRunnableMethodWithArg<nsRefPtr<MediaRawData>>(mDecoder,
&MediaDataDecoder::Input,
mSamples[i].forget());
nsRefPtr<MediaRawData>(mSamples[i]));
mSamples.RemoveElementAt(i);
mTaskQueue->Dispatch(task.forget());
} else {

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

@ -7,7 +7,6 @@
#ifndef SamplesWaitingForKey_h_
#define SamplesWaitingForKey_h_
#include "mp4_demuxer/DecoderData.h"
#include "MediaTaskQueue.h"
#include "PlatformDecoderModule.h"
@ -20,7 +19,6 @@ class CDMProxy;
// Encapsulates the task of waiting for the CDMProxy to have the necessary
// keys to decypt a given sample.
class SamplesWaitingForKey {
typedef mp4_demuxer::MP4Sample MP4Sample;
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SamplesWaitingForKey)
@ -33,7 +31,7 @@ public:
// Will callback MediaDataDecoder::Input(aSample) on mDecoder once the
// sample is ready to be decrypted. The order of input samples is
// preserved.
bool WaitIfKeyNotUsable(MP4Sample* aSample);
bool WaitIfKeyNotUsable(MediaRawData* aSample);
void NotifyUsable(const CencKeyId& aKeyId);
@ -49,7 +47,7 @@ private:
nsRefPtr<MediaDataDecoder> mDecoder;
nsRefPtr<MediaTaskQueue> mTaskQueue;
nsRefPtr<CDMProxy> mProxy;
nsTArray<nsAutoPtr<MP4Sample>> mSamples;
nsTArray<nsRefPtr<MediaRawData>> mSamples;
};
} // namespace mozilla

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

@ -12,8 +12,6 @@
#define MAX_CHANNELS 16
typedef mp4_demuxer::MP4Sample MP4Sample;
namespace mozilla
{
@ -83,19 +81,13 @@ CopyAndPackAudio(AVFrame* aFrame, uint32_t aNumChannels, uint32_t aNumAFrames)
}
void
FFmpegAudioDecoder<LIBAV_VER>::DecodePacket(MP4Sample* aSample)
FFmpegAudioDecoder<LIBAV_VER>::DecodePacket(MediaRawData* aSample)
{
AVPacket packet;
av_init_packet(&packet);
if (!aSample->Pad(FF_INPUT_BUFFER_PADDING_SIZE)) {
NS_WARNING("FFmpeg audio decoder failed to allocate sample.");
mCallback->Error();
return;
}
packet.data = aSample->data;
packet.size = aSample->size;
packet.data = const_cast<uint8_t*>(aSample->mData);
packet.size = aSample->mSize;
if (!PrepareFrame()) {
NS_WARNING("FFmpeg audio decoder failed to allocate frame.");
@ -103,8 +95,8 @@ FFmpegAudioDecoder<LIBAV_VER>::DecodePacket(MP4Sample* aSample)
return;
}
int64_t samplePosition = aSample->byte_offset;
Microseconds pts = aSample->composition_timestamp;
int64_t samplePosition = aSample->mOffset;
Microseconds pts = aSample->mTime;
while (packet.size > 0) {
int decoded;
@ -153,10 +145,10 @@ FFmpegAudioDecoder<LIBAV_VER>::DecodePacket(MP4Sample* aSample)
}
nsresult
FFmpegAudioDecoder<LIBAV_VER>::Input(MP4Sample* aSample)
FFmpegAudioDecoder<LIBAV_VER>::Input(MediaRawData* aSample)
{
mTaskQueue->Dispatch(NS_NewRunnableMethodWithArg<nsAutoPtr<MP4Sample> >(
this, &FFmpegAudioDecoder::DecodePacket, nsAutoPtr<MP4Sample>(aSample)));
mTaskQueue->Dispatch(NS_NewRunnableMethodWithArg<nsRefPtr<MediaRawData> >(
this, &FFmpegAudioDecoder::DecodePacket, nsRefPtr<MediaRawData>(aSample)));
return NS_OK;
}

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

@ -26,12 +26,12 @@ public:
virtual ~FFmpegAudioDecoder();
virtual nsresult Init() override;
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) override;
virtual nsresult Input(MediaRawData* aSample) override;
virtual nsresult Drain() override;
static AVCodecID GetCodecId(const nsACString& aMimeType);
private:
void DecodePacket(mp4_demuxer::MP4Sample* aSample);
void DecodePacket(MediaRawData* aSample);
MediaDataDecoderCallback* mCallback;
};

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

@ -30,7 +30,7 @@ public:
static bool Link();
virtual nsresult Init() override;
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) override = 0;
virtual nsresult Input(MediaRawData* aSample) override = 0;
virtual nsresult Flush() override;
virtual nsresult Drain() override = 0;
virtual nsresult Shutdown() override;
@ -41,7 +41,7 @@ protected:
FlushableMediaTaskQueue* mTaskQueue;
AVCodecContext* mCodecContext;
AVFrame* mFrame;
nsRefPtr<mp4_demuxer::ByteBuffer> mExtraData;
nsRefPtr<DataBuffer> mExtraData;
private:
static bool sFFmpegInitDone;

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

@ -18,8 +18,6 @@
typedef mozilla::layers::Image Image;
typedef mozilla::layers::PlanarYCbCrImage PlanarYCbCrImage;
typedef mp4_demuxer::MP4Sample MP4Sample;
namespace mozilla
{
@ -50,23 +48,17 @@ FFmpegH264Decoder<LIBAV_VER>::Init()
}
FFmpegH264Decoder<LIBAV_VER>::DecodeResult
FFmpegH264Decoder<LIBAV_VER>::DoDecodeFrame(mp4_demuxer::MP4Sample* aSample)
FFmpegH264Decoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample)
{
AVPacket packet;
av_init_packet(&packet);
if (!aSample->Pad(FF_INPUT_BUFFER_PADDING_SIZE)) {
NS_WARNING("FFmpeg h264 decoder failed to allocate sample.");
mCallback->Error();
return DecodeResult::DECODE_ERROR;
}
packet.data = aSample->data;
packet.size = aSample->size;
packet.dts = aSample->decode_timestamp;
packet.pts = aSample->composition_timestamp;
packet.flags = aSample->is_sync_point ? AV_PKT_FLAG_KEY : 0;
packet.pos = aSample->byte_offset;
packet.data = const_cast<uint8_t*>(aSample->mData);
packet.size = aSample->mSize;
packet.dts = aSample->mTimecode;
packet.pts = aSample->mTime;
packet.flags = aSample->mKeyframe ? AV_PKT_FLAG_KEY : 0;
packet.pos = aSample->mOffset;
if (!PrepareFrame()) {
NS_WARNING("FFmpeg h264 decoder failed to allocate frame.");
@ -112,11 +104,11 @@ FFmpegH264Decoder<LIBAV_VER>::DoDecodeFrame(mp4_demuxer::MP4Sample* aSample)
nsRefPtr<VideoData> v = VideoData::Create(info,
mImageContainer,
aSample->byte_offset,
aSample->mOffset,
mFrame->pkt_pts,
aSample->duration,
aSample->mDuration,
b,
aSample->is_sync_point,
aSample->mKeyframe,
-1,
gfx::IntRect(0, 0, mCodecContext->width, mCodecContext->height));
if (!v) {
@ -131,7 +123,7 @@ FFmpegH264Decoder<LIBAV_VER>::DoDecodeFrame(mp4_demuxer::MP4Sample* aSample)
}
void
FFmpegH264Decoder<LIBAV_VER>::DecodeFrame(mp4_demuxer::MP4Sample* aSample)
FFmpegH264Decoder<LIBAV_VER>::DecodeFrame(MediaRawData* aSample)
{
if (DoDecodeFrame(aSample) != DecodeResult::DECODE_ERROR &&
mTaskQueue->IsEmpty()) {
@ -245,12 +237,12 @@ FFmpegH264Decoder<LIBAV_VER>::AllocateYUV420PVideoBuffer(
}
nsresult
FFmpegH264Decoder<LIBAV_VER>::Input(mp4_demuxer::MP4Sample* aSample)
FFmpegH264Decoder<LIBAV_VER>::Input(MediaRawData* aSample)
{
mTaskQueue->Dispatch(
NS_NewRunnableMethodWithArg<nsAutoPtr<mp4_demuxer::MP4Sample>>(
NS_NewRunnableMethodWithArg<nsRefPtr<MediaRawData>>(
this, &FFmpegH264Decoder<LIBAV_VER>::DecodeFrame,
nsAutoPtr<mp4_demuxer::MP4Sample>(aSample)));
nsRefPtr<MediaRawData>(aSample)));
return NS_OK;
}
@ -258,7 +250,7 @@ FFmpegH264Decoder<LIBAV_VER>::Input(mp4_demuxer::MP4Sample* aSample)
void
FFmpegH264Decoder<LIBAV_VER>::DoDrain()
{
nsAutoPtr<MP4Sample> empty(new MP4Sample());
nsRefPtr<MediaRawData> empty(new MediaRawData());
while (DoDecodeFrame(empty) == DecodeResult::DECODE_FRAME) {
}
mCallback->DrainComplete();

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

@ -37,14 +37,14 @@ public:
virtual ~FFmpegH264Decoder();
virtual nsresult Init() override;
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) override;
virtual nsresult Input(MediaRawData* aSample) override;
virtual nsresult Drain() override;
virtual nsresult Flush() override;
static AVCodecID GetCodecId(const nsACString& aMimeType);
private:
void DecodeFrame(mp4_demuxer::MP4Sample* aSample);
DecodeResult DoDecodeFrame(mp4_demuxer::MP4Sample* aSample);
void DecodeFrame(MediaRawData* aSample);
DecodeResult DoDecodeFrame(MediaRawData* aSample);
void DoDrain();
void OutputDelayedFrames();

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

@ -6,6 +6,7 @@
#include "GMPAudioDecoder.h"
#include "nsServiceManagerUtils.h"
#include "mp4_demuxer/DecoderData.h"
namespace mozilla {
@ -191,17 +192,17 @@ GMPAudioDecoder::Init()
}
nsresult
GMPAudioDecoder::Input(mp4_demuxer::MP4Sample* aSample)
GMPAudioDecoder::Input(MediaRawData* aSample)
{
MOZ_ASSERT(IsOnGMPThread());
nsAutoPtr<mp4_demuxer::MP4Sample> sample(aSample);
nsRefPtr<MediaRawData> sample(aSample);
if (!mGMP) {
mCallback->Error();
return NS_ERROR_FAILURE;
}
mAdapter->SetLastStreamOffset(sample->byte_offset);
mAdapter->SetLastStreamOffset(sample->mOffset);
gmp::GMPAudioSamplesImpl samples(sample, mConfig.channel_count, mConfig.samples_per_second);
nsresult rv = mGMP->Decode(samples);

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

@ -70,7 +70,7 @@ public:
}
virtual nsresult Init() override;
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) override;
virtual nsresult Input(MediaRawData* aSample) override;
virtual nsresult Flush() override;
virtual nsresult Drain() override;
virtual nsresult Shutdown() override;

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

@ -8,6 +8,8 @@
#include "GMPVideoHost.h"
#include "mozilla/Endian.h"
#include "prsystem.h"
#include "MediaData.h"
#include "mp4_demuxer/DecoderData.h"
namespace mozilla {
@ -115,7 +117,7 @@ GMPVideoDecoder::GetNodeId()
}
GMPUnique<GMPVideoEncodedFrame>::Ptr
GMPVideoDecoder::CreateFrame(mp4_demuxer::MP4Sample* aSample)
GMPVideoDecoder::CreateFrame(MediaRawData* aSample)
{
GMPVideoFrame* ftmp = nullptr;
GMPErr err = mHost->CreateFrame(kGMPEncodedVideoFrame, &ftmp);
@ -125,13 +127,13 @@ GMPVideoDecoder::CreateFrame(mp4_demuxer::MP4Sample* aSample)
}
GMPUnique<GMPVideoEncodedFrame>::Ptr frame(static_cast<GMPVideoEncodedFrame*>(ftmp));
err = frame->CreateEmptyFrame(aSample->size);
err = frame->CreateEmptyFrame(aSample->mSize);
if (GMP_FAILED(err)) {
mCallback->Error();
return nullptr;
}
memcpy(frame->Buffer(), aSample->data, frame->Size());
memcpy(frame->Buffer(), aSample->mData, frame->Size());
// Convert 4-byte NAL unit lengths to host-endian 4-byte buffer lengths to
// suit the GMP API.
@ -149,10 +151,10 @@ GMPVideoDecoder::CreateFrame(mp4_demuxer::MP4Sample* aSample)
frame->SetEncodedWidth(mConfig.display_width);
frame->SetEncodedHeight(mConfig.display_height);
frame->SetTimeStamp(aSample->composition_timestamp);
frame->SetTimeStamp(aSample->mTime);
frame->SetCompleteFrame(true);
frame->SetDuration(aSample->duration);
frame->SetFrameType(aSample->is_sync_point ? kGMPKeyFrame : kGMPDeltaFrame);
frame->SetDuration(aSample->mDuration);
frame->SetFrameType(aSample->mKeyframe ? kGMPKeyFrame : kGMPDeltaFrame);
return frame;
}
@ -235,17 +237,17 @@ GMPVideoDecoder::Init()
}
nsresult
GMPVideoDecoder::Input(mp4_demuxer::MP4Sample* aSample)
GMPVideoDecoder::Input(MediaRawData* aSample)
{
MOZ_ASSERT(IsOnGMPThread());
nsAutoPtr<mp4_demuxer::MP4Sample> sample(aSample);
nsRefPtr<MediaRawData> sample(aSample);
if (!mGMP) {
mCallback->Error();
return NS_ERROR_FAILURE;
}
mAdapter->SetLastStreamOffset(sample->byte_offset);
mAdapter->SetLastStreamOffset(sample->mOffset);
GMPUnique<GMPVideoEncodedFrame>::Ptr frame = CreateFrame(sample);
nsTArray<uint8_t> info; // No codec specific per-frame info to pass.

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

@ -85,7 +85,7 @@ public:
}
virtual nsresult Init() override;
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) override;
virtual nsresult Input(MediaRawData* aSample) override;
virtual nsresult Flush() override;
virtual nsresult Drain() override;
virtual nsresult Shutdown() override;
@ -93,7 +93,7 @@ public:
protected:
virtual void InitTags(nsTArray<nsCString>& aTags);
virtual nsCString GetNodeId();
virtual GMPUnique<GMPVideoEncodedFrame>::Ptr CreateFrame(mp4_demuxer::MP4Sample* aSample);
virtual GMPUnique<GMPVideoEncodedFrame>::Ptr CreateFrame(MediaRawData* aSample);
private:
class GMPInitDoneRunnable : public nsRunnable

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

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MediaDataDecoderProxy.h"
#include "MediaData.h"
namespace mozilla {
@ -33,7 +34,7 @@ MediaDataDecoderProxy::Init()
}
nsresult
MediaDataDecoderProxy::Input(mp4_demuxer::MP4Sample* aSample)
MediaDataDecoderProxy::Input(MediaRawData* aSample)
{
MOZ_ASSERT(!IsOnProxyThread());
MOZ_ASSERT(!mIsShutdown);

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

@ -8,8 +8,6 @@
#define MediaDataDecoderProxy_h_
#include "PlatformDecoderModule.h"
#include "mp4_demuxer/DecoderData.h"
#include "nsAutoPtr.h"
#include "nsRefPtr.h"
#include "nsThreadUtils.h"
#include "nscore.h"
@ -19,19 +17,19 @@ namespace mozilla {
class InputTask : public nsRunnable {
public:
InputTask(MediaDataDecoder* aDecoder,
mp4_demuxer::MP4Sample* aSample)
MediaRawData* aSample)
: mDecoder(aDecoder)
, mSample(aSample)
{}
NS_IMETHOD Run() {
mDecoder->Input(mSample.forget());
mDecoder->Input(mSample);
return NS_OK;
}
private:
nsRefPtr<MediaDataDecoder> mDecoder;
nsAutoPtr<mp4_demuxer::MP4Sample> mSample;
nsRefPtr<MediaRawData> mSample;
};
class InitTask : public nsRunnable {
@ -88,7 +86,7 @@ class MediaDataDecoderProxy;
class MediaDataDecoderCallbackProxy : public MediaDataDecoderCallback {
public:
explicit MediaDataDecoderCallbackProxy(MediaDataDecoderProxy* aProxyDecoder, MediaDataDecoderCallback* aCallback)
MediaDataDecoderCallbackProxy(MediaDataDecoderProxy* aProxyDecoder, MediaDataDecoderCallback* aCallback)
: mProxyDecoder(aProxyDecoder)
, mProxyCallback(aCallback)
{
@ -157,7 +155,7 @@ public:
// asynchronously and responded to via the MediaDataDecoderCallback.
// Note: the nsresults returned by the proxied decoder are lost.
virtual nsresult Init() override;
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) override;
virtual nsresult Input(MediaRawData* aSample) override;
virtual nsresult Flush() override;
virtual nsresult Drain() override;
virtual nsresult Shutdown() override;

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

@ -19,6 +19,7 @@
#include <stagefright/foundation/AMessage.h>
#include <stagefright/foundation/ALooper.h>
#include "media/openmax/OMX_Audio.h"
#include "MediaData.h"
#include <android/log.h>
#define GADM_LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "GonkAudioDecoderManager", __VA_ARGS__)
@ -100,16 +101,16 @@ GonkAudioDecoderManager::Init(MediaDataDecoderCallback* aCallback)
}
status_t
GonkAudioDecoderManager::SendSampleToOMX(mp4_demuxer::MP4Sample* aSample)
GonkAudioDecoderManager::SendSampleToOMX(MediaRawData* aSample)
{
return mDecoder->Input(reinterpret_cast<const uint8_t*>(aSample->data),
aSample->size,
aSample->composition_timestamp,
return mDecoder->Input(reinterpret_cast<const uint8_t*>(aSample->mData),
aSample->mSize,
aSample->mTime,
0);
}
bool
GonkAudioDecoderManager::PerformFormatSpecificProcess(mp4_demuxer::MP4Sample* aSample)
GonkAudioDecoderManager::PerformFormatSpecificProcess(MediaRawData* aSample)
{
if (aSample && mUseAdts) {
int8_t frequency_index =

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

@ -35,9 +35,9 @@ public:
virtual nsresult Flush() override;
protected:
virtual bool PerformFormatSpecificProcess(mp4_demuxer::MP4Sample* aSample) override;
virtual bool PerformFormatSpecificProcess(MediaRawData* aSample) override;
virtual status_t SendSampleToOMX(mp4_demuxer::MP4Sample* aSample) override;
virtual status_t SendSampleToOMX(MediaRawData* aSample) override;
private:

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

@ -8,6 +8,7 @@
#include "VideoUtils.h"
#include "nsTArray.h"
#include "MediaCodecProxy.h"
#include "MediaData.h"
#include "prlog.h"
#include <android/log.h>
@ -30,7 +31,7 @@ GonkDecoderManager::GonkDecoderManager(MediaTaskQueue* aTaskQueue)
}
nsresult
GonkDecoderManager::Input(mp4_demuxer::MP4Sample* aSample)
GonkDecoderManager::Input(MediaRawData* aSample)
{
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
@ -49,18 +50,18 @@ GonkDecoderManager::Input(mp4_demuxer::MP4Sample* aSample)
mQueueSample.RemoveElementAt(0);
}
// When EOS, aSample will be null and sends this empty MP4Sample to nofity
// When EOS, aSample will be null and sends this empty MediaRawData to nofity
// OMX it reachs EOS.
nsAutoPtr<mp4_demuxer::MP4Sample> sample;
nsRefPtr<MediaRawData> sample;
if (!aSample) {
sample = new mp4_demuxer::MP4Sample();
sample = new MediaRawData();
}
// If rv is OK, that means mQueueSample is empty, now try to queue current input
// aSample.
if (rv == OK) {
MOZ_ASSERT(!mQueueSample.Length());
mp4_demuxer::MP4Sample* tmp;
MediaRawData* tmp;
if (aSample) {
tmp = aSample;
if (!PerformFormatSpecificProcess(aSample)) {
@ -151,18 +152,18 @@ GonkMediaDataDecoder::Shutdown()
// Inserts data into the decoder's pipeline.
nsresult
GonkMediaDataDecoder::Input(mp4_demuxer::MP4Sample* aSample)
GonkMediaDataDecoder::Input(MediaRawData* aSample)
{
mTaskQueue->Dispatch(
NS_NewRunnableMethodWithArg<nsAutoPtr<mp4_demuxer::MP4Sample>>(
NS_NewRunnableMethodWithArg<nsRefPtr<MediaRawData>>(
this,
&GonkMediaDataDecoder::ProcessDecode,
nsAutoPtr<mp4_demuxer::MP4Sample>(aSample)));
nsRefPtr<MediaRawData>(aSample)));
return NS_OK;
}
void
GonkMediaDataDecoder::ProcessDecode(mp4_demuxer::MP4Sample* aSample)
GonkMediaDataDecoder::ProcessDecode(MediaRawData* aSample)
{
nsresult rv = mManager->Input(aSample);
if (rv != NS_OK) {
@ -172,7 +173,7 @@ GonkMediaDataDecoder::ProcessDecode(mp4_demuxer::MP4Sample* aSample)
return;
}
if (aSample) {
mLastStreamOffset = aSample->byte_offset;
mLastStreamOffset = aSample->mOffset;
}
ProcessOutput();
}

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

@ -6,7 +6,6 @@
#if !defined(GonkMediaDataDecoder_h_)
#define GonkMediaDataDecoder_h_
#include "mp4_demuxer/mp4_demuxer.h"
#include "mozilla/RefPtr.h"
#include "MP4Reader.h"
@ -15,6 +14,7 @@ class MediaCodecProxy;
} // namespace android
namespace mozilla {
class MediaRawData;
// Manage the data flow from inputting encoded data and outputting decode data.
class GonkDecoderManager {
@ -28,7 +28,7 @@ public:
virtual android::sp<android::MediaCodecProxy> Init(MediaDataDecoderCallback* aCallback) = 0;
// Add samples into OMX decoder or queue them if decoder is out of input buffer.
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample);
virtual nsresult Input(MediaRawData* aSample);
// Produces decoded output, it blocks until output can be produced or a timeout
// is expired or until EOS. Returns NS_OK on success, or NS_ERROR_NOT_AVAILABLE
@ -62,15 +62,15 @@ public:
protected:
// It performs special operation to MP4 sample, the real action is depended on
// the codec type.
virtual bool PerformFormatSpecificProcess(mp4_demuxer::MP4Sample* aSample) { return true; }
virtual bool PerformFormatSpecificProcess(MediaRawData* aSample) { return true; }
// It sends MP4Sample to OMX layer. It must be overrided by subclass.
virtual android::status_t SendSampleToOMX(mp4_demuxer::MP4Sample* aSample) = 0;
virtual android::status_t SendSampleToOMX(MediaRawData* aSample) = 0;
// An queue with the MP4 samples which are waiting to be sent into OMX.
// If an element is an empty MP4Sample, that menas EOS. There should not
// any sample be queued after EOS.
nsTArray<nsAutoPtr<mp4_demuxer::MP4Sample>> mQueueSample;
nsTArray<nsRefPtr<MediaRawData>> mQueueSample;
RefPtr<MediaTaskQueue> mTaskQueue;
};
@ -90,7 +90,7 @@ public:
virtual nsresult Init() override;
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample);
virtual nsresult Input(MediaRawData* aSample);
virtual nsresult Flush() override;
@ -112,7 +112,7 @@ private:
// extracts output if available, if aSample is null, it means there is
// no data from source, it will notify the decoder EOS and flush all the
// decoded frames.
void ProcessDecode(mp4_demuxer::MP4Sample* aSample);
void ProcessDecode(MediaRawData* aSample);
// Called on the task queue. Extracts output if available, and delivers
// it to the reader. Called after ProcessDecode() and ProcessDrain().

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

@ -438,17 +438,17 @@ void GonkVideoDecoderManager::ReleaseVideoBuffer() {
}
status_t
GonkVideoDecoderManager::SendSampleToOMX(mp4_demuxer::MP4Sample* aSample)
GonkVideoDecoderManager::SendSampleToOMX(MediaRawData* aSample)
{
// An empty MP4Sample is going to notify EOS to decoder. It doesn't need
// An empty MediaRawData is going to notify EOS to decoder. It doesn't need
// to keep PTS and duration.
if (aSample->data && aSample->duration && aSample->composition_timestamp) {
QueueFrameTimeIn(aSample->composition_timestamp, aSample->duration);
if (aSample->mData && aSample->mDuration && aSample->mTime) {
QueueFrameTimeIn(aSample->mTime, aSample->mDuration);
}
return mDecoder->Input(reinterpret_cast<const uint8_t*>(aSample->data),
aSample->size,
aSample->composition_timestamp,
return mDecoder->Input(reinterpret_cast<const uint8_t*>(aSample->mData),
aSample->mSize,
aSample->mTime,
0);
}

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

@ -58,7 +58,7 @@ public:
static void RecycleCallback(TextureClient* aClient, void* aClosure);
protected:
virtual android::status_t SendSampleToOMX(mp4_demuxer::MP4Sample* aSample) override;
virtual android::status_t SendSampleToOMX(MediaRawData* aSample) override;
private:
struct FrameInfo

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

@ -177,11 +177,11 @@ WMFAudioMFTManager::Init()
}
HRESULT
WMFAudioMFTManager::Input(mp4_demuxer::MP4Sample* aSample)
WMFAudioMFTManager::Input(MediaRawData* aSample)
{
const uint8_t* data = reinterpret_cast<const uint8_t*>(aSample->data);
uint32_t length = aSample->size;
return mDecoder->Input(data, length, aSample->composition_timestamp);
return mDecoder->Input(aSample->mData,
uint32_t(aSample->mSize),
aSample->mTime);
}
HRESULT

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

@ -22,7 +22,7 @@ public:
virtual TemporaryRef<MFTDecoder> Init() override;
virtual HRESULT Input(mp4_demuxer::MP4Sample* aSample) override;
virtual HRESULT Input(MediaRawData* aSample) override;
// Note WMF's AAC decoder sometimes output negatively timestamped samples,
// presumably they're the preroll samples, and we strip them. We may return

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

@ -75,18 +75,18 @@ WMFMediaDataDecoder::ProcessReleaseDecoder()
// Inserts data into the decoder's pipeline.
nsresult
WMFMediaDataDecoder::Input(mp4_demuxer::MP4Sample* aSample)
WMFMediaDataDecoder::Input(MediaRawData* aSample)
{
mTaskQueue->Dispatch(
NS_NewRunnableMethodWithArg<nsAutoPtr<mp4_demuxer::MP4Sample>>(
NS_NewRunnableMethodWithArg<nsRefPtr<MediaRawData>>(
this,
&WMFMediaDataDecoder::ProcessDecode,
nsAutoPtr<mp4_demuxer::MP4Sample>(aSample)));
nsRefPtr<MediaRawData>(aSample)));
return NS_OK;
}
void
WMFMediaDataDecoder::ProcessDecode(mp4_demuxer::MP4Sample* aSample)
WMFMediaDataDecoder::ProcessDecode(MediaRawData* aSample)
{
HRESULT hr = mMFTManager->Input(aSample);
if (FAILED(hr)) {
@ -95,7 +95,7 @@ WMFMediaDataDecoder::ProcessDecode(mp4_demuxer::MP4Sample* aSample)
return;
}
mLastStreamOffset = aSample->byte_offset;
mLastStreamOffset = aSample->mOffset;
ProcessOutput();
}

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

@ -13,10 +13,6 @@
#include "MFTDecoder.h"
#include "mozilla/RefPtr.h"
namespace mp4_demuxer {
class MP4Sample;
}
namespace mozilla {
// Encapsulates the initialization of the MFTDecoder appropriate for decoding
@ -33,7 +29,7 @@ public:
// Submit a compressed sample for decoding.
// This should forward to the MFTDecoder after performing
// any required sample formatting.
virtual HRESULT Input(mp4_demuxer::MP4Sample* aSample) = 0;
virtual HRESULT Input(MediaRawData* aSample) = 0;
// Produces decoded output, if possible. Blocks until output can be produced,
// or until no more is able to be produced.
@ -65,7 +61,7 @@ public:
virtual nsresult Init() override;
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample);
virtual nsresult Input(MediaRawData* aSample);
virtual nsresult Flush() override;
@ -83,7 +79,7 @@ private:
// Called on the task queue. Inserts the sample into the decoder, and
// extracts output if available.
void ProcessDecode(mp4_demuxer::MP4Sample* aSample);
void ProcessDecode(MediaRawData* aSample);
// Called on the task queue. Extracts output if available, and delivers
// it to the reader. Called after ProcessDecode() and ProcessDrain().

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

@ -235,16 +235,16 @@ WMFVideoMFTManager::Init()
}
HRESULT
WMFVideoMFTManager::Input(mp4_demuxer::MP4Sample* aSample)
WMFVideoMFTManager::Input(MediaRawData* aSample)
{
if (!mDecoder) {
// This can happen during shutdown.
return E_FAIL;
}
// Forward sample data to the decoder.
const uint8_t* data = reinterpret_cast<const uint8_t*>(aSample->data);
uint32_t length = aSample->size;
return mDecoder->Input(data, length, aSample->composition_timestamp);
return mDecoder->Input(aSample->mData,
uint32_t(aSample->mSize),
aSample->mTime);
}
HRESULT

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

@ -28,7 +28,7 @@ public:
virtual TemporaryRef<MFTDecoder> Init() override;
virtual HRESULT Input(mp4_demuxer::MP4Sample* aSample) override;
virtual HRESULT Input(MediaRawData* aSample) override;
virtual HRESULT Output(int64_t aStreamOffset,
nsRefPtr<MediaData>& aOutput) override;

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

@ -52,7 +52,7 @@ H264Converter::Init()
}
nsresult
H264Converter::Input(mp4_demuxer::MP4Sample* aSample)
H264Converter::Input(MediaRawData* aSample)
{
if (!mNeedAVCC) {
if (!mp4_demuxer::AnnexB::ConvertSampleToAnnexB(aSample)) {
@ -71,7 +71,7 @@ H264Converter::Input(mp4_demuxer::MP4Sample* aSample)
rv = CreateDecoderAndInit(aSample);
if (rv == NS_ERROR_NOT_INITIALIZED) {
// We are missing the required SPS to create the decoder.
// Ignore for the time being, the MP4Sample will be dropped.
// Ignore for the time being, the MediaRawData will be dropped.
return NS_OK;
}
} else {
@ -79,7 +79,7 @@ H264Converter::Input(mp4_demuxer::MP4Sample* aSample)
}
NS_ENSURE_SUCCESS(rv, rv);
aSample->extra_data = mCurrentConfig.extra_data;
aSample->mExtraData = mCurrentConfig.extra_data;
return mDecoder->Input(aSample);
}
@ -187,9 +187,9 @@ H264Converter::CreateDecoder()
}
nsresult
H264Converter::CreateDecoderAndInit(mp4_demuxer::MP4Sample* aSample)
H264Converter::CreateDecoderAndInit(MediaRawData* aSample)
{
nsRefPtr<mp4_demuxer::ByteBuffer> extra_data =
nsRefPtr<DataBuffer> extra_data =
mp4_demuxer::AnnexB::ExtractExtraData(aSample);
if (!mp4_demuxer::AnnexB::HasSPS(extra_data)) {
return NS_ERROR_NOT_INITIALIZED;
@ -202,9 +202,9 @@ H264Converter::CreateDecoderAndInit(mp4_demuxer::MP4Sample* aSample)
}
nsresult
H264Converter::CheckForSPSChange(mp4_demuxer::MP4Sample* aSample)
H264Converter::CheckForSPSChange(MediaRawData* aSample)
{
nsRefPtr<mp4_demuxer::ByteBuffer> extra_data =
nsRefPtr<DataBuffer> extra_data =
mp4_demuxer::AnnexB::ExtractExtraData(aSample);
if (!mp4_demuxer::AnnexB::HasSPS(extra_data) ||
mp4_demuxer::AnnexB::CompareExtraData(extra_data,
@ -224,7 +224,7 @@ H264Converter::CheckForSPSChange(mp4_demuxer::MP4Sample* aSample)
}
void
H264Converter::UpdateConfigFromExtraData(mp4_demuxer::ByteBuffer* aExtraData)
H264Converter::UpdateConfigFromExtraData(DataBuffer* aExtraData)
{
mp4_demuxer::SPSData spsdata;
if (mp4_demuxer::H264::DecodeSPSFromExtraData(aExtraData, spsdata) &&

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

@ -30,7 +30,7 @@ public:
virtual ~H264Converter();
virtual nsresult Init() override;
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) override;
virtual nsresult Input(MediaRawData* aSample) override;
virtual nsresult Flush() override;
virtual nsresult Drain() override;
virtual nsresult Shutdown() override;
@ -48,9 +48,9 @@ private:
// Returns NS_ERROR_FAILURE if error is permanent and can't be recovered and
// will set mError accordingly.
nsresult CreateDecoder();
nsresult CreateDecoderAndInit(mp4_demuxer::MP4Sample* aSample);
nsresult CheckForSPSChange(mp4_demuxer::MP4Sample* aSample);
void UpdateConfigFromExtraData(mp4_demuxer::ByteBuffer* aExtraData);
nsresult CreateDecoderAndInit(MediaRawData* aSample);
nsresult CheckForSPSChange(MediaRawData* aSample);
void UpdateConfigFromExtraData(DataBuffer* aExtraData);
nsRefPtr<PlatformDecoderModule> mPDM;
mp4_demuxer::VideoDecoderConfig mCurrentConfig;

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

@ -7,7 +7,7 @@
#include "gmp-audio-samples.h"
#include "gmp-errors.h"
#include "GMPEncryptedBufferDataImpl.h"
#include "mp4_demuxer/DecoderData.h"
#include "MediaData.h"
namespace mozilla {
namespace gmp {
@ -32,17 +32,17 @@ GMPAudioSamplesImpl::GMPAudioSamplesImpl(const GMPAudioEncodedSampleData& aData)
}
}
GMPAudioSamplesImpl::GMPAudioSamplesImpl(mp4_demuxer::MP4Sample* aSample,
GMPAudioSamplesImpl::GMPAudioSamplesImpl(MediaRawData* aSample,
uint32_t aChannels,
uint32_t aRate)
: mFormat(kGMPAudioEncodedSamples)
, mTimeStamp(aSample->composition_timestamp)
, mTimeStamp(aSample->mTime)
, mChannels(aChannels)
, mRate(aRate)
{
mBuffer.AppendElements(aSample->data, aSample->size);
if (aSample->crypto.valid) {
mCrypto = new GMPEncryptedBufferDataImpl(aSample->crypto);
mBuffer.AppendElements(aSample->mData, aSample->mSize);
if (aSample->mCrypto.valid) {
mCrypto = new GMPEncryptedBufferDataImpl(aSample->mCrypto);
}
}

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

@ -14,12 +14,9 @@
#include "GMPEncryptedBufferDataImpl.h"
#include "mozilla/gmp/GMPTypes.h"
namespace mp4_demuxer {
class MP4Sample;
}
namespace mozilla {
class CryptoSample;
class MediaRawData;
namespace gmp {
@ -27,7 +24,7 @@ class GMPAudioSamplesImpl : public GMPAudioSamples {
public:
explicit GMPAudioSamplesImpl(GMPAudioFormat aFormat);
explicit GMPAudioSamplesImpl(const GMPAudioEncodedSampleData& aData);
GMPAudioSamplesImpl(mp4_demuxer::MP4Sample* aSample,
GMPAudioSamplesImpl(MediaRawData* aSample,
uint32_t aChannels,
uint32_t aRate);
virtual ~GMPAudioSamplesImpl();

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

@ -43,23 +43,23 @@ TEST(MP4Demuxer, Seek)
EXPECT_TRUE(d->Init());
nsTArray<nsAutoPtr<MP4Sample>> samples;
MP4Sample* sample;
nsTArray<nsRefPtr<MediaRawData>> samples;
nsRefPtr<MediaRawData> sample;
while (!!(sample = d->DemuxVideoSample())) {
samples.AppendElement(sample);
if (samples.Length() >= 2) {
EXPECT_LT(samples[samples.Length() - 2]->decode_timestamp,
samples[samples.Length() - 1]->decode_timestamp);
EXPECT_LT(samples[samples.Length() - 2]->mTimecode,
samples[samples.Length() - 1]->mTimecode);
}
}
Microseconds keyFrame = 0;
for (size_t i = 0; i < samples.Length(); i++) {
if (samples[i]->is_sync_point) {
keyFrame = samples[i]->decode_timestamp;
if (samples[i]->mKeyframe) {
keyFrame = samples[i]->mTimecode;
}
d->SeekVideo(samples[i]->composition_timestamp);
d->SeekVideo(samples[i]->mTime);
sample = d->DemuxVideoSample();
EXPECT_EQ(keyFrame, sample->decode_timestamp);
EXPECT_EQ(keyFrame, sample->mTimecode);
}
}
@ -158,10 +158,10 @@ TEST(MP4Demuxer, CENCFrag)
"1 16 7e571d037e571d037e571d037e571d03 000000000000000000000000000019cd 5,2392",
};
MP4Sample* sample;
nsRefPtr<MediaRawData> sample;
size_t i = 0;
while (!!(sample = d->DemuxVideoSample())) {
nsCString text = ToCryptoString(sample->crypto);
nsCString text = ToCryptoString(sample->mCrypto);
EXPECT_STREQ(video[i++], text.get());
}
EXPECT_EQ(ArrayLength(video), i);
@ -265,7 +265,7 @@ TEST(MP4Demuxer, CENCFrag)
i = 0;
while (!!(sample = d->DemuxAudioSample())) {
nsCString text = ToCryptoString(sample->crypto);
nsCString text = ToCryptoString(sample->mCrypto);
EXPECT_STREQ(audio[i++], text.get());
}
EXPECT_EQ(ArrayLength(audio), i);
@ -292,11 +292,11 @@ TEST(MP4Demuxer, GetNextKeyframe)
// gizmp-frag has two keyframes; one at dts=cts=0, and another at
// dts=cts=1000000. Verify we get expected results.
MP4Sample* sample;
nsRefPtr<MediaRawData> sample;
size_t i = 0;
const int64_t keyframe = 1000000;
while (!!(sample = d->DemuxVideoSample())) {
int64_t expected = (sample->decode_timestamp < keyframe) ? keyframe : -1;
int64_t expected = (sample->mTimecode < keyframe) ? keyframe : -1;
EXPECT_EQ(d->GetNextKeyframeTime(), expected);
i++;
}

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

@ -35,7 +35,7 @@ using layers::Image;
using layers::LayerManager;
using layers::LayersBackend;
class VP8Sample : public MP4Sample
class VP8Sample : public MediaRawData
{
public:
VP8Sample(int64_t aTimestamp,
@ -44,21 +44,13 @@ public:
uint8_t* aData,
size_t aSize,
bool aSyncPoint)
: MediaRawData(aData, aSize)
{
decode_timestamp = -1;
composition_timestamp = aTimestamp;
duration = aDuration;
byte_offset = aByteOffset;
is_sync_point = aSyncPoint;
data = new uint8_t[aSize];
size = aSize;
memmove(data, aData, size);
}
virtual ~VP8Sample()
{
delete data;
mTimecode = -1;
mTime = aTimestamp;
mDuration = aDuration;
mOffset = aByteOffset;
mKeyframe = aSyncPoint;
}
};
@ -162,7 +154,7 @@ IntelWebMVideoDecoder::Init(unsigned int aWidth, unsigned int aHeight)
}
bool
IntelWebMVideoDecoder::Demux(nsAutoPtr<VP8Sample>& aSample, bool* aEOS)
IntelWebMVideoDecoder::Demux(nsRefPtr<VP8Sample>& aSample, bool* aEOS)
{
nsAutoRef<NesteggPacketHolder> holder(mReader->NextPacket(WebMReader::VIDEO));
if (!holder) {
@ -232,6 +224,9 @@ IntelWebMVideoDecoder::Demux(nsAutoPtr<VP8Sample>& aSample, bool* aEOS)
data,
length,
si.is_kf);
if (!aSample->mData) {
return false;
}
}
return true;
@ -257,7 +252,7 @@ IntelWebMVideoDecoder::Decode()
!mEOS) {
mMonitor.AssertCurrentThreadOwns();
mMonitor.Unlock();
nsAutoPtr<VP8Sample> compressed(PopSample());
nsRefPtr<VP8Sample> compressed(PopSample());
if (!compressed) {
// EOS, or error. Let the state machine know there are no more
// frames coming.
@ -272,7 +267,7 @@ IntelWebMVideoDecoder::Decode()
} else {
#ifdef LOG_SAMPLE_DECODE
LOG("PopSample %s time=%lld dur=%lld", TrackTypeToStr(aTrack),
compressed->composition_timestamp, compressed->duration);
compressed->mTime, compressed->mDuration);
#endif
mMonitor.Lock();
mDrainComplete = false;
@ -282,10 +277,6 @@ IntelWebMVideoDecoder::Decode()
if (NS_FAILED(mMediaDataDecoder->Input(compressed))) {
return false;
}
// If Input() failed, we let the auto pointer delete |compressed|.
// Otherwise, we assume the decoder will delete it when it's finished
// with it.
compressed.forget();
}
mMonitor.Lock();
}
@ -317,14 +308,14 @@ IntelWebMVideoDecoder::SkipVideoDemuxToNextKeyFrame(int64_t aTimeThreshold, uint
// Loop until we reach the next keyframe after the threshold.
while (true) {
nsAutoPtr<VP8Sample> compressed(PopSample());
nsRefPtr<VP8Sample> compressed(PopSample());
if (!compressed) {
// EOS, or error. Let the state machine know.
return false;
}
aParsed++;
if (!compressed->is_sync_point ||
compressed->composition_timestamp < aTimeThreshold) {
if (!compressed->mKeyframe ||
compressed->mTime < aTimeThreshold) {
continue;
}
mQueuedVideoSample = compressed;
@ -367,15 +358,14 @@ IntelWebMVideoDecoder::DecodeVideoFrame(bool& aKeyframeSkip,
return rv;
}
VP8Sample*
already_AddRefed<VP8Sample>
IntelWebMVideoDecoder::PopSample()
{
VP8Sample* sample = nullptr;
if (mQueuedVideoSample) {
return mQueuedVideoSample.forget();
}
nsRefPtr<VP8Sample> sample;
while (mSampleQueue.empty()) {
nsAutoPtr<VP8Sample> sample;
bool eos = false;
bool ok = Demux(sample, &eos);
if (!ok || eos) {
@ -389,7 +379,7 @@ IntelWebMVideoDecoder::PopSample()
MOZ_ASSERT(!mSampleQueue.empty());
sample = mSampleQueue.front();
mSampleQueue.pop_front();
return sample;
return sample.forget();
}
void

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

@ -15,6 +15,7 @@
#include "mp4_demuxer/mp4_demuxer.h"
#include "mp4_demuxer/DecoderData.h"
#include "MediaData.h"
class MediaTaskQueue;
@ -22,7 +23,7 @@ namespace mozilla {
class VP8Sample;
typedef std::deque<VP8Sample*> VP8SampleQueue;
typedef std::deque<nsRefPtr<VP8Sample>> VP8SampleQueue;
class IntelWebMVideoDecoder : public WebMVideoDecoder, public MediaDataDecoderCallback
{
@ -50,13 +51,13 @@ private:
bool Decode();
bool Demux(nsAutoPtr<VP8Sample>& aSample, bool* aEOS);
bool Demux(nsRefPtr<VP8Sample>& aSample, bool* aEOS);
bool SkipVideoDemuxToNextKeyFrame(int64_t aTimeThreshold, uint32_t& parsed);
bool IsSupportedVideoMimeType(const nsACString& aMimeType);
VP8Sample* PopSample();
already_AddRefed<VP8Sample> PopSample();
nsRefPtr<WebMReader> mReader;
nsRefPtr<PlatformDecoderModule> mPlatform;
@ -72,7 +73,7 @@ private:
nsAutoPtr<mp4_demuxer::VideoDecoderConfig> mDecoderConfig;
VP8SampleQueue mSampleQueue;
nsAutoPtr<VP8Sample> mQueuedVideoSample;
nsRefPtr<VP8Sample> mQueuedVideoSample;
uint64_t mNumSamplesInput;
uint64_t mNumSamplesOutput;
uint64_t mLastReportedNumDecodedFrames;

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

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mp4_demuxer/Adts.h"
#include "mp4_demuxer/DecoderData.h"
#include "MediaData.h"
#include "media/stagefright/MediaBuffer.h"
#include "mozilla/Array.h"
#include "mozilla/ArrayUtils.h"
@ -34,11 +34,11 @@ Adts::GetFrequencyIndex(uint16_t aSamplesPerSecond)
bool
Adts::ConvertSample(uint16_t aChannelCount, int8_t aFrequencyIndex,
int8_t aProfile, MP4Sample* aSample)
int8_t aProfile, MediaRawData* aSample)
{
static const int kADTSHeaderSize = 7;
size_t newSize = aSample->size + kADTSHeaderSize;
size_t newSize = aSample->mSize + kADTSHeaderSize;
// ADTS header uses 13 bits for packet size.
if (newSize >= (1 << 13) || aChannelCount > 15 ||
@ -56,16 +56,17 @@ Adts::ConvertSample(uint16_t aChannelCount, int8_t aFrequencyIndex,
header[5] = ((newSize & 7) << 5) + 0x1f;
header[6] = 0xfc;
if (!aSample->Prepend(&header[0], ArrayLength(header))) {
nsAutoPtr<MediaRawDataWriter> writer(aSample->CreateWriter());
if (!writer->Prepend(&header[0], ArrayLength(header))) {
return false;
}
if (aSample->crypto.valid) {
if (aSample->crypto.plain_sizes.Length() == 0) {
aSample->crypto.plain_sizes.AppendElement(kADTSHeaderSize);
aSample->crypto.encrypted_sizes.AppendElement(aSample->size - kADTSHeaderSize);
if (aSample->mCrypto.valid) {
if (aSample->mCrypto.plain_sizes.Length() == 0) {
aSample->mCrypto.plain_sizes.AppendElement(kADTSHeaderSize);
aSample->mCrypto.encrypted_sizes.AppendElement(aSample->mSize - kADTSHeaderSize);
} else {
aSample->crypto.plain_sizes[0] += kADTSHeaderSize;
aSample->mCrypto.plain_sizes[0] += kADTSHeaderSize;
}
}

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

@ -7,7 +7,7 @@
#include "mp4_demuxer/AnnexB.h"
#include "mp4_demuxer/ByteReader.h"
#include "mp4_demuxer/ByteWriter.h"
#include "mp4_demuxer/DecoderData.h"
#include "MediaData.h"
using namespace mozilla;
@ -17,25 +17,25 @@ namespace mp4_demuxer
static const uint8_t kAnnexBDelimiter[] = { 0, 0, 0, 1 };
bool
AnnexB::ConvertSampleToAnnexB(MP4Sample* aSample)
AnnexB::ConvertSampleToAnnexB(mozilla::MediaRawData* aSample)
{
MOZ_ASSERT(aSample);
if (!IsAVCC(aSample)) {
return true;
}
MOZ_ASSERT(aSample->data);
MOZ_ASSERT(aSample->mData);
if (!ConvertSampleTo4BytesAVCC(aSample)) {
return false;
}
if (aSample->size < 4) {
if (aSample->mSize < 4) {
// Nothing to do, it's corrupted anyway.
return true;
}
ByteReader reader(aSample->data, aSample->size);
ByteReader reader(aSample->mData, aSample->mSize);
mozilla::Vector<uint8_t> tmp;
ByteWriter writer(tmp);
@ -51,15 +51,17 @@ AnnexB::ConvertSampleToAnnexB(MP4Sample* aSample)
writer.Write(p, nalLen);
}
if (!aSample->Replace(tmp.begin(), tmp.length())) {
nsAutoPtr<MediaRawDataWriter> samplewriter(aSample->CreateWriter());
if (!samplewriter->Replace(tmp.begin(), tmp.length())) {
return false;
}
// Prepend the Annex B NAL with SPS and PPS tables to keyframes.
if (aSample->is_sync_point) {
nsRefPtr<ByteBuffer> annexB =
ConvertExtraDataToAnnexB(aSample->extra_data);
if (!aSample->Prepend(annexB->Elements(), annexB->Length())) {
if (aSample->mKeyframe) {
nsRefPtr<DataBuffer> annexB =
ConvertExtraDataToAnnexB(aSample->mExtraData);
if (!samplewriter->Prepend(annexB->Elements(), annexB->Length())) {
return false;
}
}
@ -67,8 +69,8 @@ AnnexB::ConvertSampleToAnnexB(MP4Sample* aSample)
return true;
}
already_AddRefed<ByteBuffer>
AnnexB::ConvertExtraDataToAnnexB(const ByteBuffer* aExtraData)
already_AddRefed<mozilla::DataBuffer>
AnnexB::ConvertExtraDataToAnnexB(const mozilla::DataBuffer* aExtraData)
{
// AVCC 6 byte header looks like:
// +------+------+------+------+------+------+------+------+
@ -85,7 +87,7 @@ AnnexB::ConvertExtraDataToAnnexB(const ByteBuffer* aExtraData)
// [5] | unused | numSps |
// +------+------+------+------+------+------+------+------+
nsRefPtr<ByteBuffer> annexB = new ByteBuffer;
nsRefPtr<mozilla::DataBuffer> annexB = new mozilla::DataBuffer;
ByteReader reader(*aExtraData);
const uint8_t* ptr = reader.Read(5);
@ -103,7 +105,7 @@ AnnexB::ConvertExtraDataToAnnexB(const ByteBuffer* aExtraData)
void
AnnexB::ConvertSPSOrPPS(ByteReader& aReader, uint8_t aCount,
ByteBuffer* aAnnexB)
mozilla::DataBuffer* aAnnexB)
{
for (int i = 0; i < aCount; i++) {
uint16_t length = aReader.ReadU16();
@ -212,7 +214,7 @@ ParseNALUnits(ByteWriter& aBw, ByteReader& aBr)
}
bool
AnnexB::ConvertSampleToAVCC(MP4Sample* aSample)
AnnexB::ConvertSampleToAVCC(mozilla::MediaRawData* aSample)
{
if (IsAVCC(aSample)) {
return ConvertSampleTo4BytesAVCC(aSample);
@ -224,19 +226,20 @@ AnnexB::ConvertSampleToAVCC(MP4Sample* aSample)
mozilla::Vector<uint8_t> nalu;
ByteWriter writer(nalu);
ByteReader reader(aSample->data, aSample->size);
ByteReader reader(aSample->mData, aSample->mSize);
ParseNALUnits(writer, reader);
return aSample->Replace(nalu.begin(), nalu.length());
nsAutoPtr<MediaRawDataWriter> samplewriter(aSample->CreateWriter());
return samplewriter->Replace(nalu.begin(), nalu.length());
}
already_AddRefed<ByteBuffer>
AnnexB::ExtractExtraData(const MP4Sample* aSample)
already_AddRefed<mozilla::DataBuffer>
AnnexB::ExtractExtraData(const mozilla::MediaRawData* aSample)
{
nsRefPtr<ByteBuffer> extradata = new ByteBuffer;
if (IsAVCC(aSample) && HasSPS(aSample->extra_data)) {
nsRefPtr<mozilla::DataBuffer> extradata = new mozilla::DataBuffer;
if (IsAVCC(aSample) && HasSPS(aSample->mExtraData)) {
// We already have an explicit extradata, re-use it.
extradata = aSample->extra_data;
extradata = aSample->mExtraData;
return extradata.forget();
}
@ -254,16 +257,15 @@ AnnexB::ExtractExtraData(const MP4Sample* aSample)
int nalLenSize;
if (IsAVCC(aSample)) {
nalLenSize = ((*aSample->extra_data)[4] & 3) + 1;
nalLenSize = ((*aSample->mExtraData)[4] & 3) + 1;
} else {
// We do not have an extradata, assume it's AnnexB converted to AVCC via
// ConvertSampleToAVCC.
nalLenSize = 4;
}
ByteReader reader(aSample->data, aSample->size);
ByteReader reader(aSample->mData, aSample->mSize);
// Find SPS and PPS NALUs in AVCC data
uint8_t* d = aSample->data;
while (reader.Remaining() > nalLenSize) {
uint32_t nalLen;
switch (nalLenSize) {
@ -307,19 +309,19 @@ AnnexB::ExtractExtraData(const MP4Sample* aSample)
}
bool
AnnexB::HasSPS(const MP4Sample* aSample)
AnnexB::HasSPS(const mozilla::MediaRawData* aSample)
{
return HasSPS(aSample->extra_data);
return HasSPS(aSample->mExtraData);
}
bool
AnnexB::HasSPS(const ByteBuffer* aExtraData)
AnnexB::HasSPS(const mozilla::DataBuffer* aExtraData)
{
if (!aExtraData) {
return false;
}
ByteReader reader(*aExtraData);
ByteReader reader(aExtraData);
const uint8_t* ptr = reader.Read(5);
if (!ptr || !reader.CanRead8()) {
return false;
@ -331,18 +333,18 @@ AnnexB::HasSPS(const ByteBuffer* aExtraData)
}
bool
AnnexB::ConvertSampleTo4BytesAVCC(MP4Sample* aSample)
AnnexB::ConvertSampleTo4BytesAVCC(mozilla::MediaRawData* aSample)
{
MOZ_ASSERT(IsAVCC(aSample));
int nalLenSize = ((*aSample->extra_data)[4] & 3) + 1;
int nalLenSize = ((*aSample->mExtraData)[4] & 3) + 1;
if (nalLenSize == 4) {
return true;
}
mozilla::Vector<uint8_t> dest;
ByteWriter writer(dest);
ByteReader reader(aSample->data, aSample->size);
ByteReader reader(aSample->mData, aSample->mSize);
while (reader.Remaining() > nalLenSize) {
uint32_t nalLen;
switch (nalLenSize) {
@ -358,29 +360,30 @@ AnnexB::ConvertSampleTo4BytesAVCC(MP4Sample* aSample)
writer.WriteU32(nalLen);
writer.Write(p, nalLen);
}
return aSample->Replace(dest.begin(), dest.length());
nsAutoPtr<MediaRawDataWriter> samplewriter(aSample->CreateWriter());
return samplewriter->Replace(dest.begin(), dest.length());
}
bool
AnnexB::IsAVCC(const MP4Sample* aSample)
AnnexB::IsAVCC(const mozilla::MediaRawData* aSample)
{
return aSample->size >= 3 && aSample->extra_data &&
aSample->extra_data->Length() >= 7 && (*aSample->extra_data)[0] == 1;
return aSample->mSize >= 3 && aSample->mExtraData &&
aSample->mExtraData->Length() >= 7 && (*aSample->mExtraData)[0] == 1;
}
bool
AnnexB::IsAnnexB(const MP4Sample* aSample)
AnnexB::IsAnnexB(const mozilla::MediaRawData* aSample)
{
if (aSample->size < 4) {
if (aSample->mSize < 4) {
return false;
}
uint32_t header = mozilla::BigEndian::readUint32(aSample->data);
uint32_t header = mozilla::BigEndian::readUint32(aSample->mData);
return header == 0x00000001 || (header >> 8) == 0x000001;
}
bool
AnnexB::CompareExtraData(const ByteBuffer* aExtraData1,
const ByteBuffer* aExtraData2)
AnnexB::CompareExtraData(const mozilla::DataBuffer* aExtraData1,
const mozilla::DataBuffer* aExtraData2)
{
// Very crude comparison.
return aExtraData1 == aExtraData2 || *aExtraData1 == *aExtraData2;

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

@ -75,7 +75,7 @@ FindData(const MetaData* aMetaData, uint32_t aKey, nsTArray<T>* aDest)
}
static bool
FindData(const MetaData* aMetaData, uint32_t aKey, ByteBuffer* aDest)
FindData(const MetaData* aMetaData, uint32_t aKey, mozilla::DataBuffer* aDest)
{
return FindData(aMetaData, aKey, static_cast<nsTArray<uint8_t>*>(aDest));
}
@ -170,90 +170,4 @@ VideoDecoderConfig::IsValid()
{
return display_width > 0 && display_height > 0;
}
MP4Sample::MP4Sample()
: decode_timestamp(0)
, composition_timestamp(0)
, duration(0)
, byte_offset(0)
, is_sync_point(0)
, data(nullptr)
, size(0)
, extra_data(nullptr)
{
}
MP4Sample*
MP4Sample::Clone() const
{
nsAutoPtr<MP4Sample> s(new MP4Sample());
s->decode_timestamp = decode_timestamp;
s->composition_timestamp = composition_timestamp;
s->duration = duration;
s->byte_offset = byte_offset;
s->is_sync_point = is_sync_point;
s->size = size;
s->crypto = crypto;
s->extra_data = extra_data;
s->extra_buffer = s->data = new (fallible) uint8_t[size];
if (!s->extra_buffer) {
return nullptr;
}
memcpy(s->data, data, size);
return s.forget();
}
MP4Sample::~MP4Sample()
{
}
bool
MP4Sample::Pad(size_t aPaddingBytes)
{
size_t newSize = size + aPaddingBytes;
uint8_t* newData = new (fallible) uint8_t[newSize];
if (!newData) {
return false;
}
memset(newData + size, 0, aPaddingBytes);
memcpy(newData, data, size);
extra_buffer = data = newData;
return true;
}
bool
MP4Sample::Prepend(const uint8_t* aData, size_t aSize)
{
size_t newSize = size + aSize;
uint8_t* newData = new (fallible) uint8_t[newSize];
if (!newData) {
return false;
}
memmove(newData + aSize, data, size);
memmove(newData, aData, aSize);
size = newSize;
extra_buffer = data = newData;
return true;
}
bool
MP4Sample::Replace(const uint8_t* aData, size_t aSize)
{
uint8_t* newData = new (fallible) uint8_t[aSize];
if (!newData) {
return false;
}
memcpy(newData, aData, aSize);
size = aSize;
extra_buffer = data = newData;
return true;
}
}

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

@ -19,8 +19,8 @@ namespace mp4_demuxer
class BitReader
{
public:
explicit BitReader(const ByteBuffer& aBuffer)
: mBitReader(aBuffer.Elements(), aBuffer.Length())
explicit BitReader(const mozilla::DataBuffer* aBuffer)
: mBitReader(aBuffer->Elements(), aBuffer->Length())
{
}
@ -82,8 +82,8 @@ SPSData::SPSData()
sample_ratio = 1.0;
}
/* static */ already_AddRefed<ByteBuffer>
H264::DecodeNALUnit(const ByteBuffer* aNAL)
/* static */ already_AddRefed<mozilla::DataBuffer>
H264::DecodeNALUnit(const mozilla::DataBuffer* aNAL)
{
MOZ_ASSERT(aNAL);
@ -91,8 +91,8 @@ H264::DecodeNALUnit(const ByteBuffer* aNAL)
return nullptr;
}
nsRefPtr<ByteBuffer> rbsp = new ByteBuffer;
ByteReader reader(*aNAL);
nsRefPtr<mozilla::DataBuffer> rbsp = new mozilla::DataBuffer;
ByteReader reader(aNAL);
uint8_t nal_unit_type = reader.ReadU8() & 0x1f;
uint32_t nalUnitHeaderBytes = 1;
if (nal_unit_type == 14 || nal_unit_type == 20 || nal_unit_type == 21) {
@ -138,10 +138,10 @@ ConditionDimension(float aValue)
}
/* static */ bool
H264::DecodeSPS(const ByteBuffer* aSPS, SPSData& aDest)
H264::DecodeSPS(const mozilla::DataBuffer* aSPS, SPSData& aDest)
{
MOZ_ASSERT(aSPS);
BitReader br(*aSPS);
BitReader br(aSPS);
int32_t lastScale;
int32_t nextScale;
@ -461,12 +461,12 @@ H264::vui_parameters(BitReader& aBr, SPSData& aDest)
}
/* static */ bool
H264::DecodeSPSFromExtraData(const ByteBuffer* aExtraData, SPSData& aDest)
H264::DecodeSPSFromExtraData(const mozilla::DataBuffer* aExtraData, SPSData& aDest)
{
if (!AnnexB::HasSPS(aExtraData)) {
return false;
}
ByteReader reader(*aExtraData);
ByteReader reader(aExtraData);
if (!reader.Read(5)) {
return false;
@ -490,10 +490,10 @@ H264::DecodeSPSFromExtraData(const ByteBuffer* aExtraData, SPSData& aDest)
return false;
}
nsRefPtr<ByteBuffer> rawNAL = new ByteBuffer;
nsRefPtr<mozilla::DataBuffer> rawNAL = new mozilla::DataBuffer;
rawNAL->AppendElements(ptr, length);
nsRefPtr<ByteBuffer> sps = DecodeNALUnit(rawNAL);
nsRefPtr<mozilla::DataBuffer> sps = DecodeNALUnit(rawNAL);
reader.DiscardRemaining();

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

@ -84,30 +84,29 @@ SampleIterator::SampleIterator(Index* aIndex)
{
}
MP4Sample* SampleIterator::GetNext()
already_AddRefed<MediaRawData> SampleIterator::GetNext()
{
Sample* s(Get());
if (!s) {
return nullptr;
}
nsAutoPtr<MP4Sample> sample(new MP4Sample());
sample->decode_timestamp = s->mDecodeTime;
sample->composition_timestamp = s->mCompositionRange.start;
sample->duration = s->mCompositionRange.Length();
sample->byte_offset = s->mByteRange.mStart;
sample->is_sync_point = s->mSync;
sample->size = s->mByteRange.Length();
nsRefPtr<MediaRawData> sample = new MediaRawData();
sample->mTimecode= s->mDecodeTime;
sample->mTime = s->mCompositionRange.start;
sample->mDuration = s->mCompositionRange.Length();
sample->mOffset = s->mByteRange.mStart;
sample->mKeyframe = s->mSync;
nsAutoPtr<MediaRawDataWriter> writer(sample->CreateWriter());
// Do the blocking read
sample->data = sample->extra_buffer = new (fallible) uint8_t[sample->size];
if (!sample->data) {
if (!writer->SetSize(s->mByteRange.Length())) {
return nullptr;
}
size_t bytesRead;
if (!mIndex->mSource->ReadAt(sample->byte_offset, sample->data, sample->size,
&bytesRead) || bytesRead != sample->size) {
if (!mIndex->mSource->ReadAt(sample->mOffset, writer->mData, sample->mSize,
&bytesRead) || bytesRead != sample->mSize) {
return nullptr;
}
@ -128,10 +127,10 @@ MP4Sample* SampleIterator::GetNext()
return nullptr;
}
ByteReader reader(cenc);
sample->crypto.valid = true;
sample->crypto.iv_size = ivSize;
sample->mCrypto.valid = true;
sample->mCrypto.iv_size = ivSize;
if (!reader.ReadArray(sample->crypto.iv, ivSize)) {
if (!reader.ReadArray(sample->mCrypto.iv, ivSize)) {
return nullptr;
}
@ -143,13 +142,13 @@ MP4Sample* SampleIterator::GetNext()
}
for (size_t i = 0; i < count; i++) {
sample->crypto.plain_sizes.AppendElement(reader.ReadU16());
sample->crypto.encrypted_sizes.AppendElement(reader.ReadU32());
sample->mCrypto.plain_sizes.AppendElement(reader.ReadU16());
sample->mCrypto.encrypted_sizes.AppendElement(reader.ReadU32());
}
} else {
// No subsample information means the entire sample is encrypted.
sample->crypto.plain_sizes.AppendElement(0);
sample->crypto.encrypted_sizes.AppendElement(sample->size);
sample->mCrypto.plain_sizes.AppendElement(0);
sample->mCrypto.encrypted_sizes.AppendElement(sample->mSize);
}
}

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

@ -16,14 +16,11 @@ MP4AudioDemuxer::Seek(Microseconds aTime)
mDemuxer->SeekAudio(aTime);
}
MediaSample*
already_AddRefed<MediaRawData>
MP4AudioDemuxer::DemuxSample()
{
nsAutoPtr<MP4Sample> sample(mDemuxer->DemuxAudioSample());
if (!sample) {
return nullptr;
}
return new MediaSample(sample.forget());
nsRefPtr<MediaRawData> sample(mDemuxer->DemuxAudioSample());
return sample.forget();
}
Microseconds
@ -38,14 +35,11 @@ MP4VideoDemuxer::Seek(Microseconds aTime)
mDemuxer->SeekVideo(aTime);
}
MediaSample*
already_AddRefed<MediaRawData>
MP4VideoDemuxer::DemuxSample()
{
nsAutoPtr<MP4Sample> sample(mDemuxer->DemuxVideoSample());
if (!sample) {
return nullptr;
}
return new MediaSample(sample.forget());
nsRefPtr<MediaRawData> sample(mDemuxer->DemuxVideoSample());
return sample.forget();
}
Microseconds

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

@ -5,23 +5,15 @@
#ifndef TRACK_DEMUXER_H_
#define TRACK_DEMUXER_H_
namespace mp4_demuxer { class MP4Sample; }
template <class T> struct already_AddRefed;
namespace mozilla {
class MediaRawData;
class MediaByteRange;
typedef int64_t Microseconds;
class MediaSample {
public:
explicit MediaSample(mp4_demuxer::MP4Sample* aMp4Sample) : mMp4Sample(aMp4Sample)
{
}
nsAutoPtr<mp4_demuxer::MP4Sample> mMp4Sample;
};
class TrackDemuxer {
public:
TrackDemuxer() {}
@ -30,7 +22,7 @@ public:
virtual void Seek(Microseconds aTime) = 0;
// DemuxSample returns nullptr on end of stream or error.
virtual MediaSample* DemuxSample() = 0;
virtual already_AddRefed<MediaRawData> DemuxSample() = 0;
// Returns timestamp of next keyframe, or -1 if demuxer can't
// report this.

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

@ -7,17 +7,19 @@
#include <stdint.h>
namespace mozilla {
class MediaRawData;
}
namespace mp4_demuxer
{
class MP4Sample;
class Adts
{
public:
static int8_t GetFrequencyIndex(uint16_t aSamplesPerSecond);
static bool ConvertSample(uint16_t aChannelCount, int8_t aFrequencyIndex,
int8_t aProfile, MP4Sample* aSample);
int8_t aProfile, mozilla::MediaRawData* aSample);
};
}

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

@ -5,48 +5,49 @@
#ifndef MP4_DEMUXER_ANNEX_B_H_
#define MP4_DEMUXER_ANNEX_B_H_
#include "mp4_demuxer/DecoderData.h"
template <class T> struct already_AddRefed;
namespace mozilla {
class MediaRawData;
class DataBuffer;
}
namespace mp4_demuxer
{
class ByteReader;
class MP4Sample;
class AnnexB
{
public:
// All conversions assume size of NAL length field is 4 bytes.
// Convert a sample from AVCC format to Annex B.
static bool ConvertSampleToAnnexB(MP4Sample* aSample);
static bool ConvertSampleToAnnexB(mozilla::MediaRawData* aSample);
// Convert a sample from Annex B to AVCC.
// an AVCC extradata must not be set.
static bool ConvertSampleToAVCC(MP4Sample* aSample);
static bool ConvertSampleTo4BytesAVCC(MP4Sample* aSample);
static bool ConvertSampleToAVCC(mozilla::MediaRawData* aSample);
static bool ConvertSampleTo4BytesAVCC(mozilla::MediaRawData* aSample);
// Parse an AVCC extradata and construct the Annex B sample header.
static already_AddRefed<ByteBuffer> ConvertExtraDataToAnnexB(
const ByteBuffer* aExtraData);
static already_AddRefed<mozilla::DataBuffer> ConvertExtraDataToAnnexB(
const mozilla::DataBuffer* aExtraData);
// Extract SPS and PPS NALs from aSample, aSample must be in AVCC format.
// If aSample already contains an extradata with an SPS, it will be returned
// otherwise the SPS/PPS NALs are searched in-band.
static already_AddRefed<ByteBuffer> ExtractExtraData(
const MP4Sample* aSample);
static bool HasSPS(const MP4Sample* aSample);
static bool HasSPS(const ByteBuffer* aExtraData);
static already_AddRefed<mozilla::DataBuffer> ExtractExtraData(
const mozilla::MediaRawData* aSample);
static bool HasSPS(const mozilla::MediaRawData* aSample);
static bool HasSPS(const mozilla::DataBuffer* aExtraData);
// Returns true if format is AVCC and sample has valid extradata.
static bool IsAVCC(const MP4Sample* aSample);
static bool IsAVCC(const mozilla::MediaRawData* aSample);
// Returns true if format is AnnexB.
static bool IsAnnexB(const MP4Sample* aSample);
static bool IsAnnexB(const mozilla::MediaRawData* aSample);
// Return true if both extradata are equal.
static bool CompareExtraData(const ByteBuffer* aExtraData1,
const ByteBuffer* aExtraData2);
static bool CompareExtraData(const mozilla::DataBuffer* aExtraData1,
const mozilla::DataBuffer* aExtraData2);
private:
// AVCC box parser helper.
static void ConvertSPSOrPPS(ByteReader& aReader, uint8_t aCount,
ByteBuffer* aAnnexB);
mozilla::DataBuffer* aAnnexB);
};
} // namespace mp4_demuxer

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

@ -8,6 +8,7 @@
#include "mozilla/Endian.h"
#include "mozilla/Vector.h"
#include "nsTArray.h"
#include "MediaData.h"
namespace mp4_demuxer {
@ -32,6 +33,10 @@ public:
: mPtr(aData.Elements()), mRemaining(aData.Length()), mLength(aData.Length())
{
}
explicit ByteReader(const DataBuffer* aData)
: mPtr(aData->Elements()), mRemaining(aData->Length()), mLength(aData->Length())
{
}
void SetData(const nsTArray<uint8_t>& aData)
{

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

@ -8,7 +8,6 @@
#include "MediaData.h"
#include "mozilla/Types.h"
#include "mozilla/Vector.h"
#include "nsAutoPtr.h"
#include "nsRefPtr.h"
#include "nsString.h"
#include "nsTArray.h"
@ -24,16 +23,6 @@ namespace mp4_demuxer
class MP4Demuxer;
template <typename T>
class nsRcTArray : public nsTArray<T> {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsRcTArray);
private:
~nsRcTArray() {}
};
typedef nsRcTArray<uint8_t> ByteBuffer;
struct PsshInfo
{
PsshInfo() {}
@ -109,8 +98,8 @@ public:
, frequency_index(0)
, aac_profile(0)
, extended_profile(0)
, extra_data(new ByteBuffer)
, audio_specific_config(new ByteBuffer)
, extra_data(new mozilla::DataBuffer)
, audio_specific_config(new mozilla::DataBuffer)
{
}
@ -120,8 +109,8 @@ public:
int8_t frequency_index;
int8_t aac_profile;
int8_t extended_profile;
nsRefPtr<ByteBuffer> extra_data;
nsRefPtr<ByteBuffer> audio_specific_config;
nsRefPtr<mozilla::DataBuffer> extra_data;
nsRefPtr<mozilla::DataBuffer> audio_specific_config;
void Update(const stagefright::MetaData* aMetaData,
const char* aMimeType);
@ -140,7 +129,7 @@ public:
, display_height(0)
, image_width(0)
, image_height(0)
, extra_data(new ByteBuffer)
, extra_data(new mozilla::DataBuffer)
{
}
@ -150,7 +139,7 @@ public:
int32_t image_width;
int32_t image_height;
nsRefPtr<ByteBuffer> extra_data; // Unparsed AVCDecoderConfig payload.
nsRefPtr<mozilla::DataBuffer> extra_data; // Unparsed AVCDecoderConfig payload.
void Update(const stagefright::MetaData* aMetaData,
const char* aMimeType);
@ -158,34 +147,6 @@ public:
};
typedef int64_t Microseconds;
class MP4Sample
{
public:
MP4Sample();
virtual ~MP4Sample();
MP4Sample* Clone() const;
bool Pad(size_t aPaddingBytes);
Microseconds decode_timestamp;
Microseconds composition_timestamp;
Microseconds duration;
int64_t byte_offset;
bool is_sync_point;
uint8_t* data;
size_t size;
mozilla::CryptoSample crypto;
nsRefPtr<ByteBuffer> extra_data;
bool Prepend(const uint8_t* aData, size_t aSize);
bool Replace(const uint8_t* aData, size_t aSize);
nsAutoArrayPtr<uint8_t> extra_buffer;
private:
MP4Sample(const MP4Sample&); // Not implemented
};
}
#endif

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

@ -331,14 +331,14 @@ struct SPSData
class H264
{
public:
static bool DecodeSPSFromExtraData(const ByteBuffer* aExtraData, SPSData& aDest);
static bool DecodeSPSFromExtraData(const mozilla::DataBuffer* aExtraData, SPSData& aDest);
/* Extract RAW BYTE SEQUENCE PAYLOAD from NAL content.
Returns nullptr if invalid content.
This is compliant to ITU H.264 7.3.1 Syntax in tabular form NAL unit syntax
*/
static already_AddRefed<ByteBuffer> DecodeNALUnit(const ByteBuffer* aNAL);
static already_AddRefed<mozilla::DataBuffer> DecodeNALUnit(const mozilla::DataBuffer* aNAL);
/* Decode SPS NAL RBSP and fill SPSData structure */
static bool DecodeSPS(const ByteBuffer* aSPS, SPSData& aDest);
static bool DecodeSPS(const mozilla::DataBuffer* aSPS, SPSData& aDest);
// Ensure that SPS data makes sense, Return true if SPS data was, and false
// otherwise. If false, then content will be adjusted accordingly.
static bool EnsureSPSIsSane(SPSData& aSPS);

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

@ -20,7 +20,7 @@ class SampleIterator
{
public:
explicit SampleIterator(Index* aIndex);
MP4Sample* GetNext();
already_AddRefed<mozilla::MediaRawData> GetNext();
void Seek(Microseconds aTime);
Microseconds GetNextKeyframeTime();

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

@ -15,7 +15,7 @@ class MP4AudioDemuxer : public mozilla::TrackDemuxer {
public:
explicit MP4AudioDemuxer(MP4Demuxer* aDemuxer) : mDemuxer(aDemuxer) {}
virtual void Seek(Microseconds aTime) override;
virtual mozilla::MediaSample* DemuxSample() override;
virtual already_AddRefed<mozilla::MediaRawData> DemuxSample() override;
virtual Microseconds GetNextKeyframeTime() override;
private:
@ -26,7 +26,7 @@ class MP4VideoDemuxer : public mozilla::TrackDemuxer {
public:
explicit MP4VideoDemuxer(MP4Demuxer* aDemuxer) : mDemuxer(aDemuxer) {}
virtual void Seek(Microseconds aTime) override;
virtual mozilla::MediaSample* DemuxSample() override;
virtual already_AddRefed<mozilla::MediaRawData> DemuxSample() override;
virtual Microseconds GetNextKeyframeTime() override;
private:

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

@ -59,8 +59,8 @@ public:
// DemuxAudioSample and DemuxVideoSample functions
// return nullptr on end of stream or error.
MP4Sample* DemuxAudioSample();
MP4Sample* DemuxVideoSample();
already_AddRefed<mozilla::MediaRawData> DemuxAudioSample();
already_AddRefed<mozilla::MediaRawData> DemuxVideoSample();
const CryptoFile& Crypto() { return mCrypto; }
const AudioDecoderConfig& AudioConfig() { return mAudioConfig; }

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

@ -212,39 +212,39 @@ MP4Demuxer::SeekVideo(Microseconds aTime)
}
}
MP4Sample*
already_AddRefed<mozilla::MediaRawData>
MP4Demuxer::DemuxAudioSample()
{
mMonitor->AssertCurrentThreadOwns();
if (!mPrivate->mAudioIterator) {
return nullptr;
}
nsAutoPtr<MP4Sample> sample(mPrivate->mAudioIterator->GetNext());
nsRefPtr<mozilla::MediaRawData> sample(mPrivate->mAudioIterator->GetNext());
if (sample) {
if (sample->crypto.valid) {
sample->crypto.mode = mAudioConfig.crypto.mode;
sample->crypto.iv_size = mAudioConfig.crypto.iv_size;
sample->crypto.key.AppendElements(mAudioConfig.crypto.key);
if (sample->mCrypto.valid) {
sample->mCrypto.mode = mAudioConfig.crypto.mode;
sample->mCrypto.iv_size = mAudioConfig.crypto.iv_size;
sample->mCrypto.key.AppendElements(mAudioConfig.crypto.key);
}
}
return sample.forget();
}
MP4Sample*
already_AddRefed<MediaRawData>
MP4Demuxer::DemuxVideoSample()
{
mMonitor->AssertCurrentThreadOwns();
if (!mPrivate->mVideoIterator) {
return nullptr;
}
nsAutoPtr<MP4Sample> sample(mPrivate->mVideoIterator->GetNext());
nsRefPtr<mozilla::MediaRawData> sample(mPrivate->mVideoIterator->GetNext());
if (sample) {
sample->extra_data = mVideoConfig.extra_data;
if (sample->crypto.valid) {
sample->crypto.mode = mVideoConfig.crypto.mode;
sample->crypto.key.AppendElements(mVideoConfig.crypto.key);
sample->mExtraData = mVideoConfig.extra_data;
if (sample->mCrypto.valid) {
sample->mCrypto.mode = mVideoConfig.crypto.mode;
sample->mCrypto.key.AppendElements(mVideoConfig.crypto.key);
}
if (sample->composition_timestamp >= mNextKeyframeTime) {
if (sample->mTime >= mNextKeyframeTime) {
mNextKeyframeTime = mPrivate->mVideoIterator->GetNextKeyframeTime();
}
}