зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1195723: [flac] P12. Add sniffer for streaming flac. r=kamidphish
MozReview-Commit-ID: P62v6vsXzs --HG-- extra : rebase_source : 37c365efbff607b10ad41ce8290556ded07783e2
This commit is contained in:
Родитель
6d13063ab5
Коммит
a637a5b7d5
|
@ -236,12 +236,42 @@ const uint8_t FrameHeader::CRC8Table[256] =
|
|||
class Frame {
|
||||
public:
|
||||
|
||||
// Find the next frame start in the current resource.
|
||||
// On exit return true, offset is set and resource points to the frame found.
|
||||
// The FLAC signature is made of 14 bits set to 1; however the 15th bit is
|
||||
// mandatorily set to 0, so we need to find either of 0xfffc or 0xfffd 2-bytes
|
||||
// signature. We first use a bitmask to see if 0xfc or 0xfd is present. And if
|
||||
// so we check for the whole signature.
|
||||
// aData must be pointing to a buffer at least
|
||||
// aLength + FLAC_MAX_FRAME_HEADER_SIZE bytes.
|
||||
int64_t FindNext(const uint8_t* aData, const uint32_t aLength)
|
||||
{
|
||||
uint32_t modOffset = aLength % 4;
|
||||
uint32_t i, j;
|
||||
|
||||
for (i = 0; i < modOffset; i++) {
|
||||
if ((BigEndian::readUint16(aData + i) & 0xfffe) == 0xfff8) {
|
||||
if (mHeader.Parse(aData + i)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (; i < aLength; i += 4) {
|
||||
uint32_t x = BigEndian::readUint32(aData + i);
|
||||
if (((x & ~(x + 0x01010101)) & 0x80808080)) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
if ((BigEndian::readUint16(aData + i + j) & 0xfffe) == 0xfff8) {
|
||||
if (mHeader.Parse(aData + i + j)) {
|
||||
return i + j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Find the next frame start in the current resource.
|
||||
// On exit return true, offset is set and resource points to the frame found.
|
||||
bool FindNext(MediaResourceIndex& aResource)
|
||||
{
|
||||
static const int BUFFER_SIZE = 4096;
|
||||
|
@ -261,6 +291,7 @@ public:
|
|||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (read < FLAC_MAX_FRAME_HEADER_SIZE) {
|
||||
// Assume that we can't have a valid frame in such small content, we
|
||||
// must have reached EOS.
|
||||
|
@ -270,32 +301,12 @@ public:
|
|||
}
|
||||
|
||||
const size_t bufSize = read + innerOffset - FLAC_MAX_FRAME_HEADER_SIZE;
|
||||
int64_t foundOffset =
|
||||
FindNext(reinterpret_cast<uint8_t*>(buffer.Elements()), bufSize);
|
||||
|
||||
const uint8_t* buf = reinterpret_cast<uint8_t*>(buffer.Elements());
|
||||
uint32_t modOffset = bufSize % 4;
|
||||
uint32_t i, j;
|
||||
|
||||
for (i = 0; i < modOffset; i++) {
|
||||
if ((BigEndian::readUint16(buf + i) & 0xfffe) == 0xfff8) {
|
||||
if (mHeader.Parse(buf + i)) {
|
||||
SetOffset(aResource, offset + i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (; i < bufSize; i += 4) {
|
||||
uint32_t x = BigEndian::readUint32(buf + i);
|
||||
if (((x & ~(x + 0x01010101)) & 0x80808080)) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
if ((BigEndian::readUint16(buf + i + j) & 0xfffe) == 0xfff8) {
|
||||
if (mHeader.Parse(buf + i + j)) {
|
||||
SetOffset(aResource, offset + i + j);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (foundOffset >= 0) {
|
||||
SetOffset(aResource, foundOffset + offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Scan the next block;
|
||||
|
@ -1039,4 +1050,15 @@ FlacTrackDemuxer::TimeAtEnd()
|
|||
return mParsedFramesDuration;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
FlacDemuxer::FlacSniffer(const uint8_t* aData, const uint32_t aLength)
|
||||
{
|
||||
if (aLength < FLAC_MAX_FRAME_HEADER_SIZE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
flac::Frame frame;
|
||||
return frame.FindNext(aData, aLength - FLAC_MAX_FRAME_HEADER_SIZE) >= 0;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -30,6 +30,9 @@ public:
|
|||
TrackInfo::TrackType aType, uint32_t aTrackNumber) override;
|
||||
bool IsSeekable() const override;
|
||||
|
||||
// Return true if a valid flac frame header could be found.
|
||||
static bool FlacSniffer(const uint8_t* aData, const uint32_t aLength);
|
||||
|
||||
private:
|
||||
bool InitInternal();
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "mozilla/ModuleUtils.h"
|
||||
#include "mp3sniff.h"
|
||||
#include "nestegg/nestegg.h"
|
||||
#include "FlacDemuxer.h"
|
||||
|
||||
#include "nsIClassInfoImpl.h"
|
||||
#include <algorithm>
|
||||
|
@ -120,6 +121,11 @@ static bool MatchesMP3(const uint8_t* aData, const uint32_t aLength)
|
|||
return mp3_sniff(aData, (long)aLength);
|
||||
}
|
||||
|
||||
static bool MatchesFLAC(const uint8_t* aData, const uint32_t aLength)
|
||||
{
|
||||
return mozilla::FlacDemuxer::FlacSniffer(aData, aLength);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMediaSniffer::GetMIMETypeFromContent(nsIRequest* aRequest,
|
||||
const uint8_t* aData,
|
||||
|
@ -179,6 +185,14 @@ nsMediaSniffer::GetMIMETypeFromContent(nsIRequest* aRequest,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Flac frames are generally big, often in excess of 24kB.
|
||||
// Using a size of MAX_BYTES_SNIFFED effectively means that we will only
|
||||
// recognize flac content if it starts with a frame.
|
||||
if (MatchesFLAC(aData, clampedLength)) {
|
||||
aSniffedType.AssignLiteral(AUDIO_FLAC);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Could not sniff the media type, we are required to set it to
|
||||
// application/octet-stream.
|
||||
aSniffedType.AssignLiteral(APPLICATION_OCTET_STREAM);
|
||||
|
|
Загрузка…
Ссылка в новой задаче