Bug 1314533: [MSE] P1. Change member prototype. r?gerald draft
authorJean-Yves Avenard <jyavenard@mozilla.com>
Wed, 02 Nov 2016 21:29:13 +1100
changeset 434575 0604a27442c944b5daea4c19425dd0ce2adef74c
parent 434574 9b54183860a6946a15ddaad177096bc4b8a6b626
child 434576 0221ea0067d169fd83d3c2b7084bfd6e133a1931
push id34777
push userbmo:jyavenard@mozilla.com
push dateMon, 07 Nov 2016 01:27:18 +0000
reviewersgerald
bugs1314533
milestone52.0a1
Bug 1314533: [MSE] P1. Change member prototype. r?gerald MozReview-Commit-ID: L8H4oDoTm2b
dom/media/mediasource/ContainerParser.cpp
dom/media/mediasource/ContainerParser.h
dom/media/mediasource/TrackBuffersManager.cpp
dom/media/mediasource/gtest/TestContainerParser.cpp
--- a/dom/media/mediasource/ContainerParser.cpp
+++ b/dom/media/mediasource/ContainerParser.cpp
@@ -33,38 +33,38 @@ namespace mozilla {
 ContainerParser::ContainerParser(const nsACString& aType)
   : mHasInitData(false)
   , mType(aType)
 {
 }
 
 ContainerParser::~ContainerParser() = default;
 
-bool
+MediaResult
 ContainerParser::IsInitSegmentPresent(MediaByteBuffer* aData)
 {
   MSE_DEBUG(ContainerParser, "aLength=%u [%x%x%x%x]",
             aData->Length(),
             aData->Length() > 0 ? (*aData)[0] : 0,
             aData->Length() > 1 ? (*aData)[1] : 0,
             aData->Length() > 2 ? (*aData)[2] : 0,
             aData->Length() > 3 ? (*aData)[3] : 0);
-  return false;
+  return NS_ERROR_NOT_AVAILABLE;
 }
 
-bool
+MediaResult
 ContainerParser::IsMediaSegmentPresent(MediaByteBuffer* aData)
 {
   MSE_DEBUG(ContainerParser, "aLength=%u [%x%x%x%x]",
             aData->Length(),
             aData->Length() > 0 ? (*aData)[0] : 0,
             aData->Length() > 1 ? (*aData)[1] : 0,
             aData->Length() > 2 ? (*aData)[2] : 0,
             aData->Length() > 3 ? (*aData)[3] : 0);
-  return false;
+  return NS_ERROR_NOT_AVAILABLE;
 }
 
 bool
 ContainerParser::ParseStartAndEndTimestamps(MediaByteBuffer* aData,
                                             int64_t& aStart, int64_t& aEnd)
 {
   return false;
 }
@@ -118,17 +118,17 @@ public:
     : ContainerParser(aType)
     , mParser(0)
     , mOffset(0)
   {}
 
   static const unsigned NS_PER_USEC = 1000;
   static const unsigned USEC_PER_SEC = 1000000;
 
-  bool IsInitSegmentPresent(MediaByteBuffer* aData) override
+  MediaResult IsInitSegmentPresent(MediaByteBuffer* aData) override
   {
     ContainerParser::IsInitSegmentPresent(aData);
     // XXX: This is overly primitive, needs to collect data as it's appended
     // to the SB and handle, rather than assuming everything is present in a
     // single aData segment.
     // 0x1a45dfa3 // EBML
     // ...
     // DocType == "webm"
@@ -138,22 +138,22 @@ public:
                   // elements that follow)
     // 0x1549a966 // -> Segment Info
     // 0x1654ae6b // -> One or more Tracks
 
     // 0x1a45dfa3 // EBML
     if (aData->Length() >= 4 &&
         (*aData)[0] == 0x1a && (*aData)[1] == 0x45 && (*aData)[2] == 0xdf &&
         (*aData)[3] == 0xa3) {
-      return true;
+      return NS_OK;
     }
-    return false;
+    return NS_ERROR_NOT_AVAILABLE;
   }
 
-  bool IsMediaSegmentPresent(MediaByteBuffer* aData) override
+  MediaResult IsMediaSegmentPresent(MediaByteBuffer* aData) override
   {
     ContainerParser::IsMediaSegmentPresent(aData);
     // XXX: This is overly primitive, needs to collect data as it's appended
     // to the SB and handle, rather than assuming everything is present in a
     // single aData segment.
     // 0x1a45dfa3 // EBML
     // ...
     // DocType == "webm"
@@ -161,33 +161,34 @@ public:
     // 0x18538067 // Segment (must be "unknown" size)
     // 0x1549a966 // -> Segment Info
     // 0x1654ae6b // -> One or more Tracks
 
     // 0x1f43b675 // Cluster
     if (aData->Length() >= 4 &&
         (*aData)[0] == 0x1f && (*aData)[1] == 0x43 && (*aData)[2] == 0xb6 &&
         (*aData)[3] == 0x75) {
-      return true;
+      return NS_OK;
     }
     // 0x1c53bb6b // Cues
     if (aData->Length() >= 4 &&
         (*aData)[0] == 0x1c && (*aData)[1] == 0x53 && (*aData)[2] == 0xbb &&
         (*aData)[3] == 0x6b) {
-      return true;
+      return NS_OK;
     }
-    return false;
+    return NS_ERROR_NOT_AVAILABLE;
   }
 
   bool ParseStartAndEndTimestamps(MediaByteBuffer* aData,
                                   int64_t& aStart, int64_t& aEnd) override
   {
-    bool initSegment = IsInitSegmentPresent(aData);
+    bool initSegment = NS_SUCCEEDED(IsInitSegmentPresent(aData));
 
-    if (mLastMapping && (initSegment || IsMediaSegmentPresent(aData))) {
+    if (mLastMapping &&
+        (initSegment || NS_SUCCEEDED(IsMediaSegmentPresent(aData)))) {
       // The last data contained a complete cluster but we can only detect it
       // now that a new one is starting.
       // We use mOffset as end position to ensure that any blocks not reported
       // by WebMBufferParser are properly skipped.
       mCompleteMediaSegmentRange = MediaByteRange(mLastMapping.ref().mSyncOffset,
                                                   mOffset);
       mLastMapping.reset();
       MSE_DEBUG(WebMContainerParser, "New cluster found at start, ending previous one");
@@ -332,30 +333,30 @@ private:
 
 #ifdef MOZ_FMP4
 class MP4ContainerParser : public ContainerParser {
 public:
   explicit MP4ContainerParser(const nsACString& aType)
     : ContainerParser(aType)
   {}
 
-  bool IsInitSegmentPresent(MediaByteBuffer* aData) override
+  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.
     AtomParser parser(mType, aData);
-    return parser.StartWithInitSegment();
+    return parser.StartWithInitSegment() ? NS_OK : NS_ERROR_NOT_AVAILABLE;
   }
 
-  bool IsMediaSegmentPresent(MediaByteBuffer* aData) override
+  MediaResult IsMediaSegmentPresent(MediaByteBuffer* aData) override
   {
     AtomParser parser(mType, aData);
-    return parser.StartWithMediaSegment();
+    return parser.StartWithMediaSegment() ? NS_OK : NS_ERROR_NOT_AVAILABLE;
   }
 
 private:
   class AtomParser {
   public:
     AtomParser(const nsACString& aType, const MediaByteBuffer* aData)
     {
       const nsCString mType(aType); // for logging macro.
@@ -415,17 +416,17 @@ private:
     Maybe<size_t> mInitOffset;
     Maybe<size_t> mMediaOffset;
   };
 
 public:
   bool ParseStartAndEndTimestamps(MediaByteBuffer* aData,
                                   int64_t& aStart, int64_t& aEnd) override
   {
-    bool initSegment = IsInitSegmentPresent(aData);
+    bool initSegment = NS_SUCCEEDED(IsInitSegmentPresent(aData));
     if (initSegment) {
       mResource = new SourceBufferResource(NS_LITERAL_CSTRING("video/mp4"));
       mStream = new MP4Stream(mResource);
       // We use a timestampOffset of 0 for ContainerParser, and require
       // consumers of ParseStartAndEndTimestamps to add their timestamp offset
       // manually. This allows the ContainerParser to be shared across different
       // timestampOffsets.
       mParser = new mp4_demuxer::MoofParser(mStream, 0, /* aIsAudio = */ false);
@@ -549,56 +550,56 @@ public:
     // Return successfully parsed data.
     header.header_length = header_length;
     header.frame_length = header_length + data_length;
     header.aac_frames = frames;
     header.have_crc = have_crc;
     return true;
   }
 
-  bool IsInitSegmentPresent(MediaByteBuffer* aData) override
+  MediaResult IsInitSegmentPresent(MediaByteBuffer* aData) override
   {
     // Call superclass for logging.
     ContainerParser::IsInitSegmentPresent(aData);
 
     Header header;
     if (!Parse(aData, header)) {
-      return false;
+      return NS_ERROR_NOT_AVAILABLE;
     }
 
     MSE_DEBUGV(ADTSContainerParser, "%llu byte frame %d aac frames%s",
         (unsigned long long)header.frame_length, (int)header.aac_frames,
         header.have_crc ? " crc" : "");
 
-    return true;
+    return NS_OK;
   }
 
-  bool IsMediaSegmentPresent(MediaByteBuffer* aData) override
+  MediaResult IsMediaSegmentPresent(MediaByteBuffer* aData) override
   {
     // Call superclass for logging.
     ContainerParser::IsMediaSegmentPresent(aData);
 
     // Make sure we have a header so we know how long the frame is.
     // NB this assumes the media segment buffer starts with an
     // initialization segment. Since every frame has an ADTS header
     // this is a normal place to divide packets, but we can re-parse
     // mInitData if we need to handle separate media segments.
     Header header;
     if (!Parse(aData, header)) {
-      return false;
+      return NS_ERROR_NOT_AVAILABLE;
     }
     // We're supposed to return true as long as aData contains the
     // start of a media segment, whether or not it's complete. So
     // return true if we have any data beyond the header.
     if (aData->Length() <= header.header_length) {
-      return false;
+      return NS_ERROR_NOT_AVAILABLE;
     }
 
     // We should have at least a partial frame.
-    return true;
+    return NS_OK;
   }
 
   bool ParseStartAndEndTimestamps(MediaByteBuffer* aData,
                                   int64_t& aStart, int64_t& aEnd) override
   {
     // ADTS header.
     Header header;
     if (!Parse(aData, header)) {
--- a/dom/media/mediasource/ContainerParser.h
+++ b/dom/media/mediasource/ContainerParser.h
@@ -5,36 +5,43 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_CONTAINERPARSER_H_
 #define MOZILLA_CONTAINERPARSER_H_
 
 #include "mozilla/RefPtr.h"
 #include "nsString.h"
 #include "MediaResource.h"
+#include "MediaResult.h"
 
 namespace mozilla {
 
 class MediaByteBuffer;
 class SourceBufferResource;
 
 class ContainerParser {
 public:
   explicit ContainerParser(const nsACString& aType);
   virtual ~ContainerParser();
 
   // Return true if aData starts with an initialization segment.
   // The base implementation exists only for debug logging and is expected
   // to be called first from the overriding implementation.
-  virtual bool IsInitSegmentPresent(MediaByteBuffer* aData);
+  // Return NS_OK if segment is present, NS_ERROR_NOT_AVAILABLE if no sufficient
+  // data is currently available to make a determination. Any other value
+  // indicates an error.
+  virtual MediaResult IsInitSegmentPresent(MediaByteBuffer* aData);
 
   // Return true if aData starts with a media segment.
   // The base implementation exists only for debug logging and is expected
   // to be called first from the overriding implementation.
-  virtual bool IsMediaSegmentPresent(MediaByteBuffer* aData);
+  // Return NS_OK if segment is present, NS_ERROR_NOT_AVAILABLE if no sufficient
+  // data is currently available to make a determination. Any other value
+  // indicates an error.
+  virtual MediaResult IsMediaSegmentPresent(MediaByteBuffer* aData);
 
   // Parse aData to extract the start and end frame times from the media
   // segment.  aData may not start on a parser sync boundary.  Return true
   // if aStart and aEnd have been updated.
   virtual bool ParseStartAndEndTimestamps(MediaByteBuffer* aData,
                                           int64_t& aStart, int64_t& aEnd);
 
   // Compare aLhs and rHs, considering any error that may exist in the
--- a/dom/media/mediasource/TrackBuffersManager.cpp
+++ b/dom/media/mediasource/TrackBuffersManager.cpp
@@ -631,25 +631,25 @@ TrackBuffersManager::SegmentParserLoop()
     // ignored from the start of the input buffer.
     // We do not remove bytes from our input buffer. Instead we enforce that
     // our ContainerParser is able to skip over all data that is supposed to be
     // ignored.
 
     // 4. If the append state equals WAITING_FOR_SEGMENT, then run the following
     // steps:
     if (mSourceBufferAttributes->GetAppendState() == AppendState::WAITING_FOR_SEGMENT) {
-      if (mParser->IsInitSegmentPresent(mInputBuffer)) {
+      if (NS_SUCCEEDED(mParser->IsInitSegmentPresent(mInputBuffer))) {
         SetAppendState(AppendState::PARSING_INIT_SEGMENT);
         if (mFirstInitializationSegmentReceived) {
           // This is a new initialization segment. Obsolete the old one.
           RecreateParser(false);
         }
         continue;
       }
-      if (mParser->IsMediaSegmentPresent(mInputBuffer)) {
+      if (NS_SUCCEEDED(mParser->IsMediaSegmentPresent(mInputBuffer))) {
         SetAppendState(AppendState::PARSING_MEDIA_SEGMENT);
         mNewMediaSegmentStarted = true;
         continue;
       }
       // We have neither an init segment nor a media segment, this is either
       // invalid data or not enough data to detect a segment type.
       MSE_DEBUG("Found invalid or incomplete data.");
       NeedMoreData();
--- a/dom/media/mediasource/gtest/TestContainerParser.cpp
+++ b/dom/media/mediasource/gtest/TestContainerParser.cpp
@@ -42,43 +42,43 @@ TEST(ContainerParser, ADTSHeader) {
   parser = ContainerParser::CreateForMIMEType(NS_LITERAL_CSTRING("audio/aac"));
   ASSERT_NE(parser, nullptr);
 
   // Audio data should have no gaps.
   EXPECT_EQ(parser->GetRoundingError(), 0);
 
   // Test a valid header.
   RefPtr<MediaByteBuffer> header = make_adts_header();
-  EXPECT_TRUE(parser->IsInitSegmentPresent(header));
+  EXPECT_TRUE(NS_SUCCEEDED(parser->IsInitSegmentPresent(header)));
 
   // Test variations.
   uint8_t save = header->ElementAt(1);
   for (uint8_t i = 1; i < 3; ++i) {
     // Set non-zero layer.
     header->ReplaceElementAt(1, (header->ElementAt(1) & 0xf9) | (i << 1));
-    EXPECT_FALSE(parser->IsInitSegmentPresent(header))
+    EXPECT_FALSE(NS_SUCCEEDED(parser->IsInitSegmentPresent(header)))
       << "Accepted non-zero layer in header.";
   }
   header->ReplaceElementAt(1, save);
   save = header->ElementAt(2);
   header->ReplaceElementAt(2, (header->ElementAt(2) & 0x3b) | (15 << 2));
-  EXPECT_FALSE(parser->IsInitSegmentPresent(header))
+  EXPECT_FALSE(NS_SUCCEEDED(parser->IsInitSegmentPresent(header)))
     << "Accepted explicit frequency in header.";
   header->ReplaceElementAt(2, save);
 
   // Test a short header.
   header->SetLength(6);
-  EXPECT_FALSE(parser->IsInitSegmentPresent(header))
+  EXPECT_FALSE(NS_SUCCEEDED(parser->IsInitSegmentPresent(header)))
     << "Accepted too-short header.";
-  EXPECT_FALSE(parser->IsMediaSegmentPresent(header))
+  EXPECT_FALSE(NS_SUCCEEDED(parser->IsMediaSegmentPresent(header)))
     << "Found media segment when there was just a partial header.";
 
   // Test parse results.
   header = make_adts_header();
-  EXPECT_FALSE(parser->IsMediaSegmentPresent(header))
+  EXPECT_FALSE(NS_SUCCEEDED(parser->IsMediaSegmentPresent(header)))
     << "Found media segment when there was just a header.";
   int64_t start = 0;
   int64_t end = 0;
   EXPECT_FALSE(parser->ParseStartAndEndTimestamps(header, start, end));
 
   EXPECT_TRUE(parser->HasInitData());
   EXPECT_TRUE(parser->HasCompleteInitData());
   MediaByteBuffer* init = parser->InitData();