15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/formats/mp2t/es_parser_h264.h" 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/basictypes.h" 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/logging.h" 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/numerics/safe_conversions.h" 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/base/buffers.h" 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/base/stream_parser_buffer.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/base/video_frame.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/filters/h264_parser.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/formats/common/offset_byte_queue.h" 15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/formats/mp2t/es_adapter_video.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/formats/mp2t/mp2t_common.h" 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/rect.h" 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/size.h" 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace media { 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace mp2t { 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// An AUD NALU is at least 4 bytes: 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 3 bytes for the start code + 1 byte for the NALU type. 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int kMinAUDSize = 4; 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)EsParserH264::EsParserH264( 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const NewVideoConfigCB& new_video_config_cb, 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const EmitBufferCB& emit_buffer_cb) 30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch : es_adapter_(new_video_config_cb, emit_buffer_cb), 31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch h264_parser_(new H264Parser()), 32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch current_access_unit_pos_(0), 33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch next_access_unit_pos_(0) { 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)EsParserH264::~EsParserH264() { 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void EsParserH264::Flush() { 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DVLOG(1) << __FUNCTION__; 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!FindAUD(¤t_access_unit_pos_)) 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Simulate an additional AUD to force emitting the last access unit 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // which is assumed to be complete at this point. 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint8 aud[] = { 0x00, 0x00, 0x01, 0x09 }; 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) es_queue_->Push(aud, sizeof(aud)); 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ParseFromEsQueue(); 49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch es_adapter_.Flush(); 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EsParserH264::ResetInternal() { 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DVLOG(1) << __FUNCTION__; 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) h264_parser_.reset(new H264Parser()); 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) current_access_unit_pos_ = 0; 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) next_access_unit_pos_ = 0; 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) last_video_decoder_config_ = VideoDecoderConfig(); 59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch es_adapter_.Reset(); 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool EsParserH264::FindAUD(int64* stream_pos) { 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) while (true) { 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const uint8* es; 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int size; 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) es_queue_->PeekAt(*stream_pos, &es, &size); 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Find a start code and move the stream to the start code parser position. 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) off_t start_code_offset; 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) off_t start_code_size; 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool start_code_found = H264Parser::FindStartCode( 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) es, size, &start_code_offset, &start_code_size); 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *stream_pos += start_code_offset; 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // No H264 start code found or NALU type not available yet. 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!start_code_found || start_code_offset + start_code_size >= size) 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Exit the parser loop when an AUD is found. 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Note: NALU header for an AUD: 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // - nal_ref_idc must be 0 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // - nal_unit_type must be H264NALU::kAUD 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (es[start_code_offset + start_code_size] == H264NALU::kAUD) 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The current NALU is not an AUD, skip the start code 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // and continue parsing the stream. 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *stream_pos += start_code_size; 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool EsParserH264::ParseFromEsQueue() { 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_LE(es_queue_->head(), current_access_unit_pos_); 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_LE(current_access_unit_pos_, next_access_unit_pos_); 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_LE(next_access_unit_pos_, es_queue_->tail()); 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Find the next AUD located at or after |current_access_unit_pos_|. This is 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // needed since initially |current_access_unit_pos_| might not point to 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // an AUD. 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Discard all the data before the updated |current_access_unit_pos_| 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // since it won't be used again. 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool aud_found = FindAUD(¤t_access_unit_pos_); 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) es_queue_->Trim(current_access_unit_pos_); 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (next_access_unit_pos_ < current_access_unit_pos_) 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) next_access_unit_pos_ = current_access_unit_pos_; 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Resume parsing later if no AUD was found. 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!aud_found) 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Find the next AUD to make sure we have a complete access unit. 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (next_access_unit_pos_ < current_access_unit_pos_ + kMinAUDSize) { 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) next_access_unit_pos_ = current_access_unit_pos_ + kMinAUDSize; 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_LE(next_access_unit_pos_, es_queue_->tail()); 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!FindAUD(&next_access_unit_pos_)) 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // At this point, we know we have a full access unit. 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool is_key_frame = false; 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int pps_id_for_access_unit = -1; 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const uint8* es; 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int size; 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) es_queue_->PeekAt(current_access_unit_pos_, &es, &size); 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int access_unit_size = base::checked_cast<int, int64>( 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) next_access_unit_pos_ - current_access_unit_pos_); 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_LE(access_unit_size, size); 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) h264_parser_->SetStream(es, access_unit_size); 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) while (true) { 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool is_eos = false; 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) H264NALU nalu; 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) switch (h264_parser_->AdvanceToNextNALU(&nalu)) { 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case H264Parser::kOk: 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case H264Parser::kInvalidStream: 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case H264Parser::kUnsupportedStream: 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case H264Parser::kEOStream: 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) is_eos = true; 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (is_eos) 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) switch (nalu.nal_unit_type) { 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case H264NALU::kAUD: { 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(LOG_LEVEL_ES) << "NALU: AUD"; 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case H264NALU::kSPS: { 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(LOG_LEVEL_ES) << "NALU: SPS"; 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int sps_id; 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (h264_parser_->ParseSPS(&sps_id) != H264Parser::kOk) 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case H264NALU::kPPS: { 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(LOG_LEVEL_ES) << "NALU: PPS"; 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int pps_id; 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (h264_parser_->ParsePPS(&pps_id) != H264Parser::kOk) 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case H264NALU::kIDRSlice: 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case H264NALU::kNonIDRSlice: { 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) is_key_frame = (nalu.nal_unit_type == H264NALU::kIDRSlice); 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(LOG_LEVEL_ES) << "NALU: slice IDR=" << is_key_frame; 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) H264SliceHeader shdr; 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (h264_parser_->ParseSliceHeader(nalu, &shdr) != H264Parser::kOk) { 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Only accept an invalid SPS/PPS at the beginning when the stream 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // does not necessarily start with an SPS/PPS/IDR. 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(damienv): Should be able to differentiate a missing SPS/PPS 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // from a slice header parsing error. 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (last_video_decoder_config_.IsValidConfig()) 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pps_id_for_access_unit = shdr.pic_parameter_set_id; 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) default: { 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(LOG_LEVEL_ES) << "NALU: " << nalu.nal_unit_type; 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Emit a frame and move the stream to the next AUD position. 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RCHECK(EmitFrame(current_access_unit_pos_, access_unit_size, 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) is_key_frame, pps_id_for_access_unit)); 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) current_access_unit_pos_ = next_access_unit_pos_; 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) es_queue_->Trim(current_access_unit_pos_); 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool EsParserH264::EmitFrame(int64 access_unit_pos, int access_unit_size, 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool is_key_frame, int pps_id) { 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Get the access unit timing info. 2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TimingDesc current_timing_desc = GetTimingDescriptor(access_unit_pos); 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (current_timing_desc.pts == kNoTimestamp()) 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (current_timing_desc.dts == kNoDecodeTimestamp()) { 2081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci current_timing_desc.dts = 2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DecodeTimestamp::FromPresentationTime(current_timing_desc.pts); 2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Update the video decoder configuration if needed. 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const H264PPS* pps = h264_parser_->GetPPS(pps_id); 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!pps) { 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Only accept an invalid PPS at the beginning when the stream 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // does not necessarily start with an SPS/PPS/IDR. 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // In this case, the initial frames are conveyed to the upper layer with 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // an invalid VideoDecoderConfig and it's up to the upper layer 2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // to process this kind of frame accordingly. 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (last_video_decoder_config_.IsValidConfig()) 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const H264SPS* sps = h264_parser_->GetSPS(pps->seq_parameter_set_id); 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!sps) 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RCHECK(UpdateVideoDecoderConfig(sps)); 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Emit a frame. 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(LOG_LEVEL_ES) << "Emit frame: stream_pos=" << current_access_unit_pos_ 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << " size=" << access_unit_size; 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int es_size; 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const uint8* es; 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) es_queue_->PeekAt(current_access_unit_pos_, &es, &es_size); 2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CHECK_GE(es_size, access_unit_size); 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(wolenetz/acolwell): Validate and use a common cross-parser TrackId 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // type and allow multiple video tracks. See https://crbug.com/341581. 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<StreamParserBuffer> stream_parser_buffer = 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) StreamParserBuffer::CopyFrom( 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) es, 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) access_unit_size, 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) is_key_frame, 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DemuxerStream::VIDEO, 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 0); 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) stream_parser_buffer->SetDecodeTimestamp(current_timing_desc.dts); 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) stream_parser_buffer->set_timestamp(current_timing_desc.pts); 248116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch es_adapter_.OnNewBuffer(stream_parser_buffer); 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool EsParserH264::UpdateVideoDecoderConfig(const H264SPS* sps) { 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Set the SAR to 1 when not specified in the H264 stream. 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int sar_width = (sps->sar_width == 0) ? 1 : sps->sar_width; 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int sar_height = (sps->sar_height == 0) ? 1 : sps->sar_height; 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(damienv): a MAP unit can be either 16 or 32 pixels. 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // although it's 16 pixels for progressive non MBAFF frames. 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::Size coded_size((sps->pic_width_in_mbs_minus1 + 1) * 16, 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (sps->pic_height_in_map_units_minus1 + 1) * 16); 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::Rect visible_rect( 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sps->frame_crop_left_offset, 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sps->frame_crop_top_offset, 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (coded_size.width() - sps->frame_crop_right_offset) - 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sps->frame_crop_left_offset, 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (coded_size.height() - sps->frame_crop_bottom_offset) - 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sps->frame_crop_top_offset); 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (visible_rect.width() <= 0 || visible_rect.height() <= 0) 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::Size natural_size( 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (visible_rect.width() * sar_width) / sar_height, 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) visible_rect.height()); 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (natural_size.width() == 0) 2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VideoDecoderConfig video_decoder_config( 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kCodecH264, 2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VIDEO_CODEC_PROFILE_UNKNOWN, 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VideoFrame::YV12, 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) coded_size, 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) visible_rect, 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) natural_size, 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, 0, 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) false); 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!video_decoder_config.Matches(last_video_decoder_config_)) { 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Profile IDC: " << sps->profile_idc; 2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Level IDC: " << sps->level_idc; 2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Pic width: " << coded_size.width(); 2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Pic height: " << coded_size.height(); 2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "log2_max_frame_num_minus4: " 2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << sps->log2_max_frame_num_minus4; 2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "SAR: width=" << sps->sar_width 2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << " height=" << sps->sar_height; 2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) last_video_decoder_config_ = video_decoder_config; 296116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch es_adapter_.OnConfigChanged(video_decoder_config); 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace mp2t 3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace media 304