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/mp2t/es_parser_h264.h" | 5 #include "media/formats/mp2t/es_parser_h264.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/numerics/safe_conversions.h" | 9 #include "base/numerics/safe_conversions.h" |
10 #include "media/base/buffers.h" | 10 #include "media/base/buffers.h" |
11 #include "media/base/stream_parser_buffer.h" | 11 #include "media/base/stream_parser_buffer.h" |
12 #include "media/base/video_frame.h" | 12 #include "media/base/video_frame.h" |
13 #include "media/filters/h264_parser.h" | 13 #include "media/filters/h264_parser.h" |
14 #include "media/formats/common/offset_byte_queue.h" | 14 #include "media/formats/common/offset_byte_queue.h" |
15 #include "media/formats/mp2t/mp2t_common.h" | 15 #include "media/formats/mp2t/mp2t_common.h" |
16 #include "ui/gfx/rect.h" | 16 #include "ui/gfx/rect.h" |
17 #include "ui/gfx/size.h" | 17 #include "ui/gfx/size.h" |
18 | 18 |
19 namespace media { | 19 namespace media { |
20 namespace mp2t { | 20 namespace mp2t { |
21 | 21 |
22 // An AUD NALU is at least 4 bytes: | 22 // An AUD NALU is at least 4 bytes: |
23 // 3 bytes for the start code + 1 byte for the NALU type. | 23 // 3 bytes for the start code + 1 byte for the NALU type. |
24 const int kMinAUDSize = 4; | 24 const int kMinAUDSize = 4; |
25 | 25 |
26 // Default video frame duration. | |
27 const base::TimeDelta kDefaultFrameDuration( | |
acolwell GONE FROM CHROMIUM
2014/07/03 00:50:58
nit: Please add a comment saying why you picked 25
| |
28 base::TimeDelta::FromMilliseconds(40)); | |
29 | |
30 const size_t kMaxPtsHistoryLength = 16; | |
acolwell GONE FROM CHROMIUM
2014/07/03 00:50:58
nit: I'm assuming this is derived based on the max
| |
31 | |
26 EsParserH264::EsParserH264( | 32 EsParserH264::EsParserH264( |
27 const NewVideoConfigCB& new_video_config_cb, | 33 const NewVideoConfigCB& new_video_config_cb, |
28 const EmitBufferCB& emit_buffer_cb) | 34 const EmitBufferCB& emit_buffer_cb) |
29 : new_video_config_cb_(new_video_config_cb), | 35 : new_video_config_cb_(new_video_config_cb), |
30 emit_buffer_cb_(emit_buffer_cb), | 36 emit_buffer_cb_(emit_buffer_cb), |
31 es_queue_(new media::OffsetByteQueue()), | 37 es_queue_(new media::OffsetByteQueue()), |
32 h264_parser_(new H264Parser()), | 38 h264_parser_(new H264Parser()), |
33 current_access_unit_pos_(0), | 39 current_access_unit_pos_(0), |
34 next_access_unit_pos_(0) { | 40 next_access_unit_pos_(0) { |
35 } | 41 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
78 } | 84 } |
79 | 85 |
80 void EsParserH264::Reset() { | 86 void EsParserH264::Reset() { |
81 DVLOG(1) << "EsParserH264::Reset"; | 87 DVLOG(1) << "EsParserH264::Reset"; |
82 es_queue_.reset(new media::OffsetByteQueue()); | 88 es_queue_.reset(new media::OffsetByteQueue()); |
83 h264_parser_.reset(new H264Parser()); | 89 h264_parser_.reset(new H264Parser()); |
84 current_access_unit_pos_ = 0; | 90 current_access_unit_pos_ = 0; |
85 next_access_unit_pos_ = 0; | 91 next_access_unit_pos_ = 0; |
86 timing_desc_list_.clear(); | 92 timing_desc_list_.clear(); |
87 last_video_decoder_config_ = VideoDecoderConfig(); | 93 last_video_decoder_config_ = VideoDecoderConfig(); |
94 frame_pts_history_.clear(); | |
88 } | 95 } |
89 | 96 |
90 bool EsParserH264::FindAUD(int64* stream_pos) { | 97 bool EsParserH264::FindAUD(int64* stream_pos) { |
91 while (true) { | 98 while (true) { |
92 const uint8* es; | 99 const uint8* es; |
93 int size; | 100 int size; |
94 es_queue_->PeekAt(*stream_pos, &es, &size); | 101 es_queue_->PeekAt(*stream_pos, &es, &size); |
95 | 102 |
96 // Find a start code and move the stream to the start code parser position. | 103 // Find a start code and move the stream to the start code parser position. |
97 off_t start_code_offset; | 104 off_t start_code_offset; |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
230 // Get the access unit timing info. | 237 // Get the access unit timing info. |
231 TimingDesc current_timing_desc = {kNoTimestamp(), kNoTimestamp()}; | 238 TimingDesc current_timing_desc = {kNoTimestamp(), kNoTimestamp()}; |
232 while (!timing_desc_list_.empty() && | 239 while (!timing_desc_list_.empty() && |
233 timing_desc_list_.front().first <= access_unit_pos) { | 240 timing_desc_list_.front().first <= access_unit_pos) { |
234 current_timing_desc = timing_desc_list_.front().second; | 241 current_timing_desc = timing_desc_list_.front().second; |
235 timing_desc_list_.pop_front(); | 242 timing_desc_list_.pop_front(); |
236 } | 243 } |
237 if (current_timing_desc.pts == kNoTimestamp()) | 244 if (current_timing_desc.pts == kNoTimestamp()) |
238 return false; | 245 return false; |
239 | 246 |
247 // In Mpeg2 TS, there is no notion of frame duration. | |
248 // Only try to get an estimate of the frame duration. | |
249 // TODO(damienv): when the H264 stream has SEI timing information, | |
250 // we could get more accurate information about the frame duration. | |
251 if (!frame_pts_history_.empty() && | |
252 frame_pts_history_.back() > current_timing_desc.pts) { | |
253 // To estimate the frame duration, B frames are assigned the same PTS | |
254 // as the last non-B frame. | |
255 frame_pts_history_.push_back(frame_pts_history_.back()); | |
256 } else { | |
257 frame_pts_history_.push_back(current_timing_desc.pts); | |
258 } | |
259 if (frame_pts_history_.size() > kMaxPtsHistoryLength) | |
260 frame_pts_history_.pop_front(); | |
261 | |
262 base::TimeDelta frame_duration = kDefaultFrameDuration; | |
263 int pts_count = frame_pts_history_.size(); | |
264 if (pts_count > 2) { | |
265 base::TimeDelta avg_frame_duration = | |
266 (frame_pts_history_.back() - frame_pts_history_.front()) / | |
267 (pts_count - 1); | |
268 frame_duration = | |
269 ((kMaxPtsHistoryLength - pts_count) * kDefaultFrameDuration + | |
acolwell GONE FROM CHROMIUM
2014/07/03 00:50:58
I'm assuming that you are trying to smooth out the
damienv1
2014/07/07 17:26:34
- In theory, to get the frame duration accurately,
| |
270 pts_count * avg_frame_duration) / kMaxPtsHistoryLength; | |
271 } | |
272 | |
240 // Update the video decoder configuration if needed. | 273 // Update the video decoder configuration if needed. |
241 const H264PPS* pps = h264_parser_->GetPPS(pps_id); | 274 const H264PPS* pps = h264_parser_->GetPPS(pps_id); |
242 if (!pps) { | 275 if (!pps) { |
243 // Only accept an invalid PPS at the beginning when the stream | 276 // Only accept an invalid PPS at the beginning when the stream |
244 // does not necessarily start with an SPS/PPS/IDR. | 277 // does not necessarily start with an SPS/PPS/IDR. |
245 // In this case, the initial frames are conveyed to the upper layer with | 278 // In this case, the initial frames are conveyed to the upper layer with |
246 // an invalid VideoDecoderConfig and it's up to the upper layer | 279 // an invalid VideoDecoderConfig and it's up to the upper layer |
247 // to process this kind of frame accordingly. | 280 // to process this kind of frame accordingly. |
248 if (last_video_decoder_config_.IsValidConfig()) | 281 if (last_video_decoder_config_.IsValidConfig()) |
249 return false; | 282 return false; |
(...skipping 16 matching lines...) Expand all Loading... | |
266 // type and allow multiple video tracks. See https://crbug.com/341581. | 299 // type and allow multiple video tracks. See https://crbug.com/341581. |
267 scoped_refptr<StreamParserBuffer> stream_parser_buffer = | 300 scoped_refptr<StreamParserBuffer> stream_parser_buffer = |
268 StreamParserBuffer::CopyFrom( | 301 StreamParserBuffer::CopyFrom( |
269 es, | 302 es, |
270 access_unit_size, | 303 access_unit_size, |
271 is_key_frame, | 304 is_key_frame, |
272 DemuxerStream::VIDEO, | 305 DemuxerStream::VIDEO, |
273 0); | 306 0); |
274 stream_parser_buffer->SetDecodeTimestamp(current_timing_desc.dts); | 307 stream_parser_buffer->SetDecodeTimestamp(current_timing_desc.dts); |
275 stream_parser_buffer->set_timestamp(current_timing_desc.pts); | 308 stream_parser_buffer->set_timestamp(current_timing_desc.pts); |
309 stream_parser_buffer->set_duration(frame_duration); | |
276 emit_buffer_cb_.Run(stream_parser_buffer); | 310 emit_buffer_cb_.Run(stream_parser_buffer); |
277 return true; | 311 return true; |
278 } | 312 } |
279 | 313 |
280 bool EsParserH264::UpdateVideoDecoderConfig(const H264SPS* sps) { | 314 bool EsParserH264::UpdateVideoDecoderConfig(const H264SPS* sps) { |
281 // Set the SAR to 1 when not specified in the H264 stream. | 315 // Set the SAR to 1 when not specified in the H264 stream. |
282 int sar_width = (sps->sar_width == 0) ? 1 : sps->sar_width; | 316 int sar_width = (sps->sar_width == 0) ? 1 : sps->sar_width; |
283 int sar_height = (sps->sar_height == 0) ? 1 : sps->sar_height; | 317 int sar_height = (sps->sar_height == 0) ? 1 : sps->sar_height; |
284 | 318 |
285 // TODO(damienv): a MAP unit can be either 16 or 32 pixels. | 319 // TODO(damienv): a MAP unit can be either 16 or 32 pixels. |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
323 last_video_decoder_config_ = video_decoder_config; | 357 last_video_decoder_config_ = video_decoder_config; |
324 new_video_config_cb_.Run(video_decoder_config); | 358 new_video_config_cb_.Run(video_decoder_config); |
325 } | 359 } |
326 | 360 |
327 return true; | 361 return true; |
328 } | 362 } |
329 | 363 |
330 } // namespace mp2t | 364 } // namespace mp2t |
331 } // namespace media | 365 } // namespace media |
332 | 366 |
OLD | NEW |