| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/formats/webm/webm_stream_parser.h" | 5 #include "media/formats/webm/webm_stream_parser.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/callback.h" | 9 #include "base/callback.h" |
| 10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "media/formats/webm/webm_cluster_parser.h" | 12 #include "media/formats/webm/webm_cluster_parser.h" |
| 13 #include "media/formats/webm/webm_constants.h" | 13 #include "media/formats/webm/webm_constants.h" |
| 14 #include "media/formats/webm/webm_content_encodings.h" | 14 #include "media/formats/webm/webm_content_encodings.h" |
| 15 #include "media/formats/webm/webm_crypto_helpers.h" | 15 #include "media/formats/webm/webm_crypto_helpers.h" |
| 16 #include "media/formats/webm/webm_info_parser.h" | 16 #include "media/formats/webm/webm_info_parser.h" |
| 17 #include "media/formats/webm/webm_tracks_parser.h" | 17 #include "media/formats/webm/webm_tracks_parser.h" |
| 18 | 18 |
| 19 namespace media { | 19 namespace media { |
| 20 | 20 |
| 21 WebMStreamParser::WebMStreamParser() | 21 WebMStreamParser::WebMStreamParser() |
| 22 : state_(kWaitingForInit), | 22 : state_(kWaitingForInit), |
| 23 unknown_segment_size_(false), | 23 unknown_segment_size_(false) { |
| 24 parsing_cluster_(false) { | |
| 25 } | 24 } |
| 26 | 25 |
| 27 WebMStreamParser::~WebMStreamParser() { | 26 WebMStreamParser::~WebMStreamParser() { |
| 28 } | 27 } |
| 29 | 28 |
| 30 void WebMStreamParser::Init(const InitCB& init_cb, | 29 void WebMStreamParser::Init(const InitCB& init_cb, |
| 31 const NewConfigCB& config_cb, | 30 const NewConfigCB& config_cb, |
| 32 const NewBuffersCB& new_buffers_cb, | 31 const NewBuffersCB& new_buffers_cb, |
| 33 bool ignore_text_tracks, | 32 bool ignore_text_tracks, |
| 34 const NeedKeyCB& need_key_cb, | 33 const NeedKeyCB& need_key_cb, |
| (...skipping 17 matching lines...) Expand all Loading... |
| 52 need_key_cb_ = need_key_cb; | 51 need_key_cb_ = need_key_cb; |
| 53 new_segment_cb_ = new_segment_cb; | 52 new_segment_cb_ = new_segment_cb; |
| 54 end_of_segment_cb_ = end_of_segment_cb; | 53 end_of_segment_cb_ = end_of_segment_cb; |
| 55 log_cb_ = log_cb; | 54 log_cb_ = log_cb; |
| 56 } | 55 } |
| 57 | 56 |
| 58 void WebMStreamParser::Flush() { | 57 void WebMStreamParser::Flush() { |
| 59 DCHECK_NE(state_, kWaitingForInit); | 58 DCHECK_NE(state_, kWaitingForInit); |
| 60 | 59 |
| 61 byte_queue_.Reset(); | 60 byte_queue_.Reset(); |
| 62 parsing_cluster_ = false; | 61 if (cluster_parser_) |
| 63 | 62 cluster_parser_->Reset(); |
| 64 if (state_ != kParsingClusters) | 63 if (state_ == kParsingClusters) { |
| 65 return; | 64 ChangeState(kParsingHeaders); |
| 66 | 65 end_of_segment_cb_.Run(); |
| 67 cluster_parser_->Reset(); | 66 } |
| 68 } | 67 } |
| 69 | 68 |
| 70 bool WebMStreamParser::Parse(const uint8* buf, int size) { | 69 bool WebMStreamParser::Parse(const uint8* buf, int size) { |
| 71 DCHECK_NE(state_, kWaitingForInit); | 70 DCHECK_NE(state_, kWaitingForInit); |
| 72 | 71 |
| 73 if (state_ == kError) | 72 if (state_ == kError) |
| 74 return false; | 73 return false; |
| 75 | 74 |
| 76 byte_queue_.Push(buf, size); | 75 byte_queue_.Push(buf, size); |
| 77 | 76 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 case kWebMIdCues: | 143 case kWebMIdCues: |
| 145 case kWebMIdChapters: | 144 case kWebMIdChapters: |
| 146 // TODO(matthewjheaney): Implement support for chapters. | 145 // TODO(matthewjheaney): Implement support for chapters. |
| 147 if (cur_size < (result + element_size)) { | 146 if (cur_size < (result + element_size)) { |
| 148 // We don't have the whole element yet. Signal we need more data. | 147 // We don't have the whole element yet. Signal we need more data. |
| 149 return 0; | 148 return 0; |
| 150 } | 149 } |
| 151 // Skip the element. | 150 // Skip the element. |
| 152 return result + element_size; | 151 return result + element_size; |
| 153 break; | 152 break; |
| 153 case kWebMIdCluster: |
| 154 if (!cluster_parser_) { |
| 155 MEDIA_LOG(log_cb_) << "Found Cluster element before Info."; |
| 156 return -1; |
| 157 } |
| 158 ChangeState(kParsingClusters); |
| 159 new_segment_cb_.Run(); |
| 160 return 0; |
| 161 break; |
| 154 case kWebMIdSegment: | 162 case kWebMIdSegment: |
| 155 // Segment of unknown size indicates live stream. | 163 // Segment of unknown size indicates live stream. |
| 156 if (element_size == kWebMUnknownSize) | 164 if (element_size == kWebMUnknownSize) |
| 157 unknown_segment_size_ = true; | 165 unknown_segment_size_ = true; |
| 158 // Just consume the segment header. | 166 // Just consume the segment header. |
| 159 return result; | 167 return result; |
| 160 break; | 168 break; |
| 161 case kWebMIdInfo: | 169 case kWebMIdInfo: |
| 162 // We've found the element we are looking for. | 170 // We've found the element we are looking for. |
| 163 break; | 171 break; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 tracks_parser.audio_track_num(), | 232 tracks_parser.audio_track_num(), |
| 225 tracks_parser.GetAudioDefaultDuration(timecode_scale_in_us), | 233 tracks_parser.GetAudioDefaultDuration(timecode_scale_in_us), |
| 226 tracks_parser.video_track_num(), | 234 tracks_parser.video_track_num(), |
| 227 tracks_parser.GetVideoDefaultDuration(timecode_scale_in_us), | 235 tracks_parser.GetVideoDefaultDuration(timecode_scale_in_us), |
| 228 tracks_parser.text_tracks(), | 236 tracks_parser.text_tracks(), |
| 229 tracks_parser.ignored_tracks(), | 237 tracks_parser.ignored_tracks(), |
| 230 tracks_parser.audio_encryption_key_id(), | 238 tracks_parser.audio_encryption_key_id(), |
| 231 tracks_parser.video_encryption_key_id(), | 239 tracks_parser.video_encryption_key_id(), |
| 232 log_cb_)); | 240 log_cb_)); |
| 233 | 241 |
| 234 ChangeState(kParsingClusters); | |
| 235 | |
| 236 if (!init_cb_.is_null()) | 242 if (!init_cb_.is_null()) |
| 237 base::ResetAndReturn(&init_cb_).Run(true, params); | 243 base::ResetAndReturn(&init_cb_).Run(true, params); |
| 238 | 244 |
| 239 return bytes_parsed; | 245 return bytes_parsed; |
| 240 } | 246 } |
| 241 | 247 |
| 242 int WebMStreamParser::ParseCluster(const uint8* data, int size) { | 248 int WebMStreamParser::ParseCluster(const uint8* data, int size) { |
| 243 if (!cluster_parser_) | 249 if (!cluster_parser_) |
| 244 return -1; | 250 return -1; |
| 245 | 251 |
| 246 int result = 0; | 252 int bytes_parsed = cluster_parser_->Parse(data, size); |
| 247 int bytes_parsed; | 253 if (bytes_parsed < 0) |
| 248 bool cluster_ended; | 254 return bytes_parsed; |
| 249 do { | |
| 250 cluster_ended = false; | |
| 251 | 255 |
| 252 // If we are not parsing a cluster then handle the case when the next | 256 const BufferQueue& audio_buffers = cluster_parser_->GetAudioBuffers(); |
| 253 // element is not a cluster. | 257 const BufferQueue& video_buffers = cluster_parser_->GetVideoBuffers(); |
| 254 if (!parsing_cluster_) { | 258 const TextBufferQueueMap& text_map = cluster_parser_->GetTextBuffers(); |
| 255 int id; | |
| 256 int64 element_size; | |
| 257 bytes_parsed = WebMParseElementHeader(data, size, &id, &element_size); | |
| 258 | 259 |
| 259 if (bytes_parsed < 0) | 260 bool cluster_ended = cluster_parser_->cluster_ended(); |
| 260 return bytes_parsed; | |
| 261 | 261 |
| 262 if (bytes_parsed == 0) | 262 if ((!audio_buffers.empty() || !video_buffers.empty() || |
| 263 return result; | 263 !text_map.empty()) && |
| 264 !new_buffers_cb_.Run(audio_buffers, video_buffers, text_map)) { |
| 265 return -1; |
| 266 } |
| 264 | 267 |
| 265 if (id != kWebMIdCluster) { | 268 if (cluster_ended) { |
| 266 ChangeState(kParsingHeaders); | 269 ChangeState(kParsingHeaders); |
| 267 return result; | 270 end_of_segment_cb_.Run(); |
| 268 } | 271 } |
| 269 } | |
| 270 | 272 |
| 271 bytes_parsed = cluster_parser_->Parse(data, size); | 273 return bytes_parsed; |
| 272 | |
| 273 if (bytes_parsed < 0) | |
| 274 return bytes_parsed; | |
| 275 | |
| 276 // If cluster detected, immediately notify new segment if we have not | |
| 277 // already done this. | |
| 278 if (!parsing_cluster_ && bytes_parsed > 0) { | |
| 279 parsing_cluster_ = true; | |
| 280 new_segment_cb_.Run(); | |
| 281 } | |
| 282 | |
| 283 const BufferQueue& audio_buffers = cluster_parser_->GetAudioBuffers(); | |
| 284 const BufferQueue& video_buffers = cluster_parser_->GetVideoBuffers(); | |
| 285 const TextBufferQueueMap& text_map = cluster_parser_->GetTextBuffers(); | |
| 286 | |
| 287 cluster_ended = cluster_parser_->cluster_ended(); | |
| 288 | |
| 289 if ((!audio_buffers.empty() || !video_buffers.empty() || | |
| 290 !text_map.empty()) && | |
| 291 !new_buffers_cb_.Run(audio_buffers, video_buffers, text_map)) { | |
| 292 return -1; | |
| 293 } | |
| 294 | |
| 295 if (cluster_ended) { | |
| 296 parsing_cluster_ = false; | |
| 297 end_of_segment_cb_.Run(); | |
| 298 } | |
| 299 | |
| 300 result += bytes_parsed; | |
| 301 data += bytes_parsed; | |
| 302 size -= bytes_parsed; | |
| 303 | |
| 304 // WebMClusterParser returns 0 and |cluster_ended| is true if previously | |
| 305 // parsing an unknown-size cluster and |data| does not continue that | |
| 306 // cluster. Try parsing again in that case. | |
| 307 } while (size > 0 && (bytes_parsed > 0 || cluster_ended)); | |
| 308 | |
| 309 return result; | |
| 310 } | 274 } |
| 311 | 275 |
| 312 void WebMStreamParser::FireNeedKey(const std::string& key_id) { | 276 void WebMStreamParser::FireNeedKey(const std::string& key_id) { |
| 313 std::vector<uint8> key_id_vector(key_id.begin(), key_id.end()); | 277 std::vector<uint8> key_id_vector(key_id.begin(), key_id.end()); |
| 314 need_key_cb_.Run(kWebMEncryptInitDataType, key_id_vector); | 278 need_key_cb_.Run(kWebMEncryptInitDataType, key_id_vector); |
| 315 } | 279 } |
| 316 | 280 |
| 317 } // namespace media | 281 } // namespace media |
| OLD | NEW |