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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/base/stream_parser.h" 5 #include "media/base/stream_parser.h"
6 6
7 #include "media/base/buffers.h"
8 #include "media/base/stream_parser_buffer.h"
9
7 namespace media { 10 namespace media {
8 11
9 StreamParser::StreamParser() {} 12 StreamParser::StreamParser() {}
10 13
11 StreamParser::~StreamParser() {} 14 StreamParser::~StreamParser() {}
12 15
16 static bool MergeBufferQueuesInternal(
17 const std::vector<const StreamParser::BufferQueue*>& buffer_queues,
18 StreamParser::BufferQueue* merged_buffers) {
19 // Instead of std::merge usage, this method implements a custom merge because:
20 // 1) |buffer_queues| may contain N queues,
21 // 2) we must detect and return false if any of the queues in |buffer_queues|
22 // is unsorted, and
23 // 3) we must detect and return false if any of the buffers in |buffer_queues|
24 // has a decode timestamp prior to the last, if any, buffer in
25 // |merged_buffers|.
26 // TODO(wolenetz/acolwell): Refactor stream parsers to eliminate need for
27 // this large grain merge. See http://crbug.com/338484.
28
29 // Done if no inputs to merge.
30 if (buffer_queues.empty())
31 return true;
32
33 // Build a vector of iterators, one for each input, to traverse inputs.
34 // The union of these iterators points to the set of candidate buffers
35 // for being appended to |merged_buffers|.
36 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.
37 for (size_t i = 0; i < buffer_queues.size(); ++i)
38 itrs.push_back(buffer_queues[i]->begin());
39
40 // |last_decode_timestamp| tracks the lower bound, if any, that all candidate
41 // buffers must not be less than. If |merged_buffers| already has buffers,
42 // initialize |last_decode_timestamp| to the decode timestamp of the last
43 // buffer in it.
44 base::TimeDelta last_decode_timestamp = kNoTimestamp();
45 if (!merged_buffers->empty())
46 last_decode_timestamp = merged_buffers->back()->GetDecodeTimestamp();
47
48 // Repeatedly select and append the next buffer from the candidate buffers
49 // until either:
50 // 1) returning false, to indicate detection of decreasing DTS in some queue,
51 // when a candidate buffer has decode timestamp below
52 // |last_decode_timestamp|, which means either an input buffer wasn't
53 // sorted correctly or had a buffer with decode timestamp below the last
54 // buffer, if any, in |merged_buffers|, or
55 // 2) returning true when all buffers have been merged successfully;
56 // equivalently, when all of the iterators in |itrs| have reached the end
57 // of their respective queue from |buffer_queues|.
58 while (true) {
59 // Tracks which queue's iterator is pointing to the candidate buffer to
60 // append next, or -1 if no candidate buffers found. This indexes |itrs|.
61 int index_of_queue_with_next_decode_timestamp = -1;
62 base::TimeDelta next_decode_timestamp = kNoTimestamp();
63
64 // Scan each of the iterators for |buffer_queues| to find the candidate
65 // buffer, if any, that has the lowest decode timestamp.
66 for (size_t i = 0; i < buffer_queues.size(); ++i) {
67 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.
68 // Extract the candidate buffer's decode timestamp.
69 base::TimeDelta ts = (*itrs[i])->GetDecodeTimestamp();
70
71 if (last_decode_timestamp != kNoTimestamp() &&
72 ts < last_decode_timestamp)
73 return false;
74
75 if (ts < next_decode_timestamp ||
76 next_decode_timestamp == kNoTimestamp()) {
77 // Remember the decode timestamp and queue iterator index for this
78 // potentially winning candidate buffer.
79 next_decode_timestamp = ts;
80 index_of_queue_with_next_decode_timestamp = i;
81 }
82 }
83 }
xhwang 2014/02/06 00:36:32 This block is inefficient. Ideally, we should use
wolenetz 2014/02/06 23:56:03 Done.
84
85 // All done if no further candidate buffers exist.
86 if (index_of_queue_with_next_decode_timestamp == -1)
87 return true;
88
89 // Otherwise, append the winning candidate buffer to |merged_buffers|,
90 // remember its decode timestamp as |last_decode_timestamp| now that it is
91 // the last buffer in |merged_buffers|, advance the corresponding
92 // input BufferQueue iterator, and continue.
93 scoped_refptr<StreamParserBuffer> buffer =
94 *itrs[index_of_queue_with_next_decode_timestamp];
95 last_decode_timestamp = buffer->GetDecodeTimestamp();
96 merged_buffers->push_back(buffer);
97 ++itrs[index_of_queue_with_next_decode_timestamp];
98 }
99 }
100
101 bool MergeBufferQueues(const StreamParser::BufferQueue& audio_buffers,
102 const StreamParser::BufferQueue& video_buffers,
103 const StreamParser::TextBufferQueueMap& text_buffers,
104 StreamParser::BufferQueue* merged_buffers) {
105 DCHECK(merged_buffers);
106
107 // Prepare vector containing pointers to any provided non-empty buffer queues.
108 std::vector<const StreamParser::BufferQueue*> buffer_queues;
109 if (!audio_buffers.empty())
110 buffer_queues.push_back(&audio_buffers);
111 if (!video_buffers.empty())
112 buffer_queues.push_back(&video_buffers);
113 for (StreamParser::TextBufferQueueMap::const_iterator map_itr =
114 text_buffers.begin();
115 map_itr != text_buffers.end();
116 map_itr++) {
117 if (!map_itr->second.empty())
118 buffer_queues.push_back(&(map_itr->second));
119 }
120
121 // Do the merge.
122 return MergeBufferQueuesInternal(buffer_queues, merged_buffers);
123 }
124
13 } // namespace media 125 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698