Bug 1329480: [MSE] Do not reject partial boxes. r?gerald
Partial content less than 8 bytes long was incorrectly rejected.
We now assume that content is valid unless it is explicitly incorrect (bad box type)
MozReview-Commit-ID: 8L32mNVjzxh
--- a/dom/media/mediasource/ContainerParser.cpp
+++ b/dom/media/mediasource/ContainerParser.cpp
@@ -15,16 +15,17 @@
#include "MediaData.h"
#ifdef MOZ_FMP4
#include "MP4Stream.h"
#include "mp4_demuxer/AtomType.h"
#include "mp4_demuxer/ByteReader.h"
#endif
#include "nsAutoPtr.h"
#include "SourceBufferResource.h"
+#include <algorithm>
extern mozilla::LogModule* GetMediaSourceSamplesLog();
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define MSE_DEBUG(name, arg, ...) MOZ_LOG(GetMediaSourceSamplesLog(), mozilla::LogLevel::Debug, (TOSTRING(name) "(%p:%s)::%s: " arg, this, mType.get(), __func__, ##__VA_ARGS__))
#define MSE_DEBUGV(name, arg, ...) MOZ_LOG(GetMediaSourceSamplesLog(), mozilla::LogLevel::Verbose, (TOSTRING(name) "(%p:%s)::%s: " arg, this, mType.get(), __func__, ##__VA_ARGS__))
@@ -343,27 +344,33 @@ public:
{}
MediaResult IsInitSegmentPresent(MediaByteBuffer* aData) override
{
ContainerParser::IsInitSegmentPresent(aData);
// Each MP4 atom has a chunk size and chunk type. The root chunk in an MP4
// file is the 'ftyp' atom followed by a file type. We just check for a
// vaguely valid 'ftyp' atom.
+ if (aData->Length() < 8) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
AtomParser parser(mType, aData);
if (!parser.IsValid()) {
return MediaResult(
NS_ERROR_FAILURE,
RESULT_DETAIL("Invalid Top-Level Box:%s", parser.LastInvalidBox()));
}
return parser.StartWithInitSegment() ? NS_OK : NS_ERROR_NOT_AVAILABLE;
}
MediaResult IsMediaSegmentPresent(MediaByteBuffer* aData) override
{
+ if (aData->Length() < 8) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
AtomParser parser(mType, aData);
if (!parser.IsValid()) {
return MediaResult(
NS_ERROR_FAILURE,
RESULT_DETAIL("Invalid Box:%s", parser.LastInvalidBox()));
}
return parser.StartWithMediaSegment() ? NS_OK : NS_ERROR_NOT_AVAILABLE;
}
@@ -391,30 +398,25 @@ private:
while (reader.Remaining() >= 8) {
uint64_t size = reader.ReadU32();
const uint8_t* typec = reader.Peek(4);
mp4_demuxer::AtomType type(reader.ReadU32());
MSE_DEBUGV(AtomParser ,"Checking atom:'%c%c%c%c' @ %u",
typec[0], typec[1], typec[2], typec[3],
(uint32_t)reader.Offset() - 8);
-
- for (const auto& boxType : validBoxes) {
- if (type == boxType) {
- mValid = true;
- break;
- }
- }
- if (!mValid) {
- // No point continuing.
+ if (std::find(std::begin(validBoxes), std::end(validBoxes), type)
+ == std::end(validBoxes)) {
+ // No valid box found, no point continuing.
mLastInvalidBox[0] = typec[0];
mLastInvalidBox[1] = typec[1];
mLastInvalidBox[2] = typec[2];
mLastInvalidBox[3] = typec[3];
mLastInvalidBox[4] = '\0';
+ mValid = false;
break;
}
if (mInitOffset.isNothing() &&
mp4_demuxer::AtomType(type) == initAtom) {
mInitOffset = Some(reader.Offset());
}
if (mMediaOffset.isNothing() &&
mp4_demuxer::AtomType(type) == mediaAtom) {
@@ -453,17 +455,17 @@ private:
return mMediaOffset.isSome() &&
(mInitOffset.isNothing() || mMediaOffset.ref() < mInitOffset.ref());
}
bool IsValid() const { return mValid; }
const char* LastInvalidBox() const { return mLastInvalidBox; }
private:
Maybe<size_t> mInitOffset;
Maybe<size_t> mMediaOffset;
- bool mValid = false;
+ bool mValid = true;
char mLastInvalidBox[5];
};
public:
MediaResult ParseStartAndEndTimestamps(MediaByteBuffer* aData,
int64_t& aStart,
int64_t& aEnd) override
{