Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(933)

Unified Diff: media/base/stream_parser.cc

Issue 149153002: MSE: Add StreamParser buffer remuxing utility and tests (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased and addressed comments from PS2 Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/base/stream_parser.cc
diff --git a/media/base/stream_parser.cc b/media/base/stream_parser.cc
index 12409194fede3cf0fcaa3d1671b7301416457409..f087a4b4d83e0ecf32191f4c2a31e7e7ab78cb66 100644
--- a/media/base/stream_parser.cc
+++ b/media/base/stream_parser.cc
@@ -4,10 +4,122 @@
#include "media/base/stream_parser.h"
+#include "media/base/buffers.h"
+#include "media/base/stream_parser_buffer.h"
+
namespace media {
StreamParser::StreamParser() {}
StreamParser::~StreamParser() {}
+static bool MergeBufferQueuesInternal(
+ const std::vector<const StreamParser::BufferQueue*>& buffer_queues,
+ StreamParser::BufferQueue* merged_buffers) {
+ // Instead of std::merge usage, this method implements a custom merge because:
+ // 1) |buffer_queues| may contain N queues,
+ // 2) we must detect and return false if any of the queues in |buffer_queues|
+ // is unsorted, and
+ // 3) we must detect and return false if any of the buffers in |buffer_queues|
+ // has a decode timestamp prior to the last, if any, buffer in
+ // |merged_buffers|.
+ // TODO(wolenetz/acolwell): Refactor stream parsers to eliminate need for
+ // this large grain merge. See http://crbug.com/338484.
+
+ // Done if no inputs to merge.
+ if (buffer_queues.empty())
+ return true;
+
+ // Build a vector of iterators, one for each input, to traverse inputs.
+ // The union of these iterators points to the set of candidate buffers
+ // for being appended to |merged_buffers|.
+ std::vector<StreamParser::BufferQueue::const_iterator> itrs;
xhwang 2014/02/06 00:36:32 Use vector::vector(size_type n) to avoid expanding
wolenetz 2014/02/06 23:56:03 Done.
+ for (size_t i = 0; i < buffer_queues.size(); ++i)
+ itrs.push_back(buffer_queues[i]->begin());
+
+ // |last_decode_timestamp| tracks the lower bound, if any, that all candidate
+ // buffers must not be less than. If |merged_buffers| already has buffers,
+ // initialize |last_decode_timestamp| to the decode timestamp of the last
+ // buffer in it.
+ base::TimeDelta last_decode_timestamp = kNoTimestamp();
+ if (!merged_buffers->empty())
+ last_decode_timestamp = merged_buffers->back()->GetDecodeTimestamp();
+
+ // Repeatedly select and append the next buffer from the candidate buffers
+ // until either:
+ // 1) returning false, to indicate detection of decreasing DTS in some queue,
+ // when a candidate buffer has decode timestamp below
+ // |last_decode_timestamp|, which means either an input buffer wasn't
+ // sorted correctly or had a buffer with decode timestamp below the last
+ // buffer, if any, in |merged_buffers|, or
+ // 2) returning true when all buffers have been merged successfully;
+ // equivalently, when all of the iterators in |itrs| have reached the end
+ // of their respective queue from |buffer_queues|.
+ while (true) {
+ // Tracks which queue's iterator is pointing to the candidate buffer to
+ // append next, or -1 if no candidate buffers found. This indexes |itrs|.
+ int index_of_queue_with_next_decode_timestamp = -1;
+ base::TimeDelta next_decode_timestamp = kNoTimestamp();
+
+ // Scan each of the iterators for |buffer_queues| to find the candidate
+ // buffer, if any, that has the lowest decode timestamp.
+ for (size_t i = 0; i < buffer_queues.size(); ++i) {
+ if (itrs[i] != buffer_queues[i]->end()) {
xhwang 2014/02/06 00:36:32 if (itrs[i] == buffer_queues[i]->end()) continue
wolenetz 2014/02/06 23:56:03 Done.
+ // Extract the candidate buffer's decode timestamp.
+ base::TimeDelta ts = (*itrs[i])->GetDecodeTimestamp();
+
+ if (last_decode_timestamp != kNoTimestamp() &&
+ ts < last_decode_timestamp)
+ return false;
+
+ if (ts < next_decode_timestamp ||
+ next_decode_timestamp == kNoTimestamp()) {
+ // Remember the decode timestamp and queue iterator index for this
+ // potentially winning candidate buffer.
+ next_decode_timestamp = ts;
+ index_of_queue_with_next_decode_timestamp = i;
+ }
+ }
+ }
xhwang 2014/02/06 00:36:32 This block is inefficient. Ideally, we should use
wolenetz 2014/02/06 23:56:03 Done.
+
+ // All done if no further candidate buffers exist.
+ if (index_of_queue_with_next_decode_timestamp == -1)
+ return true;
+
+ // Otherwise, append the winning candidate buffer to |merged_buffers|,
+ // remember its decode timestamp as |last_decode_timestamp| now that it is
+ // the last buffer in |merged_buffers|, advance the corresponding
+ // input BufferQueue iterator, and continue.
+ scoped_refptr<StreamParserBuffer> buffer =
+ *itrs[index_of_queue_with_next_decode_timestamp];
+ last_decode_timestamp = buffer->GetDecodeTimestamp();
+ merged_buffers->push_back(buffer);
+ ++itrs[index_of_queue_with_next_decode_timestamp];
+ }
+}
+
+bool MergeBufferQueues(const StreamParser::BufferQueue& audio_buffers,
+ const StreamParser::BufferQueue& video_buffers,
+ const StreamParser::TextBufferQueueMap& text_buffers,
+ StreamParser::BufferQueue* merged_buffers) {
+ DCHECK(merged_buffers);
+
+ // Prepare vector containing pointers to any provided non-empty buffer queues.
+ std::vector<const StreamParser::BufferQueue*> buffer_queues;
+ if (!audio_buffers.empty())
+ buffer_queues.push_back(&audio_buffers);
+ if (!video_buffers.empty())
+ buffer_queues.push_back(&video_buffers);
+ for (StreamParser::TextBufferQueueMap::const_iterator map_itr =
+ text_buffers.begin();
+ map_itr != text_buffers.end();
+ map_itr++) {
+ if (!map_itr->second.empty())
+ buffer_queues.push_back(&(map_itr->second));
+ }
+
+ // Do the merge.
+ return MergeBufferQueuesInternal(buffer_queues, merged_buffers);
+}
+
} // namespace media

Powered by Google App Engine
This is Rietveld 408576698