gecko-dev/dom/media/mp4/DecoderData.cpp

149 строки
4.7 KiB
C++

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "Adts.h"
#include "AnnexB.h"
#include "BufferReader.h"
#include "DecoderData.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/EndianUtils.h"
#include "VideoUtils.h"
// OpusDecoder header is really needed only by MP4 in rust
#include "OpusDecoder.h"
#include "mp4parse.h"
using mozilla::media::TimeUnit;
namespace mozilla
{
mozilla::Result<mozilla::Ok, nsresult>
CryptoFile::DoUpdate(const uint8_t* aData, size_t aLength)
{
BufferReader reader(aData, aLength);
while (reader.Remaining()) {
PsshInfo psshInfo;
if (!reader.ReadArray(psshInfo.uuid, 16)) {
return mozilla::Err(NS_ERROR_FAILURE);
}
if (!reader.CanReadType<uint32_t>()) {
return mozilla::Err(NS_ERROR_FAILURE);
}
auto length = reader.ReadType<uint32_t>();
if (!reader.ReadArray(psshInfo.data, length)) {
return mozilla::Err(NS_ERROR_FAILURE);
}
pssh.AppendElement(psshInfo);
}
return mozilla::Ok();
}
bool
MP4AudioInfo::IsValid() const
{
return mChannels > 0 && mRate > 0 &&
// Accept any mime type here, but if it's aac, validate the profile.
(!mMimeType.EqualsLiteral("audio/mp4a-latm") ||
mProfile > 0 || mExtendedProfile > 0);
}
static void
UpdateTrackProtectedInfo(mozilla::TrackInfo& aConfig,
const Mp4parseSinfInfo& aSinf)
{
if (aSinf.is_encrypted != 0) {
aConfig.mCrypto.mValid = true;
aConfig.mCrypto.mMode = aSinf.is_encrypted;
aConfig.mCrypto.mIVSize = aSinf.iv_size;
aConfig.mCrypto.mKeyId.AppendElements(aSinf.kid.data, aSinf.kid.length);
}
}
void
MP4AudioInfo::Update(const Mp4parseTrackInfo* track,
const Mp4parseTrackAudioInfo* audio)
{
UpdateTrackProtectedInfo(*this, audio->protected_data);
if (track->codec == MP4PARSE_CODEC_OPUS) {
mMimeType = NS_LITERAL_CSTRING("audio/opus");
// The Opus decoder expects the container's codec delay or
// pre-skip value, in microseconds, as a 64-bit int at the
// start of the codec-specific config blob.
MOZ_ASSERT(audio->extra_data.data);
MOZ_ASSERT(audio->extra_data.length >= 12);
uint16_t preskip =
mozilla::LittleEndian::readUint16(audio->extra_data.data + 10);
mozilla::OpusDataDecoder::AppendCodecDelay(mCodecSpecificConfig,
mozilla::FramesToUsecs(preskip, 48000).value());
} else if (track->codec == MP4PARSE_CODEC_AAC) {
mMimeType = NS_LITERAL_CSTRING("audio/mp4a-latm");
} else if (track->codec == MP4PARSE_CODEC_FLAC) {
mMimeType = NS_LITERAL_CSTRING("audio/flac");
} else if (track->codec == MP4PARSE_CODEC_MP3) {
mMimeType = NS_LITERAL_CSTRING("audio/mpeg");
}
mRate = audio->sample_rate;
mChannels = audio->channels;
mBitDepth = audio->bit_depth;
mExtendedProfile = audio->profile;
mDuration = TimeUnit::FromMicroseconds(track->duration);
mMediaTime = TimeUnit::FromMicroseconds(track->media_time);
mTrackId = track->track_id;
// In stagefright, mProfile is kKeyAACProfile, mExtendedProfile is kKeyAACAOT.
// Both are from audioObjectType in AudioSpecificConfig.
if (audio->profile <= 4) {
mProfile = audio->profile;
}
if (audio->extra_data.length > 0) {
mExtraData->AppendElements(audio->extra_data.data,
audio->extra_data.length);
}
if (audio->codec_specific_config.length > 0) {
mCodecSpecificConfig->AppendElements(audio->codec_specific_config.data,
audio->codec_specific_config.length);
}
}
void
MP4VideoInfo::Update(const Mp4parseTrackInfo* track,
const Mp4parseTrackVideoInfo* video)
{
UpdateTrackProtectedInfo(*this, video->protected_data);
if (track->codec == MP4PARSE_CODEC_AVC) {
mMimeType = NS_LITERAL_CSTRING("video/avc");
} else if (track->codec == MP4PARSE_CODEC_VP9) {
mMimeType = NS_LITERAL_CSTRING("video/vp9");
} else if (track->codec == MP4PARSE_CODEC_MP4V) {
mMimeType = NS_LITERAL_CSTRING("video/mp4v-es");
}
mTrackId = track->track_id;
mDuration = TimeUnit::FromMicroseconds(track->duration);
mMediaTime = TimeUnit::FromMicroseconds(track->media_time);
mDisplay.width = video->display_width;
mDisplay.height = video->display_height;
mImage.width = video->image_width;
mImage.height = video->image_height;
mRotation = ToSupportedRotation(video->rotation);
if (video->extra_data.data) {
mExtraData->AppendElements(video->extra_data.data, video->extra_data.length);
}
}
bool
MP4VideoInfo::IsValid() const
{
return (mDisplay.width > 0 && mDisplay.height > 0) ||
(mImage.width > 0 && mImage.height > 0);
}
}