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

Side by Side Diff: media/formats/mp2t/mp2t_stream_parser.cc

Issue 1874413003: Convert media/formats to std::unique_ptr (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 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
OLDNEW
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/mp2t/mp2t_stream_parser.h" 5 #include "media/formats/mp2t/mp2t_stream_parser.h"
6 6
7 #include <memory>
7 #include <utility> 8 #include <utility>
8 9
9 #include "base/bind.h" 10 #include "base/bind.h"
10 #include "base/callback_helpers.h" 11 #include "base/callback_helpers.h"
11 #include "base/stl_util.h" 12 #include "base/stl_util.h"
12 #include "media/base/media_tracks.h" 13 #include "media/base/media_tracks.h"
13 #include "media/base/stream_parser_buffer.h" 14 #include "media/base/stream_parser_buffer.h"
14 #include "media/base/text_track_config.h" 15 #include "media/base/text_track_config.h"
15 #include "media/base/timestamp_constants.h" 16 #include "media/base/timestamp_constants.h"
16 #include "media/formats/mp2t/es_parser.h" 17 #include "media/formats/mp2t/es_parser.h"
(...skipping 19 matching lines...) Expand all
36 37
37 class PidState { 38 class PidState {
38 public: 39 public:
39 enum PidType { 40 enum PidType {
40 kPidPat, 41 kPidPat,
41 kPidPmt, 42 kPidPmt,
42 kPidAudioPes, 43 kPidAudioPes,
43 kPidVideoPes, 44 kPidVideoPes,
44 }; 45 };
45 46
46 PidState(int pid, PidType pid_tyoe, 47 PidState(int pid,
47 scoped_ptr<TsSection> section_parser); 48 PidType pid_tyoe,
49 std::unique_ptr<TsSection> section_parser);
48 50
49 // Extract the content of the TS packet and parse it. 51 // Extract the content of the TS packet and parse it.
50 // Return true if successful. 52 // Return true if successful.
51 bool PushTsPacket(const TsPacket& ts_packet); 53 bool PushTsPacket(const TsPacket& ts_packet);
52 54
53 // Flush the PID state (possibly emitting some pending frames) 55 // Flush the PID state (possibly emitting some pending frames)
54 // and reset its state. 56 // and reset its state.
55 void Flush(); 57 void Flush();
56 58
57 // Enable/disable the PID. 59 // Enable/disable the PID.
58 // Disabling a PID will reset its state and ignore any further incoming TS 60 // Disabling a PID will reset its state and ignore any further incoming TS
59 // packets. 61 // packets.
60 void Enable(); 62 void Enable();
61 void Disable(); 63 void Disable();
62 bool IsEnabled() const; 64 bool IsEnabled() const;
63 65
64 PidType pid_type() const { return pid_type_; } 66 PidType pid_type() const { return pid_type_; }
65 67
66 private: 68 private:
67 void ResetState(); 69 void ResetState();
68 70
69 int pid_; 71 int pid_;
70 PidType pid_type_; 72 PidType pid_type_;
71 scoped_ptr<TsSection> section_parser_; 73 std::unique_ptr<TsSection> section_parser_;
72 74
73 bool enable_; 75 bool enable_;
74 76
75 int continuity_counter_; 77 int continuity_counter_;
76 }; 78 };
77 79
78 PidState::PidState(int pid, 80 PidState::PidState(int pid,
79 PidType pid_type, 81 PidType pid_type,
80 scoped_ptr<TsSection> section_parser) 82 std::unique_ptr<TsSection> section_parser)
81 : pid_(pid), 83 : pid_(pid),
82 pid_type_(pid_type), 84 pid_type_(pid_type),
83 section_parser_(std::move(section_parser)), 85 section_parser_(std::move(section_parser)),
84 enable_(false), 86 enable_(false),
85 continuity_counter_(-1) { 87 continuity_counter_(-1) {
86 DCHECK(section_parser_); 88 DCHECK(section_parser_);
87 } 89 }
88 90
89 bool PidState::PushTsPacket(const TsPacket& ts_packet) { 91 bool PidState::PushTsPacket(const TsPacket& ts_packet) {
90 DCHECK_EQ(ts_packet.pid(), pid_); 92 DCHECK_EQ(ts_packet.pid(), pid_);
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 // Synchronization. 265 // Synchronization.
264 int skipped_bytes = TsPacket::Sync(ts_buffer, ts_buffer_size); 266 int skipped_bytes = TsPacket::Sync(ts_buffer, ts_buffer_size);
265 if (skipped_bytes > 0) { 267 if (skipped_bytes > 0) {
266 DVLOG(1) << "Packet not aligned on a TS syncword:" 268 DVLOG(1) << "Packet not aligned on a TS syncword:"
267 << " skipped_bytes=" << skipped_bytes; 269 << " skipped_bytes=" << skipped_bytes;
268 ts_byte_queue_.Pop(skipped_bytes); 270 ts_byte_queue_.Pop(skipped_bytes);
269 continue; 271 continue;
270 } 272 }
271 273
272 // Parse the TS header, skipping 1 byte if the header is invalid. 274 // Parse the TS header, skipping 1 byte if the header is invalid.
273 scoped_ptr<TsPacket> ts_packet(TsPacket::Parse(ts_buffer, ts_buffer_size)); 275 std::unique_ptr<TsPacket> ts_packet(
276 TsPacket::Parse(ts_buffer, ts_buffer_size));
274 if (!ts_packet) { 277 if (!ts_packet) {
275 DVLOG(1) << "Error: invalid TS packet"; 278 DVLOG(1) << "Error: invalid TS packet";
276 ts_byte_queue_.Pop(1); 279 ts_byte_queue_.Pop(1);
277 continue; 280 continue;
278 } 281 }
279 DVLOG(LOG_LEVEL_TS) 282 DVLOG(LOG_LEVEL_TS)
280 << "Processing PID=" << ts_packet->pid() 283 << "Processing PID=" << ts_packet->pid()
281 << " start_unit=" << ts_packet->payload_unit_start_indicator(); 284 << " start_unit=" << ts_packet->payload_unit_start_indicator();
282 285
283 // Parse the section. 286 // Parse the section.
284 std::map<int, PidState*>::iterator it = pids_.find(ts_packet->pid()); 287 std::map<int, PidState*>::iterator it = pids_.find(ts_packet->pid());
285 if (it == pids_.end() && 288 if (it == pids_.end() &&
286 ts_packet->pid() == TsSection::kPidPat) { 289 ts_packet->pid() == TsSection::kPidPat) {
287 // Create the PAT state here if needed. 290 // Create the PAT state here if needed.
288 scoped_ptr<TsSection> pat_section_parser( 291 std::unique_ptr<TsSection> pat_section_parser(new TsSectionPat(
289 new TsSectionPat( 292 base::Bind(&Mp2tStreamParser::RegisterPmt, base::Unretained(this))));
290 base::Bind(&Mp2tStreamParser::RegisterPmt, 293 std::unique_ptr<PidState> pat_pid_state(new PidState(
291 base::Unretained(this))));
292 scoped_ptr<PidState> pat_pid_state(new PidState(
293 ts_packet->pid(), PidState::kPidPat, std::move(pat_section_parser))); 294 ts_packet->pid(), PidState::kPidPat, std::move(pat_section_parser)));
294 pat_pid_state->Enable(); 295 pat_pid_state->Enable();
295 it = pids_.insert( 296 it = pids_.insert(
296 std::pair<int, PidState*>(ts_packet->pid(), 297 std::pair<int, PidState*>(ts_packet->pid(),
297 pat_pid_state.release())).first; 298 pat_pid_state.release())).first;
298 } 299 }
299 300
300 if (it != pids_.end()) { 301 if (it != pids_.end()) {
301 if (!it->second->PushTsPacket(*ts_packet)) 302 if (!it->second->PushTsPacket(*ts_packet))
302 return false; 303 return false;
(...skipping 22 matching lines...) Expand all
325 it != pids_.end(); ++it) { 326 it != pids_.end(); ++it) {
326 PidState* pid_state = it->second; 327 PidState* pid_state = it->second;
327 if (pid_state->pid_type() == PidState::kPidPmt) { 328 if (pid_state->pid_type() == PidState::kPidPmt) {
328 DVLOG_IF(1, pmt_pid != it->first) << "More than one program is defined"; 329 DVLOG_IF(1, pmt_pid != it->first) << "More than one program is defined";
329 return; 330 return;
330 } 331 }
331 } 332 }
332 333
333 // Create the PMT state here if needed. 334 // Create the PMT state here if needed.
334 DVLOG(1) << "Create a new PMT parser"; 335 DVLOG(1) << "Create a new PMT parser";
335 scoped_ptr<TsSection> pmt_section_parser( 336 std::unique_ptr<TsSection> pmt_section_parser(new TsSectionPmt(base::Bind(
336 new TsSectionPmt( 337 &Mp2tStreamParser::RegisterPes, base::Unretained(this), pmt_pid)));
337 base::Bind(&Mp2tStreamParser::RegisterPes, 338 std::unique_ptr<PidState> pmt_pid_state(
338 base::Unretained(this), pmt_pid)));
339 scoped_ptr<PidState> pmt_pid_state(
340 new PidState(pmt_pid, PidState::kPidPmt, std::move(pmt_section_parser))); 339 new PidState(pmt_pid, PidState::kPidPmt, std::move(pmt_section_parser)));
341 pmt_pid_state->Enable(); 340 pmt_pid_state->Enable();
342 pids_.insert(std::pair<int, PidState*>(pmt_pid, pmt_pid_state.release())); 341 pids_.insert(std::pair<int, PidState*>(pmt_pid, pmt_pid_state.release()));
343 } 342 }
344 343
345 void Mp2tStreamParser::RegisterPes(int pmt_pid, 344 void Mp2tStreamParser::RegisterPes(int pmt_pid,
346 int pes_pid, 345 int pes_pid,
347 int stream_type) { 346 int stream_type) {
348 // TODO(damienv): check there is no mismatch if the entry already exists. 347 // TODO(damienv): check there is no mismatch if the entry already exists.
349 DVLOG(1) << "RegisterPes:" 348 DVLOG(1) << "RegisterPes:"
350 << " pes_pid=" << pes_pid 349 << " pes_pid=" << pes_pid
351 << " stream_type=" << std::hex << stream_type << std::dec; 350 << " stream_type=" << std::hex << stream_type << std::dec;
352 std::map<int, PidState*>::iterator it = pids_.find(pes_pid); 351 std::map<int, PidState*>::iterator it = pids_.find(pes_pid);
353 if (it != pids_.end()) 352 if (it != pids_.end())
354 return; 353 return;
355 354
356 // Create a stream parser corresponding to the stream type. 355 // Create a stream parser corresponding to the stream type.
357 bool is_audio = false; 356 bool is_audio = false;
358 scoped_ptr<EsParser> es_parser; 357 std::unique_ptr<EsParser> es_parser;
359 if (stream_type == kStreamTypeAVC) { 358 if (stream_type == kStreamTypeAVC) {
360 es_parser.reset( 359 es_parser.reset(
361 new EsParserH264( 360 new EsParserH264(
362 base::Bind(&Mp2tStreamParser::OnVideoConfigChanged, 361 base::Bind(&Mp2tStreamParser::OnVideoConfigChanged,
363 base::Unretained(this), 362 base::Unretained(this),
364 pes_pid), 363 pes_pid),
365 base::Bind(&Mp2tStreamParser::OnEmitVideoBuffer, 364 base::Bind(&Mp2tStreamParser::OnEmitVideoBuffer,
366 base::Unretained(this), 365 base::Unretained(this),
367 pes_pid))); 366 pes_pid)));
368 } else if (stream_type == kStreamTypeAAC) { 367 } else if (stream_type == kStreamTypeAAC) {
(...skipping 14 matching lines...) Expand all
383 base::Bind(&Mp2tStreamParser::OnEmitAudioBuffer, base::Unretained(this), 382 base::Bind(&Mp2tStreamParser::OnEmitAudioBuffer, base::Unretained(this),
384 pes_pid), 383 pes_pid),
385 media_log_)); 384 media_log_));
386 is_audio = true; 385 is_audio = true;
387 } else { 386 } else {
388 return; 387 return;
389 } 388 }
390 389
391 // Create the PES state here. 390 // Create the PES state here.
392 DVLOG(1) << "Create a new PES state"; 391 DVLOG(1) << "Create a new PES state";
393 scoped_ptr<TsSection> pes_section_parser( 392 std::unique_ptr<TsSection> pes_section_parser(
394 new TsSectionPes(std::move(es_parser), &timestamp_unroller_)); 393 new TsSectionPes(std::move(es_parser), &timestamp_unroller_));
395 PidState::PidType pid_type = 394 PidState::PidType pid_type =
396 is_audio ? PidState::kPidAudioPes : PidState::kPidVideoPes; 395 is_audio ? PidState::kPidAudioPes : PidState::kPidVideoPes;
397 scoped_ptr<PidState> pes_pid_state( 396 std::unique_ptr<PidState> pes_pid_state(
398 new PidState(pes_pid, pid_type, std::move(pes_section_parser))); 397 new PidState(pes_pid, pid_type, std::move(pes_section_parser)));
399 pids_.insert(std::pair<int, PidState*>(pes_pid, pes_pid_state.release())); 398 pids_.insert(std::pair<int, PidState*>(pes_pid, pes_pid_state.release()));
400 399
401 // A new PES pid has been added, the PID filter might change. 400 // A new PES pid has been added, the PID filter might change.
402 UpdatePidFilter(); 401 UpdatePidFilter();
403 } 402 }
404 403
405 void Mp2tStreamParser::UpdatePidFilter() { 404 void Mp2tStreamParser::UpdatePidFilter() {
406 // Applies the HLS rule to select the default audio/video PIDs: 405 // Applies the HLS rule to select the default audio/video PIDs:
407 // select the audio/video streams with the lowest PID. 406 // select the audio/video streams with the lowest PID.
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 // Replace any non valid config with the 1st valid entry. 498 // Replace any non valid config with the 1st valid entry.
500 // This might happen if there was no available config before. 499 // This might happen if there was no available config before.
501 for (std::list<BufferQueueWithConfig>::iterator it = 500 for (std::list<BufferQueueWithConfig>::iterator it =
502 buffer_queue_chain_.begin(); it != buffer_queue_chain_.end(); ++it) { 501 buffer_queue_chain_.begin(); it != buffer_queue_chain_.end(); ++it) {
503 if (it->audio_config.IsValidConfig()) 502 if (it->audio_config.IsValidConfig())
504 break; 503 break;
505 it->audio_config = audio_decoder_config; 504 it->audio_config = audio_decoder_config;
506 } 505 }
507 } 506 }
508 507
509 scoped_ptr<MediaTracks> GenerateMediaTrackInfo( 508 std::unique_ptr<MediaTracks> GenerateMediaTrackInfo(
510 const AudioDecoderConfig& audio_config, 509 const AudioDecoderConfig& audio_config,
511 const VideoDecoderConfig& video_config) { 510 const VideoDecoderConfig& video_config) {
512 scoped_ptr<MediaTracks> media_tracks(new MediaTracks()); 511 std::unique_ptr<MediaTracks> media_tracks(new MediaTracks());
513 // TODO(servolk): Implement proper sourcing of media track info as described 512 // TODO(servolk): Implement proper sourcing of media track info as described
514 // in crbug.com/590085 513 // in crbug.com/590085
515 if (audio_config.IsValidConfig()) { 514 if (audio_config.IsValidConfig()) {
516 media_tracks->AddAudioTrack(audio_config, "audio", "main", "", ""); 515 media_tracks->AddAudioTrack(audio_config, "audio", "main", "", "");
517 } 516 }
518 if (video_config.IsValidConfig()) { 517 if (video_config.IsValidConfig()) {
519 media_tracks->AddVideoTrack(video_config, "video", "main", "", ""); 518 media_tracks->AddVideoTrack(video_config, "video", "main", "", "");
520 } 519 }
521 return media_tracks; 520 return media_tracks;
522 } 521 }
(...skipping 10 matching lines...) Expand all
533 // Wait for more data to come if one of the config is not available. 532 // Wait for more data to come if one of the config is not available.
534 BufferQueueWithConfig& queue_with_config = buffer_queue_chain_.front(); 533 BufferQueueWithConfig& queue_with_config = buffer_queue_chain_.front();
535 if (selected_audio_pid_ > 0 && 534 if (selected_audio_pid_ > 0 &&
536 !queue_with_config.audio_config.IsValidConfig()) 535 !queue_with_config.audio_config.IsValidConfig())
537 return true; 536 return true;
538 if (selected_video_pid_ > 0 && 537 if (selected_video_pid_ > 0 &&
539 !queue_with_config.video_config.IsValidConfig()) 538 !queue_with_config.video_config.IsValidConfig())
540 return true; 539 return true;
541 540
542 // Pass the config before invoking the initialization callback. 541 // Pass the config before invoking the initialization callback.
543 scoped_ptr<MediaTracks> media_tracks = GenerateMediaTrackInfo( 542 std::unique_ptr<MediaTracks> media_tracks = GenerateMediaTrackInfo(
544 queue_with_config.audio_config, queue_with_config.video_config); 543 queue_with_config.audio_config, queue_with_config.video_config);
545 RCHECK(config_cb_.Run(std::move(media_tracks), TextTrackConfigMap())); 544 RCHECK(config_cb_.Run(std::move(media_tracks), TextTrackConfigMap()));
546 queue_with_config.is_config_sent = true; 545 queue_with_config.is_config_sent = true;
547 546
548 // For Mpeg2 TS, the duration is not known. 547 // For Mpeg2 TS, the duration is not known.
549 DVLOG(1) << "Mpeg2TS stream parser initialization done"; 548 DVLOG(1) << "Mpeg2TS stream parser initialization done";
550 549
551 // TODO(wolenetz): If possible, detect and report track counts by type more 550 // TODO(wolenetz): If possible, detect and report track counts by type more
552 // accurately here. Currently, capped at max 1 each for audio and video, with 551 // accurately here. Currently, capped at max 1 each for audio and video, with
553 // assumption of 0 text tracks. 552 // assumption of 0 text tracks.
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
641 // Start a segment if needed. 640 // Start a segment if needed.
642 if (!segment_started_) { 641 if (!segment_started_) {
643 DVLOG(1) << "Starting a new segment"; 642 DVLOG(1) << "Starting a new segment";
644 segment_started_ = true; 643 segment_started_ = true;
645 new_segment_cb_.Run(); 644 new_segment_cb_.Run();
646 } 645 }
647 646
648 // Update the audio and video config if needed. 647 // Update the audio and video config if needed.
649 BufferQueueWithConfig& queue_with_config = buffer_queue_chain_.front(); 648 BufferQueueWithConfig& queue_with_config = buffer_queue_chain_.front();
650 if (!queue_with_config.is_config_sent) { 649 if (!queue_with_config.is_config_sent) {
651 scoped_ptr<MediaTracks> media_tracks = GenerateMediaTrackInfo( 650 std::unique_ptr<MediaTracks> media_tracks = GenerateMediaTrackInfo(
652 queue_with_config.audio_config, queue_with_config.video_config); 651 queue_with_config.audio_config, queue_with_config.video_config);
653 if (!config_cb_.Run(std::move(media_tracks), TextTrackConfigMap())) 652 if (!config_cb_.Run(std::move(media_tracks), TextTrackConfigMap()))
654 return false; 653 return false;
655 queue_with_config.is_config_sent = true; 654 queue_with_config.is_config_sent = true;
656 } 655 }
657 656
658 // Add buffers. 657 // Add buffers.
659 TextBufferQueueMap empty_text_map; 658 TextBufferQueueMap empty_text_map;
660 if (!queue_with_config.audio_queue.empty() || 659 if (!queue_with_config.audio_queue.empty() ||
661 !queue_with_config.video_queue.empty()) { 660 !queue_with_config.video_queue.empty()) {
(...skipping 11 matching lines...) Expand all
673 // so that buffers with the same config can be added later on. 672 // so that buffers with the same config can be added later on.
674 BufferQueueWithConfig queue_with_config( 673 BufferQueueWithConfig queue_with_config(
675 true, last_audio_config, last_video_config); 674 true, last_audio_config, last_video_config);
676 buffer_queue_chain_.push_back(queue_with_config); 675 buffer_queue_chain_.push_back(queue_with_config);
677 676
678 return true; 677 return true;
679 } 678 }
680 679
681 } // namespace mp2t 680 } // namespace mp2t
682 } // namespace media 681 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698