Index: media/formats/mp2t/mp2t_stream_parser.cc |
diff --git a/media/formats/mp2t/mp2t_stream_parser.cc b/media/formats/mp2t/mp2t_stream_parser.cc |
index 35c61d6bde0bf20d6e4caf59a4d47e769ca79a99..53828b513ffda522ec7c837d81f9df4e28de0100 100644 |
--- a/media/formats/mp2t/mp2t_stream_parser.cc |
+++ b/media/formats/mp2t/mp2t_stream_parser.cc |
@@ -217,6 +217,10 @@ void Mp2tStreamParser::Flush() { |
// Reset the selected PIDs. |
selected_audio_pid_ = -1; |
selected_video_pid_ = -1; |
+ |
+ // Reset the timestamp unroller. |
+ timestamp_unroller_.Reset(); |
+ time_offset_ = base::TimeDelta(); |
} |
bool Mp2tStreamParser::Parse(const uint8* buf, int size) { |
@@ -356,7 +360,7 @@ void Mp2tStreamParser::RegisterPes(int pmt_pid, |
// Create the PES state here. |
DVLOG(1) << "Create a new PES state"; |
scoped_ptr<TsSection> pes_section_parser( |
- new TsSectionPes(es_parser.Pass())); |
+ new TsSectionPes(es_parser.Pass(), ×tamp_unroller_)); |
PidState::PidType pid_type = |
is_audio ? PidState::kPidAudioPes : PidState::kPidVideoPes; |
scoped_ptr<PidState> pes_pid_state( |
@@ -519,10 +523,6 @@ void Mp2tStreamParser::OnEmitAudioBuffer( |
<< stream_parser_buffer->timestamp().InMilliseconds() |
<< " dur=" |
<< stream_parser_buffer->duration().InMilliseconds(); |
- stream_parser_buffer->set_timestamp( |
- stream_parser_buffer->timestamp() - time_offset_); |
- stream_parser_buffer->SetDecodeTimestamp( |
- stream_parser_buffer->GetDecodeTimestamp() - time_offset_); |
// Ignore the incoming buffer if it is not associated with any config. |
if (buffer_queue_chain_.empty()) { |
@@ -550,10 +550,6 @@ void Mp2tStreamParser::OnEmitVideoBuffer( |
<< stream_parser_buffer->duration().InMilliseconds() |
<< " IsKeyframe=" |
<< stream_parser_buffer->IsKeyframe(); |
- stream_parser_buffer->set_timestamp( |
- stream_parser_buffer->timestamp() - time_offset_); |
- stream_parser_buffer->SetDecodeTimestamp( |
- stream_parser_buffer->GetDecodeTimestamp() - time_offset_); |
// Ignore the incoming buffer if it is not associated with any config. |
if (buffer_queue_chain_.empty()) { |
@@ -588,15 +584,27 @@ bool Mp2tStreamParser::EmitRemainingBuffers() { |
// Buffer emission. |
while (!buffer_queue_chain_.empty()) { |
+ BufferQueueWithConfig& queue_with_config = buffer_queue_chain_.front(); |
+ |
// Start a segment if needed. |
if (!segment_started_) { |
+ // We need at least some audio and video buffers to derive the global |
+ // timestamp offset. |
+ if (selected_audio_pid_ >= 0 && queue_with_config.audio_queue.empty()) |
+ return true; |
+ if (selected_video_pid_ >= 0 && queue_with_config.video_queue.empty()) |
+ return true; |
+ // Compensate if some timestamps are negative. |
wolenetz
2014/09/05 21:18:49
I'm a bit confused why this compensation is requir
damienv1
2014/09/05 21:52:03
Timestamps in MPEG-2 TS are defined modulo 2^33. S
|
+ if (timestamp_unroller_.GetMinUnrolledTimestamp() < 0) |
+ time_offset_ = base::TimeDelta::FromMicroseconds( |
+ (1000 * (INT64_C(1) << 33)) / 90); |
+ |
DVLOG(1) << "Starting a new segment"; |
segment_started_ = true; |
new_segment_cb_.Run(); |
} |
// Update the audio and video config if needed. |
- BufferQueueWithConfig& queue_with_config = buffer_queue_chain_.front(); |
if (!queue_with_config.is_config_sent) { |
if (!config_cb_.Run(queue_with_config.audio_config, |
queue_with_config.video_config, |
@@ -609,6 +617,8 @@ bool Mp2tStreamParser::EmitRemainingBuffers() { |
TextBufferQueueMap empty_text_map; |
if (!queue_with_config.audio_queue.empty() || |
!queue_with_config.video_queue.empty()) { |
+ ApplyTimeOffset(&queue_with_config.audio_queue); |
+ ApplyTimeOffset(&queue_with_config.video_queue); |
if (!new_buffers_cb_.Run(queue_with_config.audio_queue, |
queue_with_config.video_queue, |
empty_text_map)) { |
@@ -628,5 +638,14 @@ bool Mp2tStreamParser::EmitRemainingBuffers() { |
return true; |
} |
+void Mp2tStreamParser::ApplyTimeOffset( |
+ StreamParser::BufferQueue* buffer_queue) { |
+ for (StreamParser::BufferQueue::iterator it = buffer_queue->begin(); |
+ it != buffer_queue->end(); ++it) { |
+ (*it)->SetDecodeTimestamp((*it)->GetDecodeTimestamp() + time_offset_); |
+ (*it)->set_timestamp((*it)->timestamp() + time_offset_); |
+ } |
+} |
+ |
} // namespace mp2t |
} // namespace media |