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

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

Issue 364823008: Mpeg2TS - estimate duration for video frames. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 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 | Annotate | Revision Log
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/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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698