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

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: Address comments from PS4 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
« no previous file with comments | « media/base/stream_parser.h ('k') | media/base/stream_parser_buffer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 size_t num_itrs = buffer_queues.size();
37 std::vector<StreamParser::BufferQueue::const_iterator> itrs(num_itrs);
38 for (size_t i = 0; i < num_itrs; ++i)
39 itrs[i] = buffer_queues[i]->begin();
40
41 // |last_decode_timestamp| tracks the lower bound, if any, that all candidate
42 // buffers must not be less than. If |merged_buffers| already has buffers,
43 // initialize |last_decode_timestamp| to the decode timestamp of the last
44 // buffer in it.
45 base::TimeDelta last_decode_timestamp = kNoTimestamp();
46 if (!merged_buffers->empty())
47 last_decode_timestamp = merged_buffers->back()->GetDecodeTimestamp();
48
49 // Repeatedly select and append the next buffer from the candidate buffers
50 // until either:
51 // 1) returning false, to indicate detection of decreasing DTS in some queue,
52 // when a candidate buffer has decode timestamp below
53 // |last_decode_timestamp|, which means either an input buffer wasn't
54 // sorted correctly or had a buffer with decode timestamp below the last
55 // buffer, if any, in |merged_buffers|, or
56 // 2) returning true when all buffers have been merged successfully;
57 // equivalently, when all of the iterators in |itrs| have reached the end
58 // of their respective queue from |buffer_queues|.
59 // TODO(wolenetz/acolwell): Ideally, we would use a heap to store the head of
60 // all queues and pop the head with lowest decode timestamp in log(N) time.
61 // However, N will typically be small and usage of this implementation is
62 // meant to be short-term. See http://crbug.com/338484.
63 while (true) {
64 // Tracks which queue's iterator is pointing to the candidate buffer to
65 // append next, or -1 if no candidate buffers found. This indexes |itrs|.
66 int index_of_queue_with_next_decode_timestamp = -1;
67 base::TimeDelta next_decode_timestamp = kNoTimestamp();
68
69 // Scan each of the iterators for |buffer_queues| to find the candidate
70 // buffer, if any, that has the lowest decode timestamp.
71 for (size_t i = 0; i < num_itrs; ++i) {
72 if (itrs[i] == buffer_queues[i]->end())
73 continue;
74
75 // Extract the candidate buffer's decode timestamp.
76 base::TimeDelta ts = (*itrs[i])->GetDecodeTimestamp();
77
78 if (last_decode_timestamp != kNoTimestamp() &&
79 ts < last_decode_timestamp)
80 return false;
81
82 if (ts < next_decode_timestamp ||
83 next_decode_timestamp == kNoTimestamp()) {
84 // Remember the decode timestamp and queue iterator index for this
85 // potentially winning candidate buffer.
86 next_decode_timestamp = ts;
87 index_of_queue_with_next_decode_timestamp = i;
88 }
89 }
90
91 // All done if no further candidate buffers exist.
92 if (index_of_queue_with_next_decode_timestamp == -1)
93 return true;
94
95 // Otherwise, append the winning candidate buffer to |merged_buffers|,
96 // remember its decode timestamp as |last_decode_timestamp| now that it is
97 // the last buffer in |merged_buffers|, advance the corresponding
98 // input BufferQueue iterator, and continue.
99 scoped_refptr<StreamParserBuffer> buffer =
100 *itrs[index_of_queue_with_next_decode_timestamp];
101 last_decode_timestamp = buffer->GetDecodeTimestamp();
102 merged_buffers->push_back(buffer);
103 ++itrs[index_of_queue_with_next_decode_timestamp];
104 }
105 }
106
107 bool MergeBufferQueues(const StreamParser::BufferQueue& audio_buffers,
108 const StreamParser::BufferQueue& video_buffers,
109 const StreamParser::TextBufferQueueMap& text_buffers,
110 StreamParser::BufferQueue* merged_buffers) {
111 DCHECK(merged_buffers);
112
113 // Prepare vector containing pointers to any provided non-empty buffer queues.
114 std::vector<const StreamParser::BufferQueue*> buffer_queues;
115 if (!audio_buffers.empty())
116 buffer_queues.push_back(&audio_buffers);
117 if (!video_buffers.empty())
118 buffer_queues.push_back(&video_buffers);
119 for (StreamParser::TextBufferQueueMap::const_iterator map_itr =
120 text_buffers.begin();
121 map_itr != text_buffers.end();
122 map_itr++) {
123 if (!map_itr->second.empty())
124 buffer_queues.push_back(&(map_itr->second));
125 }
126
127 // Do the merge.
128 return MergeBufferQueuesInternal(buffer_queues, merged_buffers);
129 }
130
13 } // namespace media 131 } // namespace media
OLDNEW
« no previous file with comments | « media/base/stream_parser.h ('k') | media/base/stream_parser_buffer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698