OLD | NEW |
---|---|
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/webm/webm_cluster_parser.h" | 5 #include "media/webm/webm_cluster_parser.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "media/base/data_buffer.h" | 8 #include "media/base/data_buffer.h" |
9 #include "media/base/decrypt_config.h" | 9 #include "media/base/decrypt_config.h" |
10 #include "media/webm/webm_constants.h" | 10 #include "media/webm/webm_constants.h" |
11 | 11 |
12 namespace media { | 12 namespace media { |
13 | 13 |
14 WebMClusterParser::WebMClusterParser(int64 timecode_scale, | 14 WebMClusterParser::WebMClusterParser(int64 timecode_scale, |
15 int audio_track_num, | 15 int audio_track_num, |
16 base::TimeDelta audio_default_duration, | 16 base::TimeDelta audio_default_duration, |
17 int video_track_num, | 17 int video_track_num, |
18 base::TimeDelta video_default_duration, | 18 base::TimeDelta video_default_duration, |
19 const uint8* video_encryption_key_id, | 19 const uint8* video_encryption_key_id, |
20 int video_encryption_key_id_size) | 20 int video_encryption_key_id_size) |
21 : timecode_multiplier_(timecode_scale / 1000.0), | 21 : timecode_multiplier_(timecode_scale / 1000.0), |
22 audio_track_num_(audio_track_num), | |
23 audio_default_duration_(audio_default_duration), | |
24 video_track_num_(video_track_num), | |
25 video_default_duration_(video_default_duration), | |
26 video_encryption_key_id_size_(video_encryption_key_id_size), | 22 video_encryption_key_id_size_(video_encryption_key_id_size), |
27 parser_(kWebMIdCluster, this), | 23 parser_(kWebMIdCluster, this), |
28 last_block_timecode_(-1), | 24 last_block_timecode_(-1), |
29 block_data_size_(-1), | 25 block_data_size_(-1), |
30 block_duration_(-1), | 26 block_duration_(-1), |
31 cluster_timecode_(-1) { | 27 cluster_timecode_(-1), |
28 audio_(audio_track_num, audio_default_duration), | |
29 video_(video_track_num, video_default_duration) { | |
32 CHECK_GE(video_encryption_key_id_size, 0); | 30 CHECK_GE(video_encryption_key_id_size, 0); |
33 if (video_encryption_key_id_size > 0) { | 31 if (video_encryption_key_id_size > 0) { |
34 video_encryption_key_id_.reset(new uint8[video_encryption_key_id_size]); | 32 video_encryption_key_id_.reset(new uint8[video_encryption_key_id_size]); |
35 memcpy(video_encryption_key_id_.get(), video_encryption_key_id, | 33 memcpy(video_encryption_key_id_.get(), video_encryption_key_id, |
36 video_encryption_key_id_size); | 34 video_encryption_key_id_size); |
37 } | 35 } |
38 } | 36 } |
39 | 37 |
40 WebMClusterParser::~WebMClusterParser() {} | 38 WebMClusterParser::~WebMClusterParser() {} |
41 | 39 |
42 void WebMClusterParser::Reset() { | 40 void WebMClusterParser::Reset() { |
43 audio_buffers_.clear(); | |
44 video_buffers_.clear(); | |
45 last_block_timecode_ = -1; | 41 last_block_timecode_ = -1; |
46 cluster_timecode_ = -1; | 42 cluster_timecode_ = -1; |
47 parser_.Reset(); | 43 parser_.Reset(); |
44 audio_.Reset(); | |
45 video_.Reset(); | |
48 } | 46 } |
49 | 47 |
50 int WebMClusterParser::Parse(const uint8* buf, int size) { | 48 int WebMClusterParser::Parse(const uint8* buf, int size) { |
51 audio_buffers_.clear(); | 49 audio_.ClearBufferQueue(); |
52 video_buffers_.clear(); | 50 video_.ClearBufferQueue(); |
53 | 51 |
54 int result = parser_.Parse(buf, size); | 52 int result = parser_.Parse(buf, size); |
55 | 53 |
56 if (result <= 0) | 54 if (result <= 0) |
57 return result; | 55 return result; |
58 | 56 |
59 if (parser_.IsParsingComplete()) { | 57 if (parser_.IsParsingComplete()) { |
60 // Reset the parser if we're done parsing so that | 58 // Reset the parser if we're done parsing so that |
61 // it is ready to accept another cluster on the next | 59 // it is ready to accept another cluster on the next |
62 // call. | 60 // call. |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
159 if (block_data_.get()) { | 157 if (block_data_.get()) { |
160 DVLOG(1) << "More than 1 Block in a BlockGroup is not supported."; | 158 DVLOG(1) << "More than 1 Block in a BlockGroup is not supported."; |
161 return false; | 159 return false; |
162 } | 160 } |
163 | 161 |
164 block_data_.reset(new uint8[size]); | 162 block_data_.reset(new uint8[size]); |
165 memcpy(block_data_.get(), data, size); | 163 memcpy(block_data_.get(), data, size); |
166 block_data_size_ = size; | 164 block_data_size_ = size; |
167 return true; | 165 return true; |
168 } | 166 } |
167 | |
169 bool WebMClusterParser::OnBlock(int track_num, int timecode, | 168 bool WebMClusterParser::OnBlock(int track_num, int timecode, |
170 int block_duration, | 169 int block_duration, |
171 int flags, | 170 int flags, |
172 const uint8* data, int size) { | 171 const uint8* data, int size) { |
173 if (cluster_timecode_ == -1) { | 172 if (cluster_timecode_ == -1) { |
174 DVLOG(1) << "Got a block before cluster timecode."; | 173 DVLOG(1) << "Got a block before cluster timecode."; |
175 return false; | 174 return false; |
176 } | 175 } |
177 | 176 |
178 if (timecode < 0) { | 177 if (timecode < 0) { |
(...skipping 10 matching lines...) Expand all Loading... | |
189 | 188 |
190 base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds( | 189 base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds( |
191 (cluster_timecode_ + timecode) * timecode_multiplier_); | 190 (cluster_timecode_ + timecode) * timecode_multiplier_); |
192 | 191 |
193 // The first bit of the flags is set when the block contains only keyframes. | 192 // The first bit of the flags is set when the block contains only keyframes. |
194 // http://www.matroska.org/technical/specs/index.html | 193 // http://www.matroska.org/technical/specs/index.html |
195 bool is_keyframe = (flags & 0x80) != 0; | 194 bool is_keyframe = (flags & 0x80) != 0; |
196 scoped_refptr<StreamParserBuffer> buffer = | 195 scoped_refptr<StreamParserBuffer> buffer = |
197 StreamParserBuffer::CopyFrom(data, size, is_keyframe); | 196 StreamParserBuffer::CopyFrom(data, size, is_keyframe); |
198 | 197 |
199 if (track_num == video_track_num_ && video_encryption_key_id_.get()) { | 198 if (track_num == video_.track_num() && video_encryption_key_id_.get()) { |
200 buffer->SetDecryptConfig(scoped_ptr<DecryptConfig>(new DecryptConfig( | 199 buffer->SetDecryptConfig(scoped_ptr<DecryptConfig>(new DecryptConfig( |
201 video_encryption_key_id_.get(), video_encryption_key_id_size_))); | 200 video_encryption_key_id_.get(), video_encryption_key_id_size_))); |
202 } | 201 } |
203 | 202 |
204 buffer->SetTimestamp(timestamp); | 203 buffer->SetTimestamp(timestamp); |
205 BufferQueue* queue = NULL; | 204 |
206 base::TimeDelta duration = kNoTimestamp(); | 205 base::TimeDelta duration = kNoTimestamp(); |
207 | 206 |
208 if (track_num == audio_track_num_) { | |
209 duration = audio_default_duration_; | |
210 queue = &audio_buffers_; | |
211 } else if (track_num == video_track_num_) { | |
212 duration = video_default_duration_; | |
213 queue = &video_buffers_; | |
214 } else { | |
215 DVLOG(1) << "Unexpected track number " << track_num; | |
216 return false; | |
217 } | |
218 | |
219 if (block_duration >= 0) { | 207 if (block_duration >= 0) { |
220 duration = base::TimeDelta::FromMicroseconds( | 208 duration = base::TimeDelta::FromMicroseconds( |
221 block_duration * timecode_multiplier_); | 209 block_duration * timecode_multiplier_); |
222 } | 210 } |
223 | 211 |
224 buffer->SetDuration(duration); | 212 buffer->SetDuration(duration); |
scherkus (not reviewing)
2012/05/18 01:34:02
nit: move this inside of block_duration >= 0 secti
acolwell GONE FROM CHROMIUM
2012/05/18 04:02:17
Done. But it required adding a SetDuration(kNoTime
| |
225 | 213 |
226 if (!queue->empty() && | 214 if (track_num == audio_.track_num()) { |
227 buffer->GetTimestamp() == queue->back()->GetTimestamp()) { | 215 return audio_.AddBuffer(buffer); |
216 } else if (track_num == video_.track_num()) { | |
217 return video_.AddBuffer(buffer); | |
218 } | |
219 | |
220 DVLOG(1) << "Unexpected track number " << track_num; | |
221 return false; | |
222 } | |
223 | |
224 WebMClusterParser::Track::Track(int track_num, | |
225 base::TimeDelta default_duration) | |
226 : track_num_(track_num), | |
227 default_duration_(default_duration) { | |
228 } | |
229 | |
230 WebMClusterParser::Track::~Track() {} | |
231 | |
232 bool WebMClusterParser::Track::AddBuffer( | |
233 const scoped_refptr<StreamParserBuffer>& buffer) { | |
234 | |
scherkus (not reviewing)
2012/05/18 01:34:02
remove blank line
acolwell GONE FROM CHROMIUM
2012/05/18 04:02:17
Done.
| |
235 if (!buffers_.empty() && | |
236 buffer->GetTimestamp() == buffers_.back()->GetTimestamp()) { | |
228 DVLOG(1) << "Got a block timecode that is not strictly monotonically " | 237 DVLOG(1) << "Got a block timecode that is not strictly monotonically " |
229 << "increasing for track " << track_num; | 238 << "increasing for track " << track_num_; |
230 return false; | 239 return false; |
231 } | 240 } |
232 | 241 |
233 queue->push_back(buffer); | 242 if (buffer->GetDuration() == kNoTimestamp()) |
243 buffer->SetDuration(default_duration_); | |
244 | |
245 if (delayed_buffer_) { | |
246 // Update the duration of the delayed buffer and place it into the queue. | |
247 base::TimeDelta new_duration = | |
248 buffer->GetTimestamp() - delayed_buffer_->GetTimestamp(); | |
249 | |
250 if (new_duration <= base::TimeDelta()) | |
251 return false; | |
252 | |
253 delayed_buffer_->SetDuration(new_duration); | |
254 buffers_.push_back(delayed_buffer_); | |
255 | |
256 delayed_buffer_ = NULL; | |
257 } | |
258 | |
259 // Place the buffer in delayed buffer slot if we don't know | |
260 // its duration. | |
261 if (buffer->GetDuration() == kNoTimestamp()) { | |
262 delayed_buffer_ = buffer; | |
263 return true; | |
264 } | |
265 | |
266 buffers_.push_back(buffer); | |
234 return true; | 267 return true; |
235 } | 268 } |
236 | 269 |
270 void WebMClusterParser::Track::Reset() { | |
271 buffers_.clear(); | |
272 delayed_buffer_ = NULL; | |
273 } | |
274 | |
275 void WebMClusterParser::Track::ClearBufferQueue() { | |
276 buffers_.clear(); | |
277 } | |
278 | |
237 } // namespace media | 279 } // namespace media |
OLD | NEW |