Bug 1411525 - use BufferReader in flac/ogg parser. r?kinetik
MozReview-Commit-ID: 5chnxLnpqmY
--- a/dom/media/flac/FlacDemuxer.cpp
+++ b/dom/media/flac/FlacDemuxer.cpp
@@ -417,27 +417,28 @@ public:
mFirstFrame = mFrame;
}
return mFrame.IsValid();
}
// Convenience methods to external FlacFrameParser ones.
bool IsHeaderBlock(const uint8_t* aPacket, size_t aLength) const
{
- return mParser.IsHeaderBlock(aPacket, aLength);
+ auto res = mParser.IsHeaderBlock(aPacket, aLength);
+ return res.isOk() ? res.unwrap() : false;
}
uint32_t HeaderBlockLength(const uint8_t* aPacket) const
{
return mParser.HeaderBlockLength(aPacket);
}
bool DecodeHeaderBlock(const uint8_t* aPacket, size_t aLength)
{
- return mParser.DecodeHeaderBlock(aPacket, aLength);
+ return mParser.DecodeHeaderBlock(aPacket, aLength).isOk();
}
bool HasFullMetadata() const { return mParser.HasFullMetadata(); }
AudioInfo Info() const { return mParser.mInfo; }
// Return a hash table with tag metadata.
MetadataTags* GetTags() const { return mParser.GetTags(); }
--- a/dom/media/flac/FlacFrameParser.cpp
+++ b/dom/media/flac/FlacFrameParser.cpp
@@ -1,22 +1,23 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 "FlacFrameParser.h"
-#include "mp4_demuxer/ByteReader.h"
#include "nsTArray.h"
#include "OggCodecState.h"
#include "OpusParser.h"
#include "VideoUtils.h"
+#include "mp4_demuxer/BufferReader.h"
+#include "mozilla/ResultExtensions.h"
-using mp4_demuxer::ByteReader;
+using mp4_demuxer::BufferReader;
namespace mozilla
{
#define OGG_FLAC_METADATA_TYPE_STREAMINFO 0x7F
#define FLAC_STREAMINFO_SIZE 34
#define BITMASK(x) ((1ULL << x)-1)
@@ -55,94 +56,101 @@ FlacFrameParser::HeaderBlockLength(const
if (aPacket[0] == 'f') {
// This must be the first block read, which contains the fLaC signature.
aPacket += 4;
extra += 4;
}
return (BigEndian::readUint32(aPacket) & BITMASK(24)) + extra;
}
-bool
+Result<Ok, nsresult>
FlacFrameParser::DecodeHeaderBlock(const uint8_t* aPacket, size_t aLength)
{
if (aLength < 4 || aPacket[0] == 0xff) {
// Not a header block.
- return false;
+ return Err(NS_ERROR_FAILURE);
}
- ByteReader br(aPacket, aLength);
+ BufferReader br(aPacket, aLength);
mPacketCount++;
if (aPacket[0] == 'f') {
if (mPacketCount != 1 || memcmp(br.Read(4), "fLaC", 4) ||
br.Remaining() != FLAC_STREAMINFO_SIZE + 4) {
- return false;
+ return Err(NS_ERROR_FAILURE);
}
}
- uint8_t blockHeader = br.ReadU8();
+ uint8_t blockHeader;
+ MOZ_TRY_VAR(blockHeader, br.ReadU8());
// blockType is a misnomer as it could indicate here either a packet type
// should it points to the start of a Flac in Ogg metadata, or an actual
// block type as per the flac specification.
uint32_t blockType = blockHeader & 0x7f;
bool lastBlock = blockHeader & 0x80;
if (blockType == OGG_FLAC_METADATA_TYPE_STREAMINFO) {
if (mPacketCount != 1 || memcmp(br.Read(4), "FLAC", 4) ||
br.Remaining() != FLAC_STREAMINFO_SIZE + 12) {
- return false;
+ return Err(NS_ERROR_FAILURE);
}
- uint32_t major = br.ReadU8();
+ uint32_t major;
+ MOZ_TRY_VAR(major, br.ReadU8());
if (major != 1) {
// unsupported version;
- return false;
+ return Err(NS_ERROR_FAILURE);
}
- br.ReadU8(); // minor version
- mNumHeaders = Some(uint32_t(br.ReadU16()));
+ MOZ_TRY(br.ReadU8()); // minor version
+ uint32_t header;
+ MOZ_TRY_VAR(header, br.ReadU16());
+ mNumHeaders = Some(header);
br.Read(4); // fLaC
- blockType = br.ReadU8() & BITMASK(7);
+ MOZ_TRY_VAR(blockType, br.ReadU8());
+ blockType &= BITMASK(7);
// First METADATA_BLOCK_STREAMINFO
if (blockType != FLAC_METADATA_TYPE_STREAMINFO) {
// First block must be a stream info.
- return false;
+ return Err(NS_ERROR_FAILURE);
}
}
- uint32_t blockDataSize = br.ReadU24();
+ uint32_t blockDataSize;
+ MOZ_TRY_VAR(blockDataSize, br.ReadU24());
const uint8_t* blockDataStart = br.Peek(blockDataSize);
if (!blockDataStart) {
// Incomplete block.
- return false;
+ return Err(NS_ERROR_FAILURE);
}
switch (blockType) {
case FLAC_METADATA_TYPE_STREAMINFO:
{
if (mPacketCount != 1 || blockDataSize != FLAC_STREAMINFO_SIZE) {
// STREAMINFO must be the first metadata block found, and its size
// is constant.
- return false;
+ return Err(NS_ERROR_FAILURE);
}
- mMinBlockSize = br.ReadU16();
- mMaxBlockSize = br.ReadU16();
- mMinFrameSize = br.ReadU24();
- mMaxFrameSize = br.ReadU24();
+ MOZ_TRY_VAR(mMinBlockSize, br.ReadU16());
+ MOZ_TRY_VAR(mMaxBlockSize, br.ReadU16());
+ MOZ_TRY_VAR(mMinFrameSize, br.ReadU24());
+ MOZ_TRY_VAR(mMaxFrameSize, br.ReadU24());
- uint64_t blob = br.ReadU64();
+ uint64_t blob;
+ MOZ_TRY_VAR(blob, br.ReadU64());
uint32_t sampleRate = (blob >> 44) & BITMASK(20);
if (!sampleRate) {
- return false;
+ return Err(NS_ERROR_FAILURE);
}
uint32_t numChannels = ((blob >> 41) & BITMASK(3)) + 1;
if (numChannels > FLAC_MAX_CHANNELS) {
- return false;
+ return Err(NS_ERROR_FAILURE);
}
uint32_t bps = ((blob >> 36) & BITMASK(5)) + 1;
if (bps > 24) {
- return false;
+ return Err(NS_ERROR_FAILURE);
}
mNumFrames = blob & BITMASK(36);
mInfo.mMimeType = "audio/flac";
mInfo.mRate = sampleRate;
mInfo.mChannels = numChannels;
mInfo.mBitDepth = bps;
mInfo.mCodecSpecificConfig->AppendElements(blockDataStart, blockDataSize);
@@ -150,85 +158,84 @@ FlacFrameParser::DecodeHeaderBlock(const
mInfo.mDuration = duration.IsValid() ? duration : media::TimeUnit::Zero();
mParser = new OpusParser;
break;
}
case FLAC_METADATA_TYPE_VORBIS_COMMENT:
{
if (!mParser) {
// We must have seen a valid streaminfo first.
- return false;
+ return Err(NS_ERROR_FAILURE);
}
nsTArray<uint8_t> comments(blockDataSize + 8);
comments.AppendElements("OpusTags", 8);
comments.AppendElements(blockDataStart, blockDataSize);
if (!mParser->DecodeTags(comments.Elements(), comments.Length())) {
- return false;
+ return Err(NS_ERROR_FAILURE);
}
break;
}
default:
break;
}
if (mNumHeaders && mPacketCount > mNumHeaders.ref() + 1) {
// Received too many header block. assuming invalid.
- return false;
+ return Err(NS_ERROR_FAILURE);
}
if (lastBlock || (mNumHeaders && mNumHeaders.ref() + 1 == mPacketCount)) {
mFullMetadata = true;
}
- return true;
+ return Ok();
}
int64_t
FlacFrameParser::BlockDuration(const uint8_t* aPacket, size_t aLength) const
{
if (!mInfo.IsValid()) {
return -1;
}
if (mMinBlockSize == mMaxBlockSize) {
// block size is fixed, use this instead of looking at the frame header.
return mMinBlockSize;
}
// TODO
return 0;
}
-bool
+Result<bool, nsresult>
FlacFrameParser::IsHeaderBlock(const uint8_t* aPacket, size_t aLength) const
{
// Ogg Flac header
// The one-byte packet type 0x7F
// The four-byte ASCII signature "FLAC", i.e. 0x46, 0x4C, 0x41, 0x43
// Flac header:
// "fLaC", the FLAC stream marker in ASCII, meaning byte 0 of the stream is 0x66, followed by 0x4C 0x61 0x43
// If we detect either a ogg or plain flac header, then it must be valid.
if (aLength < 4 || aPacket[0] == 0xff) {
// A header is at least 4 bytes.
return false;
}
if (aPacket[0] == 0x7f) {
// Ogg packet
- ByteReader br(aPacket + 1, aLength - 1);
+ BufferReader br(aPacket + 1, aLength - 1);
const uint8_t* signature = br.Read(4);
return signature && !memcmp(signature, "FLAC", 4);
}
- ByteReader br(aPacket, aLength - 1);
+ BufferReader br(aPacket, aLength - 1);
const uint8_t* signature = br.Read(4);
if (signature && !memcmp(signature, "fLaC", 4)) {
// Flac start header, must have STREAMINFO as first metadata block;
- if (!br.CanRead8()) {
- return false;
- }
- uint32_t blockType = br.ReadU8() & 0x7f;
+ uint32_t blockType;
+ MOZ_TRY_VAR(blockType, br.ReadU8());
+ blockType &= 0x7f;
return blockType == FLAC_METADATA_TYPE_STREAMINFO;
}
char type = aPacket[0] & 0x7f;
return type >= 1 && type <= 6;
}
MetadataTags*
FlacFrameParser::GetTags() const
--- a/dom/media/flac/FlacFrameParser.h
+++ b/dom/media/flac/FlacFrameParser.h
@@ -3,16 +3,17 @@
/* 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/. */
#ifndef FLAC_FRAME_PARSER_H_
#define FLAC_FRAME_PARSER_H_
#include "mozilla/Maybe.h"
+#include "mozilla/Result.h"
#include "nsAutoPtr.h"
#include "MediaDecoder.h" // For MetadataTags
#include "MediaInfo.h"
#include "MediaResource.h"
namespace mozilla
{
@@ -31,22 +32,22 @@ class OpusParser;
// (https://xiph.org/flac/format.html#frame_header)
class FlacFrameParser
{
public:
FlacFrameParser();
~FlacFrameParser();
- bool IsHeaderBlock(const uint8_t* aPacket, size_t aLength) const;
+ Result<bool, nsresult> IsHeaderBlock(const uint8_t* aPacket, size_t aLength) const;
// Return the length of the block header (METADATA_BLOCK_HEADER+
// METADATA_BLOCK_DATA), aPacket must point to at least 4
// bytes and to a valid block header start (as determined by IsHeaderBlock).
uint32_t HeaderBlockLength(const uint8_t* aPacket) const;
- bool DecodeHeaderBlock(const uint8_t* aPacket, size_t aLength);
+ Result<Ok, nsresult> DecodeHeaderBlock(const uint8_t* aPacket, size_t aLength);
bool HasFullMetadata() const { return mFullMetadata; }
// Return the duration in frames found in the block. -1 if error
// such as invalid packet.
int64_t BlockDuration(const uint8_t* aPacket, size_t aLength) const;
// Return a hash table with tag metadata.
MetadataTags* GetTags() const;
--- a/dom/media/ogg/OggCodecState.cpp
+++ b/dom/media/ogg/OggCodecState.cpp
@@ -1312,17 +1312,17 @@ OpusState::PacketOutAsMediaRawData()
FlacState::FlacState(ogg_page* aBosPage)
: OggCodecState(aBosPage, true)
{
}
bool
FlacState::DecodeHeader(OggPacketPtr aPacket)
{
- if (!mParser.DecodeHeaderBlock(aPacket->packet, aPacket->bytes)) {
+ if (mParser.DecodeHeaderBlock(aPacket->packet, aPacket->bytes).isErr()) {
return false;
}
if (mParser.HasFullMetadata()) {
mDoneReadingHeaders = true;
}
return true;
}
@@ -1344,17 +1344,18 @@ int64_t
FlacState::PacketDuration(ogg_packet* aPacket)
{
return mParser.BlockDuration(aPacket->packet, aPacket->bytes);
}
bool
FlacState::IsHeader(ogg_packet* aPacket)
{
- return mParser.IsHeaderBlock(aPacket->packet, aPacket->bytes);
+ auto res = mParser.IsHeaderBlock(aPacket->packet, aPacket->bytes);
+ return res.isOk() ? res.unwrap() : false;
}
nsresult
FlacState::PageIn(ogg_page* aPage)
{
if (!mActive) {
return NS_OK;
}
--- a/media/libstagefright/binding/include/mp4_demuxer/BufferReader.h
+++ b/media/libstagefright/binding/include/mp4_demuxer/BufferReader.h
@@ -48,110 +48,110 @@ public:
size_t Offset() const
{
return mLength - mRemaining;
}
size_t Remaining() const { return mRemaining; }
- Result<uint8_t, nsresult> ReadU8()
+ mozilla::Result<uint8_t, nsresult> ReadU8()
{
auto ptr = Read(1);
if (!ptr) {
NS_WARNING("Failed to read data");
return mozilla::Err(NS_ERROR_FAILURE);
}
return *ptr;
}
- Result<uint16_t, nsresult> ReadU16()
+ mozilla::Result<uint16_t, nsresult> ReadU16()
{
auto ptr = Read(2);
if (!ptr) {
NS_WARNING("Failed to read data");
return mozilla::Err(NS_ERROR_FAILURE);
}
return mozilla::BigEndian::readUint16(ptr);
}
- Result<int16_t, nsresult> ReadLE16()
+ mozilla::Result<int16_t, nsresult> ReadLE16()
{
auto ptr = Read(2);
if (!ptr) {
NS_WARNING("Failed to read data");
return mozilla::Err(NS_ERROR_FAILURE);
}
return mozilla::LittleEndian::readInt16(ptr);
}
- Result<uint32_t, nsresult> ReadU24()
+ mozilla::Result<uint32_t, nsresult> ReadU24()
{
auto ptr = Read(3);
if (!ptr) {
NS_WARNING("Failed to read data");
return mozilla::Err(NS_ERROR_FAILURE);
}
return ptr[0] << 16 | ptr[1] << 8 | ptr[2];
}
- Result<int32_t, nsresult> Read24()
+ mozilla::Result<int32_t, nsresult> Read24()
{
auto res = ReadU24();
if (res.isErr()) {
return mozilla::Err(NS_ERROR_FAILURE);
}
return (int32_t)res.unwrap();
}
- Result<int32_t, nsresult> ReadLE24()
+ mozilla::Result<int32_t, nsresult> ReadLE24()
{
auto ptr = Read(3);
if (!ptr) {
NS_WARNING("Failed to read data");
return mozilla::Err(NS_ERROR_FAILURE);
}
int32_t result = int32_t(ptr[2] << 16 | ptr[1] << 8 | ptr[0]);
if (result & 0x00800000u) {
result -= 0x1000000;
}
return result;
}
- Result<uint32_t, nsresult> ReadU32()
+ mozilla::Result<uint32_t, nsresult> ReadU32()
{
auto ptr = Read(4);
if (!ptr) {
NS_WARNING("Failed to read data");
return mozilla::Err(NS_ERROR_FAILURE);
}
return mozilla::BigEndian::readUint32(ptr);
}
- Result<int32_t, nsresult> Read32()
+ mozilla::Result<int32_t, nsresult> Read32()
{
auto ptr = Read(4);
if (!ptr) {
NS_WARNING("Failed to read data");
return mozilla::Err(NS_ERROR_FAILURE);
}
return mozilla::BigEndian::readInt32(ptr);
}
- Result<uint64_t, nsresult> ReadU64()
+ mozilla::Result<uint64_t, nsresult> ReadU64()
{
auto ptr = Read(8);
if (!ptr) {
NS_WARNING("Failed to read data");
return mozilla::Err(NS_ERROR_FAILURE);
}
return mozilla::BigEndian::readUint64(ptr);
}
- Result<int64_t, nsresult> Read64()
+ mozilla::Result<int64_t, nsresult> Read64()
{
auto ptr = Read(8);
if (!ptr) {
NS_WARNING("Failed to read data");
return mozilla::Err(NS_ERROR_FAILURE);
}
return mozilla::BigEndian::readInt64(ptr);
}