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" |
(...skipping 10 matching lines...) Expand all Loading... | |
21 namespace mp2t { | 21 namespace mp2t { |
22 | 22 |
23 // An AUD NALU is at least 4 bytes: | 23 // An AUD NALU is at least 4 bytes: |
24 // 3 bytes for the start code + 1 byte for the NALU type. | 24 // 3 bytes for the start code + 1 byte for the NALU type. |
25 const int kMinAUDSize = 4; | 25 const int kMinAUDSize = 4; |
26 | 26 |
27 EsParserH264::EsParserH264( | 27 EsParserH264::EsParserH264( |
28 const NewVideoConfigCB& new_video_config_cb, | 28 const NewVideoConfigCB& new_video_config_cb, |
29 const EmitBufferCB& emit_buffer_cb) | 29 const EmitBufferCB& emit_buffer_cb) |
30 : es_adapter_(new_video_config_cb, emit_buffer_cb), | 30 : es_adapter_(new_video_config_cb, emit_buffer_cb), |
31 es_queue_(new media::OffsetByteQueue()), | 31 //es_queue_(new media::OffsetByteQueue()), |
wolenetz
2014/08/26 23:01:44
ditto
damienv1
2014/08/27 16:23:43
My mistake. Forgot to remove this line.
| |
32 h264_parser_(new H264Parser()), | 32 h264_parser_(new H264Parser()), |
33 current_access_unit_pos_(0), | 33 current_access_unit_pos_(0), |
34 next_access_unit_pos_(0) { | 34 next_access_unit_pos_(0) { |
35 } | 35 } |
36 | 36 |
37 EsParserH264::~EsParserH264() { | 37 EsParserH264::~EsParserH264() { |
38 } | 38 } |
39 | 39 |
wolenetz
2014/08/26 23:01:44
nit: Did you mean to drop the old ::Parse()'s Note
damienv1
2014/08/27 16:23:43
I added back the HLS comment in the header file.
R
| |
40 bool EsParserH264::Parse(const uint8* buf, int size, | |
41 base::TimeDelta pts, | |
42 DecodeTimestamp dts) { | |
43 // Note: Parse is invoked each time a PES packet has been reassembled. | |
44 // Unfortunately, a PES packet does not necessarily map | |
45 // to an h264 access unit, although the HLS recommendation is to use one PES | |
46 // for each access unit (but this is just a recommendation and some streams | |
47 // do not comply with this recommendation). | |
48 | |
49 // HLS recommendation: "In AVC video, you should have both a DTS and a | |
50 // PTS in each PES header". | |
51 // However, some streams do not comply with this recommendation. | |
52 DVLOG_IF(1, pts == kNoTimestamp()) << "Each video PES should have a PTS"; | |
53 if (pts != kNoTimestamp()) { | |
54 TimingDesc timing_desc; | |
55 timing_desc.pts = pts; | |
56 timing_desc.dts = (dts != kNoDecodeTimestamp()) ? dts : | |
57 DecodeTimestamp::FromPresentationTime(pts); | |
58 | |
59 // Link the end of the byte queue with the incoming timing descriptor. | |
60 timing_desc_list_.push_back( | |
61 std::pair<int64, TimingDesc>(es_queue_->tail(), timing_desc)); | |
62 } | |
63 | |
64 // Add the incoming bytes to the ES queue. | |
65 es_queue_->Push(buf, size); | |
66 return ParseInternal(); | |
67 } | |
68 | |
69 void EsParserH264::Flush() { | 40 void EsParserH264::Flush() { |
70 DVLOG(1) << "EsParserH264::Flush"; | 41 DVLOG(1) << "EsParserH264::Flush"; |
71 if (!FindAUD(¤t_access_unit_pos_)) | 42 if (!FindAUD(¤t_access_unit_pos_)) |
72 return; | 43 return; |
73 | 44 |
74 // Simulate an additional AUD to force emitting the last access unit | 45 // Simulate an additional AUD to force emitting the last access unit |
75 // which is assumed to be complete at this point. | 46 // which is assumed to be complete at this point. |
76 uint8 aud[] = { 0x00, 0x00, 0x01, 0x09 }; | 47 uint8 aud[] = { 0x00, 0x00, 0x01, 0x09 }; |
77 es_queue_->Push(aud, sizeof(aud)); | 48 es_queue_->Push(aud, sizeof(aud)); |
78 ParseInternal(); | 49 ParseFromEsQueue(); |
79 | 50 |
80 es_adapter_.Flush(); | 51 es_adapter_.Flush(); |
81 } | 52 } |
82 | 53 |
83 void EsParserH264::Reset() { | 54 void EsParserH264::Reset() { |
wolenetz
2014/08/26 23:01:44
ditto: super::Reset() should call some child::Rese
damienv1
2014/08/27 16:23:43
Done.
| |
84 DVLOG(1) << "EsParserH264::Reset"; | 55 DVLOG(1) << "EsParserH264::Reset"; |
85 es_queue_.reset(new media::OffsetByteQueue()); | 56 EsParser::Reset(); |
86 h264_parser_.reset(new H264Parser()); | 57 h264_parser_.reset(new H264Parser()); |
87 current_access_unit_pos_ = 0; | 58 current_access_unit_pos_ = 0; |
88 next_access_unit_pos_ = 0; | 59 next_access_unit_pos_ = 0; |
89 timing_desc_list_.clear(); | |
90 last_video_decoder_config_ = VideoDecoderConfig(); | 60 last_video_decoder_config_ = VideoDecoderConfig(); |
91 es_adapter_.Reset(); | 61 es_adapter_.Reset(); |
92 } | 62 } |
93 | 63 |
94 bool EsParserH264::FindAUD(int64* stream_pos) { | 64 bool EsParserH264::FindAUD(int64* stream_pos) { |
95 while (true) { | 65 while (true) { |
96 const uint8* es; | 66 const uint8* es; |
97 int size; | 67 int size; |
98 es_queue_->PeekAt(*stream_pos, &es, &size); | 68 es_queue_->PeekAt(*stream_pos, &es, &size); |
99 | 69 |
(...skipping 16 matching lines...) Expand all Loading... | |
116 break; | 86 break; |
117 | 87 |
118 // The current NALU is not an AUD, skip the start code | 88 // The current NALU is not an AUD, skip the start code |
119 // and continue parsing the stream. | 89 // and continue parsing the stream. |
120 *stream_pos += start_code_size; | 90 *stream_pos += start_code_size; |
121 } | 91 } |
122 | 92 |
123 return true; | 93 return true; |
124 } | 94 } |
125 | 95 |
126 bool EsParserH264::ParseInternal() { | 96 bool EsParserH264::ParseFromEsQueue() { |
127 DCHECK_LE(es_queue_->head(), current_access_unit_pos_); | 97 DCHECK_LE(es_queue_->head(), current_access_unit_pos_); |
128 DCHECK_LE(current_access_unit_pos_, next_access_unit_pos_); | 98 DCHECK_LE(current_access_unit_pos_, next_access_unit_pos_); |
129 DCHECK_LE(next_access_unit_pos_, es_queue_->tail()); | 99 DCHECK_LE(next_access_unit_pos_, es_queue_->tail()); |
130 | 100 |
131 // Find the next AUD located at or after |current_access_unit_pos_|. This is | 101 // Find the next AUD located at or after |current_access_unit_pos_|. This is |
132 // needed since initially |current_access_unit_pos_| might not point to | 102 // needed since initially |current_access_unit_pos_| might not point to |
133 // an AUD. | 103 // an AUD. |
134 // Discard all the data before the updated |current_access_unit_pos_| | 104 // Discard all the data before the updated |current_access_unit_pos_| |
135 // since it won't be used again. | 105 // since it won't be used again. |
136 bool aud_found = FindAUD(¤t_access_unit_pos_); | 106 bool aud_found = FindAUD(¤t_access_unit_pos_); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
225 is_key_frame, pps_id_for_access_unit)); | 195 is_key_frame, pps_id_for_access_unit)); |
226 current_access_unit_pos_ = next_access_unit_pos_; | 196 current_access_unit_pos_ = next_access_unit_pos_; |
227 es_queue_->Trim(current_access_unit_pos_); | 197 es_queue_->Trim(current_access_unit_pos_); |
228 | 198 |
229 return true; | 199 return true; |
230 } | 200 } |
231 | 201 |
232 bool EsParserH264::EmitFrame(int64 access_unit_pos, int access_unit_size, | 202 bool EsParserH264::EmitFrame(int64 access_unit_pos, int access_unit_size, |
233 bool is_key_frame, int pps_id) { | 203 bool is_key_frame, int pps_id) { |
234 // Get the access unit timing info. | 204 // Get the access unit timing info. |
235 TimingDesc current_timing_desc = {kNoDecodeTimestamp(), kNoTimestamp()}; | 205 TimingDesc current_timing_desc = GetTimingDescriptor(access_unit_pos); |
236 while (!timing_desc_list_.empty() && | |
237 timing_desc_list_.front().first <= access_unit_pos) { | |
238 current_timing_desc = timing_desc_list_.front().second; | |
239 timing_desc_list_.pop_front(); | |
240 } | |
241 if (current_timing_desc.pts == kNoTimestamp()) | 206 if (current_timing_desc.pts == kNoTimestamp()) |
242 return false; | 207 return false; |
243 | 208 |
209 if (current_timing_desc.dts == kNoDecodeTimestamp()) { | |
210 current_timing_desc.dts = | |
211 DecodeTimestamp::FromPresentationTime(current_timing_desc.pts); | |
212 } | |
213 | |
244 // Update the video decoder configuration if needed. | 214 // Update the video decoder configuration if needed. |
245 const H264PPS* pps = h264_parser_->GetPPS(pps_id); | 215 const H264PPS* pps = h264_parser_->GetPPS(pps_id); |
246 if (!pps) { | 216 if (!pps) { |
247 // Only accept an invalid PPS at the beginning when the stream | 217 // Only accept an invalid PPS at the beginning when the stream |
248 // does not necessarily start with an SPS/PPS/IDR. | 218 // does not necessarily start with an SPS/PPS/IDR. |
249 // In this case, the initial frames are conveyed to the upper layer with | 219 // In this case, the initial frames are conveyed to the upper layer with |
250 // an invalid VideoDecoderConfig and it's up to the upper layer | 220 // an invalid VideoDecoderConfig and it's up to the upper layer |
251 // to process this kind of frame accordingly. | 221 // to process this kind of frame accordingly. |
252 if (last_video_decoder_config_.IsValidConfig()) | 222 if (last_video_decoder_config_.IsValidConfig()) |
253 return false; | 223 return false; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
326 << " height=" << sps->sar_height; | 296 << " height=" << sps->sar_height; |
327 last_video_decoder_config_ = video_decoder_config; | 297 last_video_decoder_config_ = video_decoder_config; |
328 es_adapter_.OnConfigChanged(video_decoder_config); | 298 es_adapter_.OnConfigChanged(video_decoder_config); |
329 } | 299 } |
330 | 300 |
331 return true; | 301 return true; |
332 } | 302 } |
333 | 303 |
334 } // namespace mp2t | 304 } // namespace mp2t |
335 } // namespace media | 305 } // namespace media |
OLD | NEW |