Commit 6d3d0272 by xiongziliang

删除冗余文件

更新licence日期
parent 6a649174
Subproject commit 7cfb157c63ce33c2e14461c0b9fe444318bfd217
Subproject commit 682965692e26ac50652cb574625e3f20e1a651ba
MIT License
Copyright (c) 2016 xiongziliang <771730766@qq.com>
Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......@@ -26,7 +26,7 @@
#include "H264.h"
#include "H264/SPSParser.h"
#include "SPSParser.h"
#include "Util/logger.h"
using namespace toolkit;
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "H264Parser.h"
#include "Util/logger.h"
using namespace toolkit;
H264Parser::H264Parser(){
}
H264Parser::~H264Parser(){
}
void H264Parser::inputH264(const string &h264,uint32_t dts){
_parser.SetStream((const uint8_t *)h264.data(), h264.size());
while (true) {
if(media::H264Parser::kOk != _parser.AdvanceToNextNALU(&_nalu)){
break;
}
switch (_nalu.nal_unit_type) {
case media::H264NALU::kNonIDRSlice:
case media::H264NALU::kIDRSlice:{
if(media::H264Parser::kOk == _parser.ParseSliceHeader(_nalu, &_shdr)){
const media::H264SPS *pPps = _parser.GetSPS(_shdr.pic_parameter_set_id);
if (pPps) {
_poc.ComputePicOrderCnt(pPps, _shdr, &_iNowPOC);
computePts(dts);
}
}
}
break;
case media::H264NALU::kSPS:{
int sps_id;
_parser.ParseSPS(&sps_id);
}
break;
case media::H264NALU::kPPS:{
int pps_id;
_parser.ParsePPS(&pps_id);
}
break;
default:
break;
}
}
}
void H264Parser::computePts(uint32_t iNowDTS) {
auto iPOCInc = _iNowPOC - _iLastPOC;
if (_shdr.slice_type % 5 == 1) {
//这是B帧
_iNowPTS = _iLastPTS + _iMsPerPOC * (iPOCInc);
} else {
//这是I帧或者P帧
_iNowPTS = iNowDTS;
//计算每一POC的时间
if(iPOCInc == 0){
WarnL << "iPOCInc = 0," << _iNowPOC << " " << _iLastPOC;
}else{
_iMsPerPOC = (_iNowPTS - _iLastPTS) / iPOCInc;
}
_iLastPTS = _iNowPTS;
_iLastPOC = _iNowPOC;
}
// DebugL << _shdr.slice_type
// <<"\r\nNOW:"
// << _iNowPOC << " "
// << _iNowPTS << " "
// << iNowDTS << " "
// << "\r\nLST:"
// << _iLastPOC << " "
// << _iLastPTS << " "
// << _iMsPerPOC << endl;
}
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef H264Parser_h
#define H264Parser_h
#include <stdio.h>
#include <string>
#include "h264_poc.h"
#include "h264_parser.h"
using namespace std;
#ifndef INT32_MAX
#define INT32_MAX 0x7FFFFFFF
#endif//INT32_MAX
class H264Parser{
public:
H264Parser();
virtual ~H264Parser();
void inputH264(const string &h264,uint32_t dts);
int32_t getPOC() const{
return _iNowPOC;
}
int getSliceType() const{
return _shdr.slice_type;
}
int getNaluType() const{
return _nalu.nal_unit_type;
}
uint32_t getPts() const{
return _iNowPTS;
}
private:
media::H264Parser _parser;
media::H264POC _poc;
media::H264NALU _nalu;
media::H264SliceHeader _shdr;
int32_t _iNowPOC = INT32_MAX;
int32_t _iLastPOC = INT32_MAX;
uint32_t _iNowPTS = INT32_MAX;
uint32_t _iLastPTS = INT32_MAX;
int32_t _iMsPerPOC = 30;
void computePts(uint32_t dts);
};
#endif /* H264Parser_hpp */
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "h264_bit_reader.h"
#include "macros.h"
namespace media {
H264BitReader::H264BitReader()
: data_(NULL),
bytes_left_(0),
curr_byte_(0),
num_remaining_bits_in_curr_byte_(0),
prev_two_bytes_(0),
emulation_prevention_bytes_(0) {}
H264BitReader::~H264BitReader() {}
bool H264BitReader::Initialize(const uint8_t* data, off_t size) {
DCHECK(data);
if (size < 1)
return false;
data_ = data;
bytes_left_ = size;
num_remaining_bits_in_curr_byte_ = 0;
// Initially set to 0xffff to accept all initial two-byte sequences.
prev_two_bytes_ = 0xffff;
emulation_prevention_bytes_ = 0;
return true;
}
bool H264BitReader::UpdateCurrByte() {
if (bytes_left_ < 1)
return false;
// Emulation prevention three-byte detection.
// If a sequence of 0x000003 is found, skip (ignore) the last byte (0x03).
if (*data_ == 0x03 && (prev_two_bytes_ & 0xffff) == 0) {
// Detected 0x000003, skip last byte.
++data_;
--bytes_left_;
++emulation_prevention_bytes_;
// Need another full three bytes before we can detect the sequence again.
prev_two_bytes_ = 0xffff;
if (bytes_left_ < 1)
return false;
}
// Load a new byte and advance pointers.
curr_byte_ = *data_++ & 0xff;
--bytes_left_;
num_remaining_bits_in_curr_byte_ = 8;
prev_two_bytes_ = ((prev_two_bytes_ & 0xff) << 8) | curr_byte_;
return true;
}
// Read |num_bits| (1 to 31 inclusive) from the stream and return them
// in |out|, with first bit in the stream as MSB in |out| at position
// (|num_bits| - 1).
bool H264BitReader::ReadBits(int num_bits, int* out) {
int bits_left = num_bits;
*out = 0;
DCHECK(num_bits <= 31);
while (num_remaining_bits_in_curr_byte_ < bits_left) {
// Take all that's left in current byte, shift to make space for the rest.
*out |= (curr_byte_ << (bits_left - num_remaining_bits_in_curr_byte_));
bits_left -= num_remaining_bits_in_curr_byte_;
if (!UpdateCurrByte())
return false;
}
*out |= (curr_byte_ >> (num_remaining_bits_in_curr_byte_ - bits_left));
*out &= ((1u << num_bits) - 1u);
num_remaining_bits_in_curr_byte_ -= bits_left;
return true;
}
off_t H264BitReader::NumBitsLeft() {
return (num_remaining_bits_in_curr_byte_ + bytes_left_ * 8);
}
bool H264BitReader::HasMoreRBSPData() {
// Make sure we have more bits, if we are at 0 bits in current byte and
// updating current byte fails, we don't have more data anyway.
if (num_remaining_bits_in_curr_byte_ == 0 && !UpdateCurrByte())
return false;
// If there is no more RBSP data, then |curr_byte_| contains the stop bit and
// zero padding. Check to see if there is other data instead.
// (We don't actually check for the stop bit itself, instead treating the
// invalid case of all trailing zeros identically).
if ((curr_byte_ & ((1 << (num_remaining_bits_in_curr_byte_ - 1)) - 1)) != 0)
return true;
// While the spec disallows it (7.4.1: "The last byte of the NAL unit shall
// not be equal to 0x00"), some streams have trailing null bytes anyway. We
// don't handle emulation prevention sequences because HasMoreRBSPData() is
// not used when parsing slices (where cabac_zero_word elements are legal).
for (off_t i = 0; i < bytes_left_; i++) {
if (data_[i] != 0)
return true;
}
bytes_left_ = 0;
return false;
}
size_t H264BitReader::NumEmulationPreventionBytesRead() {
return emulation_prevention_bytes_;
}
} // namespace media
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This file contains an implementation of an H264 Annex-B video stream parser.
#ifndef MEDIA_FILTERS_H264_BIT_READER_H_
#define MEDIA_FILTERS_H264_BIT_READER_H_
#include <stddef.h>
#include <stdint.h>
#include <sys/types.h>
#include "macros.h"
using namespace std;
namespace media {
// A class to provide bit-granularity reading of H.264 streams.
// This is not a generic bit reader class, as it takes into account
// H.264 stream-specific constraints, such as skipping emulation-prevention
// bytes and stop bits. See spec for more details.
class MEDIA_EXPORT H264BitReader {
public:
H264BitReader();
~H264BitReader();
// Initialize the reader to start reading at |data|, |size| being size
// of |data| in bytes.
// Return false on insufficient size of stream..
// TODO(posciak,fischman): consider replacing Initialize() with
// heap-allocating and creating bit readers on demand instead.
bool Initialize(const uint8_t* data, off_t size);
// Read |num_bits| next bits from stream and return in |*out|, first bit
// from the stream starting at |num_bits| position in |*out|.
// |num_bits| may be 1-32, inclusive.
// Return false if the given number of bits cannot be read (not enough
// bits in the stream), true otherwise.
bool ReadBits(int num_bits, int* out);
// Return the number of bits left in the stream.
off_t NumBitsLeft();
// See the definition of more_rbsp_data() in spec.
bool HasMoreRBSPData();
// Return the number of emulation prevention bytes already read.
size_t NumEmulationPreventionBytesRead();
private:
// Advance to the next byte, loading it into curr_byte_.
// Return false on end of stream.
bool UpdateCurrByte();
// Pointer to the next unread (not in curr_byte_) byte in the stream.
const uint8_t* data_;
// Bytes left in the stream (without the curr_byte_).
off_t bytes_left_;
// Contents of the current byte; first unread bit starting at position
// 8 - num_remaining_bits_in_curr_byte_ from MSB.
int curr_byte_;
// Number of bits remaining in curr_byte_
int num_remaining_bits_in_curr_byte_;
// Used in emulation prevention three byte detection (see spec).
// Initially set to 0xffff to accept all initial two-byte sequences.
int prev_two_bytes_;
// Number of emulation preventation bytes (0x000003) we met.
size_t emulation_prevention_bytes_;
DISALLOW_COPY_AND_ASSIGN(H264BitReader);
};
} // namespace media
#endif // MEDIA_FILTERS_H264_BIT_READER_H_
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "h264_parser.h"
#include <limits>
#include <memory>
#include "macros.h"
#include "Util/logger.h"
using namespace toolkit;
template <class ForwardIterator>
void STLDeleteContainerPairSecondPointers(ForwardIterator begin,
ForwardIterator end) {
while (begin != end) {
ForwardIterator temp = begin;
++begin;
delete temp->second;
}
}
template <class T>
void STLDeleteValues(T* container) {
if (!container)
return;
STLDeleteContainerPairSecondPointers(container->begin(), container->end());
container->clear();
}
namespace media {
bool H264SliceHeader::IsPSlice() const {
return (slice_type % 5 == kPSlice);
}
bool H264SliceHeader::IsBSlice() const {
return (slice_type % 5 == kBSlice);
}
bool H264SliceHeader::IsISlice() const {
return (slice_type % 5 == kISlice);
}
bool H264SliceHeader::IsSPSlice() const {
return (slice_type % 5 == kSPSlice);
}
bool H264SliceHeader::IsSISlice() const {
return (slice_type % 5 == kSISlice);
}
H264NALU::H264NALU() {
memset(this, 0, sizeof(*this));
}
H264SPS::H264SPS() {
memset(this, 0, sizeof(*this));
}
H264PPS::H264PPS() {
memset(this, 0, sizeof(*this));
}
H264SliceHeader::H264SliceHeader() {
memset(this, 0, sizeof(*this));
}
H264SEIMessage::H264SEIMessage() {
memset(this, 0, sizeof(*this));
}
#define READ_BITS_OR_RETURN(num_bits, out) \
do { \
int _out; \
if (!br_.ReadBits(num_bits, &_out)) { \
DebugL \
<< "Error in stream: unexpected EOS while trying to read " #out; \
return kInvalidStream; \
} \
*out = _out; \
} while (0)
#define READ_BOOL_OR_RETURN(out) \
do { \
int _out; \
if (!br_.ReadBits(1, &_out)) { \
DebugL \
<< "Error in stream: unexpected EOS while trying to read " #out; \
return kInvalidStream; \
} \
*out = _out != 0; \
} while (0)
#define READ_UE_OR_RETURN(out) \
do { \
if (ReadUE(out) != kOk) { \
DebugL << "Error in stream: invalid value while trying to read " #out; \
return kInvalidStream; \
} \
} while (0)
#define READ_SE_OR_RETURN(out) \
do { \
if (ReadSE(out) != kOk) { \
DebugL << "Error in stream: invalid value while trying to read " #out; \
return kInvalidStream; \
} \
} while (0)
#define IN_RANGE_OR_RETURN(val, min, max) \
do { \
if ((val) < (min) || (val) > (max)) { \
DebugL << "Error in stream: invalid value, expected " #val " to be" \
<< " in range [" << (min) << ":" << (max) << "]" \
<< " found " << (val) << " instead"; \
return kInvalidStream; \
} \
} while (0)
#define TRUE_OR_RETURN(a) \
do { \
if (!(a)) { \
DebugL << "Error in stream: invalid value, expected " << #a; \
return kInvalidStream; \
} \
} while (0)
// ISO 14496 part 10
// VUI parameters: Table E-1 "Meaning of sample aspect ratio indicator"
static const int kTableSarWidth[] = {
0, 1, 12, 10, 16, 40, 24, 20, 32, 80, 18, 15, 64, 160, 4, 3, 2
};
static const int kTableSarHeight[] = {
0, 1, 11, 11, 11, 33, 11, 11, 11, 33, 11, 11, 33, 99, 3, 2, 1
};
static_assert(arraysize(kTableSarWidth) == arraysize(kTableSarHeight),
"sar tables must have the same size");
H264Parser::H264Parser() {
Reset();
}
H264Parser::~H264Parser() {
STLDeleteValues(&active_SPSes_);
STLDeleteValues(&active_PPSes_);
}
void H264Parser::Reset() {
stream_ = NULL;
bytes_left_ = 0;
encrypted_ranges_.clear();
}
void H264Parser::SetStream(const uint8_t* stream, off_t stream_size) {
std::vector<SubsampleEntry> subsamples;
SetEncryptedStream(stream, stream_size, subsamples);
}
void H264Parser::SetEncryptedStream(const uint8_t* stream,
off_t stream_size,
const std::vector<SubsampleEntry>& subsamples) {
DCHECK(stream);
DCHECK_GT(stream_size, 0);
stream_ = stream;
bytes_left_ = stream_size;
encrypted_ranges_.clear();
const uint8_t* start = stream;
const uint8_t* stream_end = stream_ + bytes_left_;
for (size_t i = 0; i < subsamples.size() && start < stream_end; ++i) {
start += subsamples[i].clear_bytes;
const uint8_t* end =
min(start + subsamples[i].cypher_bytes, stream_end);
encrypted_ranges_.Add(start, end);
start = end;
}
}
const H264PPS* H264Parser::GetPPS(int pps_id) const {
auto it = active_PPSes_.find(pps_id);
if (it == active_PPSes_.end()) {
DebugL << "Requested a nonexistent PPS id " << pps_id;
return nullptr;
}
return it->second;
}
const H264SPS* H264Parser::GetSPS(int sps_id) const {
auto it = active_SPSes_.find(sps_id);
if (it == active_SPSes_.end()) {
DebugL << "Requested a nonexistent SPS id " << sps_id;
return nullptr;
}
return it->second;
}
static inline bool IsStartCode(const uint8_t* data) {
return data[0] == 0x00 && data[1] == 0x00 && data[2] == 0x01;
}
// static
bool H264Parser::FindStartCode(const uint8_t* data,
off_t data_size,
off_t* offset,
off_t* start_code_size) {
DCHECK_GE(data_size, 0);
off_t bytes_left = data_size;
while (bytes_left >= 3) {
if (IsStartCode(data)) {
// Found three-byte start code, set pointer at its beginning.
*offset = data_size - bytes_left;
*start_code_size = 3;
// If there is a zero byte before this start code,
// then it's actually a four-byte start code, so backtrack one byte.
if (*offset > 0 && *(data - 1) == 0x00) {
--(*offset);
++(*start_code_size);
}
return true;
}
++data;
--bytes_left;
}
// End of data: offset is pointing to the first byte that was not considered
// as a possible start of a start code.
// Note: there is no security issue when receiving a negative |data_size|
// since in this case, |bytes_left| is equal to |data_size| and thus
// |*offset| is equal to 0 (valid offset).
*offset = data_size - bytes_left;
*start_code_size = 0;
return false;
}
bool H264Parser::LocateNALU(off_t* nalu_size, off_t* start_code_size) {
// Find the start code of next NALU.
off_t nalu_start_off = 0;
off_t annexb_start_code_size = 0;
if (!FindStartCodeInClearRanges(stream_, bytes_left_,
encrypted_ranges_,
&nalu_start_off, &annexb_start_code_size)) {
//DebugL << "Could not find start code, end of stream?";
return false;
}
// Move the stream to the beginning of the NALU (pointing at the start code).
stream_ += nalu_start_off;
bytes_left_ -= nalu_start_off;
const uint8_t* nalu_data = stream_ + annexb_start_code_size;
off_t max_nalu_data_size = bytes_left_ - annexb_start_code_size;
if (max_nalu_data_size <= 0) {
DebugL << "End of stream";
return false;
}
// Find the start code of next NALU;
// if successful, |nalu_size_without_start_code| is the number of bytes from
// after previous start code to before this one;
// if next start code is not found, it is still a valid NALU since there
// are some bytes left after the first start code: all the remaining bytes
// belong to the current NALU.
off_t next_start_code_size = 0;
off_t nalu_size_without_start_code = 0;
if (!FindStartCodeInClearRanges(nalu_data, max_nalu_data_size,
encrypted_ranges_,
&nalu_size_without_start_code,
&next_start_code_size)) {
nalu_size_without_start_code = max_nalu_data_size;
}
*nalu_size = nalu_size_without_start_code + annexb_start_code_size;
*start_code_size = annexb_start_code_size;
return true;
}
bool H264Parser::FindStartCodeInClearRanges(
const uint8_t* data,
off_t data_size,
const Ranges<const uint8_t*>& encrypted_ranges,
off_t* offset,
off_t* start_code_size) {
if (encrypted_ranges.size() == 0)
return FindStartCode(data, data_size, offset, start_code_size);
DCHECK_GE(data_size, 0);
const uint8_t* start = data;
do {
off_t bytes_left = data_size - (start - data);
if (!FindStartCode(start, bytes_left, offset, start_code_size))
return false;
// Construct a Ranges object that represents the region occupied
// by the start code and the 1 byte needed to read the NAL unit type.
const uint8_t* start_code = start + *offset;
const uint8_t* start_code_end = start_code + *start_code_size;
Ranges<const uint8_t*> start_code_range;
start_code_range.Add(start_code, start_code_end + 1);
if (encrypted_ranges.IntersectionWith(start_code_range).size() > 0) {
// The start code is inside an encrypted section so we need to scan
// for another start code.
*start_code_size = 0;
start += min(*offset + 1, bytes_left);
}
} while (*start_code_size == 0);
// Update |*offset| to include the data we skipped over.
*offset += start - data;
return true;
}
H264Parser::Result H264Parser::ReadUE(int* val) {
int num_bits = -1;
int bit;
int rest;
// Count the number of contiguous zero bits.
do {
READ_BITS_OR_RETURN(1, &bit);
num_bits++;
} while (bit == 0);
if (num_bits > 31)
return kInvalidStream;
// Calculate exp-Golomb code value of size num_bits.
// Special case for |num_bits| == 31 to avoid integer overflow. The only
// valid representation as an int is 2^31 - 1, so the remaining bits must
// be 0 or else the number is too large.
*val = (1u << num_bits) - 1u;
if (num_bits == 31) {
READ_BITS_OR_RETURN(num_bits, &rest);
return (rest == 0) ? kOk : kInvalidStream;
}
if (num_bits > 0) {
READ_BITS_OR_RETURN(num_bits, &rest);
*val += rest;
}
return kOk;
}
H264Parser::Result H264Parser::ReadSE(int* val) {
int ue;
Result res;
// See Chapter 9 in the spec.
res = ReadUE(&ue);
if (res != kOk)
return res;
if (ue % 2 == 0)
*val = -(ue / 2);
else
*val = ue / 2 + 1;
return kOk;
}
H264Parser::Result H264Parser::AdvanceToNextNALU(H264NALU* nalu) {
off_t start_code_size;
off_t nalu_size_with_start_code;
if (!LocateNALU(&nalu_size_with_start_code, &start_code_size)) {
//DebugL << "Could not find next NALU, bytes left in stream: " << bytes_left_;
return kEOStream;
}
nalu->data = stream_ + start_code_size;
nalu->size = nalu_size_with_start_code - start_code_size;
//DebugL << "NALU found: size=" << nalu_size_with_start_code;
// Initialize bit reader at the start of found NALU.
if (!br_.Initialize(nalu->data, nalu->size))
return kEOStream;
// Move parser state to after this NALU, so next time AdvanceToNextNALU
// is called, we will effectively be skipping it;
// other parsing functions will use the position saved
// in bit reader for parsing, so we don't have to remember it here.
stream_ += nalu_size_with_start_code;
bytes_left_ -= nalu_size_with_start_code;
// Read NALU header, skip the forbidden_zero_bit, but check for it.
int data;
READ_BITS_OR_RETURN(1, &data);
TRUE_OR_RETURN(data == 0);
READ_BITS_OR_RETURN(2, &nalu->nal_ref_idc);
READ_BITS_OR_RETURN(5, &nalu->nal_unit_type);
/*DebugL << "NALU type: " << static_cast<int>(nalu->nal_unit_type)
<< " at: " << reinterpret_cast<const void*>(nalu->data)
<< " size: " << nalu->size
<< " ref: " << static_cast<int>(nalu->nal_ref_idc);
*/
return kOk;
}
// Default scaling lists (per spec).
static const int kDefault4x4Intra[kH264ScalingList4x4Length] = {
6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, 32, 37, 37, 42, };
static const int kDefault4x4Inter[kH264ScalingList4x4Length] = {
10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34, };
static const int kDefault8x8Intra[kH264ScalingList8x8Length] = {
6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18, 18, 18, 18, 23,
23, 23, 23, 23, 23, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27,
27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31,
31, 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42, };
static const int kDefault8x8Inter[kH264ScalingList8x8Length] = {
9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19, 19, 19, 19, 21,
21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, 24,
24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27,
27, 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35, };
static inline void DefaultScalingList4x4(
int i,
int scaling_list4x4[][kH264ScalingList4x4Length]) {
DCHECK_LT(i, 6);
if (i < 3)
memcpy(scaling_list4x4[i], kDefault4x4Intra, sizeof(kDefault4x4Intra));
else if (i < 6)
memcpy(scaling_list4x4[i], kDefault4x4Inter, sizeof(kDefault4x4Inter));
}
static inline void DefaultScalingList8x8(
int i,
int scaling_list8x8[][kH264ScalingList8x8Length]) {
DCHECK_LT(i, 6);
if (i % 2 == 0)
memcpy(scaling_list8x8[i], kDefault8x8Intra, sizeof(kDefault8x8Intra));
else
memcpy(scaling_list8x8[i], kDefault8x8Inter, sizeof(kDefault8x8Inter));
}
static void FallbackScalingList4x4(
int i,
const int default_scaling_list_intra[],
const int default_scaling_list_inter[],
int scaling_list4x4[][kH264ScalingList4x4Length]) {
static const int kScalingList4x4ByteSize =
sizeof(scaling_list4x4[0][0]) * kH264ScalingList4x4Length;
switch (i) {
case 0:
memcpy(scaling_list4x4[i], default_scaling_list_intra,
kScalingList4x4ByteSize);
break;
case 1:
memcpy(scaling_list4x4[i], scaling_list4x4[0], kScalingList4x4ByteSize);
break;
case 2:
memcpy(scaling_list4x4[i], scaling_list4x4[1], kScalingList4x4ByteSize);
break;
case 3:
memcpy(scaling_list4x4[i], default_scaling_list_inter,
kScalingList4x4ByteSize);
break;
case 4:
memcpy(scaling_list4x4[i], scaling_list4x4[3], kScalingList4x4ByteSize);
break;
case 5:
memcpy(scaling_list4x4[i], scaling_list4x4[4], kScalingList4x4ByteSize);
break;
default:
NOTREACHED();
break;
}
}
static void FallbackScalingList8x8(
int i,
const int default_scaling_list_intra[],
const int default_scaling_list_inter[],
int scaling_list8x8[][kH264ScalingList8x8Length]) {
static const int kScalingList8x8ByteSize =
sizeof(scaling_list8x8[0][0]) * kH264ScalingList8x8Length;
switch (i) {
case 0:
memcpy(scaling_list8x8[i], default_scaling_list_intra,
kScalingList8x8ByteSize);
break;
case 1:
memcpy(scaling_list8x8[i], default_scaling_list_inter,
kScalingList8x8ByteSize);
break;
case 2:
memcpy(scaling_list8x8[i], scaling_list8x8[0], kScalingList8x8ByteSize);
break;
case 3:
memcpy(scaling_list8x8[i], scaling_list8x8[1], kScalingList8x8ByteSize);
break;
case 4:
memcpy(scaling_list8x8[i], scaling_list8x8[2], kScalingList8x8ByteSize);
break;
case 5:
memcpy(scaling_list8x8[i], scaling_list8x8[3], kScalingList8x8ByteSize);
break;
default:
NOTREACHED();
break;
}
}
H264Parser::Result H264Parser::ParseScalingList(int size,
int* scaling_list,
bool* use_default) {
// See chapter 7.3.2.1.1.1.
int last_scale = 8;
int next_scale = 8;
int delta_scale;
*use_default = false;
for (int j = 0; j < size; ++j) {
if (next_scale != 0) {
READ_SE_OR_RETURN(&delta_scale);
IN_RANGE_OR_RETURN(delta_scale, -128, 127);
next_scale = (last_scale + delta_scale + 256) & 0xff;
if (j == 0 && next_scale == 0) {
*use_default = true;
return kOk;
}
}
scaling_list[j] = (next_scale == 0) ? last_scale : next_scale;
last_scale = scaling_list[j];
}
return kOk;
}
H264Parser::Result H264Parser::ParseSPSScalingLists(H264SPS* sps) {
// See 7.4.2.1.1.
bool seq_scaling_list_present_flag;
bool use_default;
Result res;
// Parse scaling_list4x4.
for (int i = 0; i < 6; ++i) {
READ_BOOL_OR_RETURN(&seq_scaling_list_present_flag);
if (seq_scaling_list_present_flag) {
res = ParseScalingList(arraysize(sps->scaling_list4x4[i]),
sps->scaling_list4x4[i],
&use_default);
if (res != kOk)
return res;
if (use_default)
DefaultScalingList4x4(i, sps->scaling_list4x4);
} else {
FallbackScalingList4x4(
i, kDefault4x4Intra, kDefault4x4Inter, sps->scaling_list4x4);
}
}
// Parse scaling_list8x8.
for (int i = 0; i < ((sps->chroma_format_idc != 3) ? 2 : 6); ++i) {
READ_BOOL_OR_RETURN(&seq_scaling_list_present_flag);
if (seq_scaling_list_present_flag) {
res = ParseScalingList(arraysize(sps->scaling_list8x8[i]),
sps->scaling_list8x8[i],
&use_default);
if (res != kOk)
return res;
if (use_default)
DefaultScalingList8x8(i, sps->scaling_list8x8);
} else {
FallbackScalingList8x8(
i, kDefault8x8Intra, kDefault8x8Inter, sps->scaling_list8x8);
}
}
return kOk;
}
H264Parser::Result H264Parser::ParsePPSScalingLists(const H264SPS& sps,
H264PPS* pps) {
// See 7.4.2.2.
bool pic_scaling_list_present_flag;
bool use_default;
Result res;
for (int i = 0; i < 6; ++i) {
READ_BOOL_OR_RETURN(&pic_scaling_list_present_flag);
if (pic_scaling_list_present_flag) {
res = ParseScalingList(arraysize(pps->scaling_list4x4[i]),
pps->scaling_list4x4[i],
&use_default);
if (res != kOk)
return res;
if (use_default)
DefaultScalingList4x4(i, pps->scaling_list4x4);
} else {
if (sps.seq_scaling_matrix_present_flag) {
// Table 7-2 fallback rule A in spec.
FallbackScalingList4x4(
i, kDefault4x4Intra, kDefault4x4Inter, pps->scaling_list4x4);
} else {
// Table 7-2 fallback rule B in spec.
FallbackScalingList4x4(i,
sps.scaling_list4x4[0],
sps.scaling_list4x4[3],
pps->scaling_list4x4);
}
}
}
if (pps->transform_8x8_mode_flag) {
for (int i = 0; i < ((sps.chroma_format_idc != 3) ? 2 : 6); ++i) {
READ_BOOL_OR_RETURN(&pic_scaling_list_present_flag);
if (pic_scaling_list_present_flag) {
res = ParseScalingList(arraysize(pps->scaling_list8x8[i]),
pps->scaling_list8x8[i],
&use_default);
if (res != kOk)
return res;
if (use_default)
DefaultScalingList8x8(i, pps->scaling_list8x8);
} else {
if (sps.seq_scaling_matrix_present_flag) {
// Table 7-2 fallback rule A in spec.
FallbackScalingList8x8(
i, kDefault8x8Intra, kDefault8x8Inter, pps->scaling_list8x8);
} else {
// Table 7-2 fallback rule B in spec.
FallbackScalingList8x8(i,
sps.scaling_list8x8[0],
sps.scaling_list8x8[1],
pps->scaling_list8x8);
}
}
}
}
return kOk;
}
H264Parser::Result H264Parser::ParseAndIgnoreHRDParameters(
bool* hrd_parameters_present) {
int data;
READ_BOOL_OR_RETURN(&data); // {nal,vcl}_hrd_parameters_present_flag
if (!data)
return kOk;
*hrd_parameters_present = true;
int cpb_cnt_minus1;
READ_UE_OR_RETURN(&cpb_cnt_minus1);
IN_RANGE_OR_RETURN(cpb_cnt_minus1, 0, 31);
READ_BITS_OR_RETURN(8, &data); // bit_rate_scale, cpb_size_scale
for (int i = 0; i <= cpb_cnt_minus1; ++i) {
READ_UE_OR_RETURN(&data); // bit_rate_value_minus1[i]
READ_UE_OR_RETURN(&data); // cpb_size_value_minus1[i]
READ_BOOL_OR_RETURN(&data); // cbr_flag
}
READ_BITS_OR_RETURN(20, &data); // cpb/dpb delays, etc.
return kOk;
}
H264Parser::Result H264Parser::ParseVUIParameters(H264SPS* sps) {
bool aspect_ratio_info_present_flag;
READ_BOOL_OR_RETURN(&aspect_ratio_info_present_flag);
if (aspect_ratio_info_present_flag) {
int aspect_ratio_idc;
READ_BITS_OR_RETURN(8, &aspect_ratio_idc);
if (aspect_ratio_idc == H264SPS::kExtendedSar) {
READ_BITS_OR_RETURN(16, &sps->sar_width);
READ_BITS_OR_RETURN(16, &sps->sar_height);
} else {
const int max_aspect_ratio_idc = arraysize(kTableSarWidth) - 1;
IN_RANGE_OR_RETURN(aspect_ratio_idc, 0, max_aspect_ratio_idc);
sps->sar_width = kTableSarWidth[aspect_ratio_idc];
sps->sar_height = kTableSarHeight[aspect_ratio_idc];
}
}
int data;
// Read and ignore overscan and video signal type info.
READ_BOOL_OR_RETURN(&data); // overscan_info_present_flag
if (data)
READ_BOOL_OR_RETURN(&data); // overscan_appropriate_flag
READ_BOOL_OR_RETURN(&data); // video_signal_type_present_flag
if (data) {
READ_BITS_OR_RETURN(3, &data); // video_format
READ_BOOL_OR_RETURN(&data); // video_full_range_flag
READ_BOOL_OR_RETURN(&data); // colour_description_present_flag
if (data)
READ_BITS_OR_RETURN(24, &data); // color description syntax elements
}
READ_BOOL_OR_RETURN(&data); // chroma_loc_info_present_flag
if (data) {
READ_UE_OR_RETURN(&data); // chroma_sample_loc_type_top_field
READ_UE_OR_RETURN(&data); // chroma_sample_loc_type_bottom_field
}
// Read and ignore timing info.
READ_BOOL_OR_RETURN(&data); // timing_info_present_flag
if (data) {
READ_BITS_OR_RETURN(16, &data); // num_units_in_tick
READ_BITS_OR_RETURN(16, &data); // num_units_in_tick
READ_BITS_OR_RETURN(16, &data); // time_scale
READ_BITS_OR_RETURN(16, &data); // time_scale
READ_BOOL_OR_RETURN(&data); // fixed_frame_rate_flag
}
// Read and ignore NAL HRD parameters, if present.
bool hrd_parameters_present = false;
Result res = ParseAndIgnoreHRDParameters(&hrd_parameters_present);
if (res != kOk)
return res;
// Read and ignore VCL HRD parameters, if present.
res = ParseAndIgnoreHRDParameters(&hrd_parameters_present);
if (res != kOk)
return res;
if (hrd_parameters_present) // One of NAL or VCL params present is enough.
READ_BOOL_OR_RETURN(&data); // low_delay_hrd_flag
READ_BOOL_OR_RETURN(&data); // pic_struct_present_flag
READ_BOOL_OR_RETURN(&sps->bitstream_restriction_flag);
if (sps->bitstream_restriction_flag) {
READ_BOOL_OR_RETURN(&data); // motion_vectors_over_pic_boundaries_flag
READ_UE_OR_RETURN(&data); // max_bytes_per_pic_denom
READ_UE_OR_RETURN(&data); // max_bits_per_mb_denom
READ_UE_OR_RETURN(&data); // log2_max_mv_length_horizontal
READ_UE_OR_RETURN(&data); // log2_max_mv_length_vertical
READ_UE_OR_RETURN(&sps->max_num_reorder_frames);
READ_UE_OR_RETURN(&sps->max_dec_frame_buffering);
TRUE_OR_RETURN(sps->max_dec_frame_buffering >= sps->max_num_ref_frames);
IN_RANGE_OR_RETURN(
sps->max_num_reorder_frames, 0, sps->max_dec_frame_buffering);
}
return kOk;
}
static void FillDefaultSeqScalingLists(H264SPS* sps) {
for (int i = 0; i < 6; ++i)
for (int j = 0; j < kH264ScalingList4x4Length; ++j)
sps->scaling_list4x4[i][j] = 16;
for (int i = 0; i < 6; ++i)
for (int j = 0; j < kH264ScalingList8x8Length; ++j)
sps->scaling_list8x8[i][j] = 16;
}
H264Parser::Result H264Parser::ParseSPS(int* sps_id) {
// See 7.4.2.1.
int data;
Result res;
*sps_id = -1;
std::unique_ptr<H264SPS> sps(new H264SPS());
READ_BITS_OR_RETURN(8, &sps->profile_idc);
READ_BOOL_OR_RETURN(&sps->constraint_set0_flag);
READ_BOOL_OR_RETURN(&sps->constraint_set1_flag);
READ_BOOL_OR_RETURN(&sps->constraint_set2_flag);
READ_BOOL_OR_RETURN(&sps->constraint_set3_flag);
READ_BOOL_OR_RETURN(&sps->constraint_set4_flag);
READ_BOOL_OR_RETURN(&sps->constraint_set5_flag);
READ_BITS_OR_RETURN(2, &data); // reserved_zero_2bits
READ_BITS_OR_RETURN(8, &sps->level_idc);
READ_UE_OR_RETURN(&sps->seq_parameter_set_id);
TRUE_OR_RETURN(sps->seq_parameter_set_id < 32);
if (sps->profile_idc == 100 || sps->profile_idc == 110 ||
sps->profile_idc == 122 || sps->profile_idc == 244 ||
sps->profile_idc == 44 || sps->profile_idc == 83 ||
sps->profile_idc == 86 || sps->profile_idc == 118 ||
sps->profile_idc == 128) {
READ_UE_OR_RETURN(&sps->chroma_format_idc);
TRUE_OR_RETURN(sps->chroma_format_idc < 4);
if (sps->chroma_format_idc == 3)
READ_BOOL_OR_RETURN(&sps->separate_colour_plane_flag);
READ_UE_OR_RETURN(&sps->bit_depth_luma_minus8);
TRUE_OR_RETURN(sps->bit_depth_luma_minus8 < 7);
READ_UE_OR_RETURN(&sps->bit_depth_chroma_minus8);
TRUE_OR_RETURN(sps->bit_depth_chroma_minus8 < 7);
READ_BOOL_OR_RETURN(&sps->qpprime_y_zero_transform_bypass_flag);
READ_BOOL_OR_RETURN(&sps->seq_scaling_matrix_present_flag);
if (sps->seq_scaling_matrix_present_flag) {
//DebugL << "Scaling matrix present";
res = ParseSPSScalingLists(sps.get());
if (res != kOk)
return res;
} else {
FillDefaultSeqScalingLists(sps.get());
}
} else {
sps->chroma_format_idc = 1;
FillDefaultSeqScalingLists(sps.get());
}
if (sps->separate_colour_plane_flag)
sps->chroma_array_type = 0;
else
sps->chroma_array_type = sps->chroma_format_idc;
READ_UE_OR_RETURN(&sps->log2_max_frame_num_minus4);
TRUE_OR_RETURN(sps->log2_max_frame_num_minus4 < 13);
READ_UE_OR_RETURN(&sps->pic_order_cnt_type);
TRUE_OR_RETURN(sps->pic_order_cnt_type < 3);
sps->expected_delta_per_pic_order_cnt_cycle = 0;
if (sps->pic_order_cnt_type == 0) {
READ_UE_OR_RETURN(&sps->log2_max_pic_order_cnt_lsb_minus4);
TRUE_OR_RETURN(sps->log2_max_pic_order_cnt_lsb_minus4 < 13);
} else if (sps->pic_order_cnt_type == 1) {
READ_BOOL_OR_RETURN(&sps->delta_pic_order_always_zero_flag);
READ_SE_OR_RETURN(&sps->offset_for_non_ref_pic);
READ_SE_OR_RETURN(&sps->offset_for_top_to_bottom_field);
READ_UE_OR_RETURN(&sps->num_ref_frames_in_pic_order_cnt_cycle);
TRUE_OR_RETURN(sps->num_ref_frames_in_pic_order_cnt_cycle < 255);
for (int i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; ++i) {
READ_SE_OR_RETURN(&sps->offset_for_ref_frame[i]);
sps->expected_delta_per_pic_order_cnt_cycle +=
sps->offset_for_ref_frame[i];
}
}
READ_UE_OR_RETURN(&sps->max_num_ref_frames);
READ_BOOL_OR_RETURN(&sps->gaps_in_frame_num_value_allowed_flag);
READ_UE_OR_RETURN(&sps->pic_width_in_mbs_minus1);
READ_UE_OR_RETURN(&sps->pic_height_in_map_units_minus1);
READ_BOOL_OR_RETURN(&sps->frame_mbs_only_flag);
if (!sps->frame_mbs_only_flag)
READ_BOOL_OR_RETURN(&sps->mb_adaptive_frame_field_flag);
READ_BOOL_OR_RETURN(&sps->direct_8x8_inference_flag);
READ_BOOL_OR_RETURN(&sps->frame_cropping_flag);
if (sps->frame_cropping_flag) {
READ_UE_OR_RETURN(&sps->frame_crop_left_offset);
READ_UE_OR_RETURN(&sps->frame_crop_right_offset);
READ_UE_OR_RETURN(&sps->frame_crop_top_offset);
READ_UE_OR_RETURN(&sps->frame_crop_bottom_offset);
}
READ_BOOL_OR_RETURN(&sps->vui_parameters_present_flag);
if (sps->vui_parameters_present_flag) {
//DebugL << "VUI parameters present";
res = ParseVUIParameters(sps.get());
if (res != kOk)
return res;
}
// If an SPS with the same id already exists, replace it.
*sps_id = sps->seq_parameter_set_id;
delete active_SPSes_[*sps_id];
active_SPSes_[*sps_id] = sps.release();
return kOk;
}
H264Parser::Result H264Parser::ParsePPS(int* pps_id) {
// See 7.4.2.2.
const H264SPS* sps;
Result res;
*pps_id = -1;
std::unique_ptr<H264PPS> pps(new H264PPS());
READ_UE_OR_RETURN(&pps->pic_parameter_set_id);
READ_UE_OR_RETURN(&pps->seq_parameter_set_id);
TRUE_OR_RETURN(pps->seq_parameter_set_id < 32);
if (active_SPSes_.find(pps->seq_parameter_set_id) == active_SPSes_.end()) {
DebugL << "Invalid stream, no SPS id: " << pps->seq_parameter_set_id;
return kInvalidStream;
}
sps = GetSPS(pps->seq_parameter_set_id);
TRUE_OR_RETURN(sps);
READ_BOOL_OR_RETURN(&pps->entropy_coding_mode_flag);
READ_BOOL_OR_RETURN(&pps->bottom_field_pic_order_in_frame_present_flag);
READ_UE_OR_RETURN(&pps->num_slice_groups_minus1);
if (pps->num_slice_groups_minus1 > 1) {
DebugL << "Slice groups not supported";
return kUnsupportedStream;
}
READ_UE_OR_RETURN(&pps->num_ref_idx_l0_default_active_minus1);
TRUE_OR_RETURN(pps->num_ref_idx_l0_default_active_minus1 < 32);
READ_UE_OR_RETURN(&pps->num_ref_idx_l1_default_active_minus1);
TRUE_OR_RETURN(pps->num_ref_idx_l1_default_active_minus1 < 32);
READ_BOOL_OR_RETURN(&pps->weighted_pred_flag);
READ_BITS_OR_RETURN(2, &pps->weighted_bipred_idc);
TRUE_OR_RETURN(pps->weighted_bipred_idc < 3);
READ_SE_OR_RETURN(&pps->pic_init_qp_minus26);
IN_RANGE_OR_RETURN(pps->pic_init_qp_minus26, -26, 25);
READ_SE_OR_RETURN(&pps->pic_init_qs_minus26);
IN_RANGE_OR_RETURN(pps->pic_init_qs_minus26, -26, 25);
READ_SE_OR_RETURN(&pps->chroma_qp_index_offset);
IN_RANGE_OR_RETURN(pps->chroma_qp_index_offset, -12, 12);
pps->second_chroma_qp_index_offset = pps->chroma_qp_index_offset;
READ_BOOL_OR_RETURN(&pps->deblocking_filter_control_present_flag);
READ_BOOL_OR_RETURN(&pps->constrained_intra_pred_flag);
READ_BOOL_OR_RETURN(&pps->redundant_pic_cnt_present_flag);
if (br_.HasMoreRBSPData()) {
READ_BOOL_OR_RETURN(&pps->transform_8x8_mode_flag);
READ_BOOL_OR_RETURN(&pps->pic_scaling_matrix_present_flag);
if (pps->pic_scaling_matrix_present_flag) {
DebugL << "Picture scaling matrix present";
res = ParsePPSScalingLists(*sps, pps.get());
if (res != kOk)
return res;
}
READ_SE_OR_RETURN(&pps->second_chroma_qp_index_offset);
}
// If a PPS with the same id already exists, replace it.
*pps_id = pps->pic_parameter_set_id;
delete active_PPSes_[*pps_id];
active_PPSes_[*pps_id] = pps.release();
return kOk;
}
H264Parser::Result H264Parser::ParseRefPicListModification(
int num_ref_idx_active_minus1,
H264ModificationOfPicNum* ref_list_mods) {
H264ModificationOfPicNum* pic_num_mod;
if (num_ref_idx_active_minus1 >= 32)
return kInvalidStream;
for (int i = 0; i < 32; ++i) {
pic_num_mod = &ref_list_mods[i];
READ_UE_OR_RETURN(&pic_num_mod->modification_of_pic_nums_idc);
TRUE_OR_RETURN(pic_num_mod->modification_of_pic_nums_idc < 4);
switch (pic_num_mod->modification_of_pic_nums_idc) {
case 0:
case 1:
READ_UE_OR_RETURN(&pic_num_mod->abs_diff_pic_num_minus1);
break;
case 2:
READ_UE_OR_RETURN(&pic_num_mod->long_term_pic_num);
break;
case 3:
// Per spec, list cannot be empty.
if (i == 0)
return kInvalidStream;
return kOk;
default:
return kInvalidStream;
}
}
// If we got here, we didn't get loop end marker prematurely,
// so make sure it is there for our client.
int modification_of_pic_nums_idc;
READ_UE_OR_RETURN(&modification_of_pic_nums_idc);
TRUE_OR_RETURN(modification_of_pic_nums_idc == 3);
return kOk;
}
H264Parser::Result H264Parser::ParseRefPicListModifications(
H264SliceHeader* shdr) {
Result res;
if (!shdr->IsISlice() && !shdr->IsSISlice()) {
READ_BOOL_OR_RETURN(&shdr->ref_pic_list_modification_flag_l0);
if (shdr->ref_pic_list_modification_flag_l0) {
res = ParseRefPicListModification(shdr->num_ref_idx_l0_active_minus1,
shdr->ref_list_l0_modifications);
if (res != kOk)
return res;
}
}
if (shdr->IsBSlice()) {
READ_BOOL_OR_RETURN(&shdr->ref_pic_list_modification_flag_l1);
if (shdr->ref_pic_list_modification_flag_l1) {
res = ParseRefPicListModification(shdr->num_ref_idx_l1_active_minus1,
shdr->ref_list_l1_modifications);
if (res != kOk)
return res;
}
}
return kOk;
}
H264Parser::Result H264Parser::ParseWeightingFactors(
int num_ref_idx_active_minus1,
int chroma_array_type,
int luma_log2_weight_denom,
int chroma_log2_weight_denom,
H264WeightingFactors* w_facts) {
int def_luma_weight = 1 << luma_log2_weight_denom;
int def_chroma_weight = 1 << chroma_log2_weight_denom;
for (int i = 0; i < num_ref_idx_active_minus1 + 1; ++i) {
READ_BOOL_OR_RETURN(&w_facts->luma_weight_flag);
if (w_facts->luma_weight_flag) {
READ_SE_OR_RETURN(&w_facts->luma_weight[i]);
IN_RANGE_OR_RETURN(w_facts->luma_weight[i], -128, 127);
READ_SE_OR_RETURN(&w_facts->luma_offset[i]);
IN_RANGE_OR_RETURN(w_facts->luma_offset[i], -128, 127);
} else {
w_facts->luma_weight[i] = def_luma_weight;
w_facts->luma_offset[i] = 0;
}
if (chroma_array_type != 0) {
READ_BOOL_OR_RETURN(&w_facts->chroma_weight_flag);
if (w_facts->chroma_weight_flag) {
for (int j = 0; j < 2; ++j) {
READ_SE_OR_RETURN(&w_facts->chroma_weight[i][j]);
IN_RANGE_OR_RETURN(w_facts->chroma_weight[i][j], -128, 127);
READ_SE_OR_RETURN(&w_facts->chroma_offset[i][j]);
IN_RANGE_OR_RETURN(w_facts->chroma_offset[i][j], -128, 127);
}
} else {
for (int j = 0; j < 2; ++j) {
w_facts->chroma_weight[i][j] = def_chroma_weight;
w_facts->chroma_offset[i][j] = 0;
}
}
}
}
return kOk;
}
H264Parser::Result H264Parser::ParsePredWeightTable(const H264SPS& sps,
H264SliceHeader* shdr) {
READ_UE_OR_RETURN(&shdr->luma_log2_weight_denom);
TRUE_OR_RETURN(shdr->luma_log2_weight_denom < 8);
if (sps.chroma_array_type != 0)
READ_UE_OR_RETURN(&shdr->chroma_log2_weight_denom);
TRUE_OR_RETURN(shdr->chroma_log2_weight_denom < 8);
Result res = ParseWeightingFactors(shdr->num_ref_idx_l0_active_minus1,
sps.chroma_array_type,
shdr->luma_log2_weight_denom,
shdr->chroma_log2_weight_denom,
&shdr->pred_weight_table_l0);
if (res != kOk)
return res;
if (shdr->IsBSlice()) {
res = ParseWeightingFactors(shdr->num_ref_idx_l1_active_minus1,
sps.chroma_array_type,
shdr->luma_log2_weight_denom,
shdr->chroma_log2_weight_denom,
&shdr->pred_weight_table_l1);
if (res != kOk)
return res;
}
return kOk;
}
H264Parser::Result H264Parser::ParseDecRefPicMarking(H264SliceHeader* shdr) {
size_t bits_left_at_start = br_.NumBitsLeft();
if (shdr->idr_pic_flag) {
READ_BOOL_OR_RETURN(&shdr->no_output_of_prior_pics_flag);
READ_BOOL_OR_RETURN(&shdr->long_term_reference_flag);
} else {
READ_BOOL_OR_RETURN(&shdr->adaptive_ref_pic_marking_mode_flag);
H264DecRefPicMarking* marking;
if (shdr->adaptive_ref_pic_marking_mode_flag) {
size_t i;
for (i = 0; i < arraysize(shdr->ref_pic_marking); ++i) {
marking = &shdr->ref_pic_marking[i];
READ_UE_OR_RETURN(&marking->memory_mgmnt_control_operation);
if (marking->memory_mgmnt_control_operation == 0)
break;
if (marking->memory_mgmnt_control_operation == 1 ||
marking->memory_mgmnt_control_operation == 3)
READ_UE_OR_RETURN(&marking->difference_of_pic_nums_minus1);
if (marking->memory_mgmnt_control_operation == 2)
READ_UE_OR_RETURN(&marking->long_term_pic_num);
if (marking->memory_mgmnt_control_operation == 3 ||
marking->memory_mgmnt_control_operation == 6)
READ_UE_OR_RETURN(&marking->long_term_frame_idx);
if (marking->memory_mgmnt_control_operation == 4)
READ_UE_OR_RETURN(&marking->max_long_term_frame_idx_plus1);
if (marking->memory_mgmnt_control_operation > 6)
return kInvalidStream;
}
if (i == arraysize(shdr->ref_pic_marking)) {
DebugL << "Ran out of dec ref pic marking fields";
return kUnsupportedStream;
}
}
}
shdr->dec_ref_pic_marking_bit_size = bits_left_at_start - br_.NumBitsLeft();
return kOk;
}
H264Parser::Result H264Parser::ParseSliceHeader(const H264NALU& nalu,
H264SliceHeader* shdr) {
// See 7.4.3.
const H264SPS* sps;
const H264PPS* pps;
Result res;
memset(shdr, 0, sizeof(*shdr));
shdr->idr_pic_flag = (nalu.nal_unit_type == 5);
shdr->nal_ref_idc = nalu.nal_ref_idc;
shdr->nalu_data = nalu.data;
shdr->nalu_size = nalu.size;
READ_UE_OR_RETURN(&shdr->first_mb_in_slice);
READ_UE_OR_RETURN(&shdr->slice_type);
TRUE_OR_RETURN(shdr->slice_type < 10);
READ_UE_OR_RETURN(&shdr->pic_parameter_set_id);
pps = GetPPS(shdr->pic_parameter_set_id);
TRUE_OR_RETURN(pps);
sps = GetSPS(pps->seq_parameter_set_id);
TRUE_OR_RETURN(sps);
if (sps->separate_colour_plane_flag) {
DebugL << "Interlaced streams not supported";
return kUnsupportedStream;
}
READ_BITS_OR_RETURN(sps->log2_max_frame_num_minus4 + 4, &shdr->frame_num);
if (!sps->frame_mbs_only_flag) {
READ_BOOL_OR_RETURN(&shdr->field_pic_flag);
if (shdr->field_pic_flag) {
DebugL << "Interlaced streams not supported";
return kUnsupportedStream;
}
}
if (shdr->idr_pic_flag)
READ_UE_OR_RETURN(&shdr->idr_pic_id);
size_t bits_left_at_pic_order_cnt_start = br_.NumBitsLeft();
if (sps->pic_order_cnt_type == 0) {
READ_BITS_OR_RETURN(sps->log2_max_pic_order_cnt_lsb_minus4 + 4,
&shdr->pic_order_cnt_lsb);
if (pps->bottom_field_pic_order_in_frame_present_flag &&
!shdr->field_pic_flag)
READ_SE_OR_RETURN(&shdr->delta_pic_order_cnt_bottom);
}
if (sps->pic_order_cnt_type == 1 && !sps->delta_pic_order_always_zero_flag) {
READ_SE_OR_RETURN(&shdr->delta_pic_order_cnt0);
if (pps->bottom_field_pic_order_in_frame_present_flag &&
!shdr->field_pic_flag)
READ_SE_OR_RETURN(&shdr->delta_pic_order_cnt1);
}
shdr->pic_order_cnt_bit_size =
bits_left_at_pic_order_cnt_start - br_.NumBitsLeft();
if (pps->redundant_pic_cnt_present_flag) {
READ_UE_OR_RETURN(&shdr->redundant_pic_cnt);
TRUE_OR_RETURN(shdr->redundant_pic_cnt < 128);
}
if (shdr->IsBSlice())
READ_BOOL_OR_RETURN(&shdr->direct_spatial_mv_pred_flag);
if (shdr->IsPSlice() || shdr->IsSPSlice() || shdr->IsBSlice()) {
READ_BOOL_OR_RETURN(&shdr->num_ref_idx_active_override_flag);
if (shdr->num_ref_idx_active_override_flag) {
READ_UE_OR_RETURN(&shdr->num_ref_idx_l0_active_minus1);
if (shdr->IsBSlice())
READ_UE_OR_RETURN(&shdr->num_ref_idx_l1_active_minus1);
} else {
shdr->num_ref_idx_l0_active_minus1 =
pps->num_ref_idx_l0_default_active_minus1;
if (shdr->IsBSlice()) {
shdr->num_ref_idx_l1_active_minus1 =
pps->num_ref_idx_l1_default_active_minus1;
}
}
}
if (shdr->field_pic_flag) {
TRUE_OR_RETURN(shdr->num_ref_idx_l0_active_minus1 < 32);
TRUE_OR_RETURN(shdr->num_ref_idx_l1_active_minus1 < 32);
} else {
TRUE_OR_RETURN(shdr->num_ref_idx_l0_active_minus1 < 16);
TRUE_OR_RETURN(shdr->num_ref_idx_l1_active_minus1 < 16);
}
if (nalu.nal_unit_type == H264NALU::kCodedSliceExtension) {
return kUnsupportedStream;
} else {
res = ParseRefPicListModifications(shdr);
if (res != kOk)
return res;
}
if ((pps->weighted_pred_flag && (shdr->IsPSlice() || shdr->IsSPSlice())) ||
(pps->weighted_bipred_idc == 1 && shdr->IsBSlice())) {
res = ParsePredWeightTable(*sps, shdr);
if (res != kOk)
return res;
}
if (nalu.nal_ref_idc != 0) {
res = ParseDecRefPicMarking(shdr);
if (res != kOk)
return res;
}
if (pps->entropy_coding_mode_flag && !shdr->IsISlice() &&
!shdr->IsSISlice()) {
READ_UE_OR_RETURN(&shdr->cabac_init_idc);
TRUE_OR_RETURN(shdr->cabac_init_idc < 3);
}
READ_SE_OR_RETURN(&shdr->slice_qp_delta);
if (shdr->IsSPSlice() || shdr->IsSISlice()) {
if (shdr->IsSPSlice())
READ_BOOL_OR_RETURN(&shdr->sp_for_switch_flag);
READ_SE_OR_RETURN(&shdr->slice_qs_delta);
}
if (pps->deblocking_filter_control_present_flag) {
READ_UE_OR_RETURN(&shdr->disable_deblocking_filter_idc);
TRUE_OR_RETURN(shdr->disable_deblocking_filter_idc < 3);
if (shdr->disable_deblocking_filter_idc != 1) {
READ_SE_OR_RETURN(&shdr->slice_alpha_c0_offset_div2);
IN_RANGE_OR_RETURN(shdr->slice_alpha_c0_offset_div2, -6, 6);
READ_SE_OR_RETURN(&shdr->slice_beta_offset_div2);
IN_RANGE_OR_RETURN(shdr->slice_beta_offset_div2, -6, 6);
}
}
if (pps->num_slice_groups_minus1 > 0) {
DebugL << "Slice groups not supported";
return kUnsupportedStream;
}
size_t epb = br_.NumEmulationPreventionBytesRead();
shdr->header_bit_size = (shdr->nalu_size - epb) * 8 - br_.NumBitsLeft();
return kOk;
}
H264Parser::Result H264Parser::ParseSEI(H264SEIMessage* sei_msg) {
int byte;
memset(sei_msg, 0, sizeof(*sei_msg));
READ_BITS_OR_RETURN(8, &byte);
while (byte == 0xff) {
sei_msg->type += 255;
READ_BITS_OR_RETURN(8, &byte);
}
sei_msg->type += byte;
READ_BITS_OR_RETURN(8, &byte);
while (byte == 0xff) {
sei_msg->payload_size += 255;
READ_BITS_OR_RETURN(8, &byte);
}
sei_msg->payload_size += byte;
DebugL << "Found SEI message type: " << sei_msg->type
<< " payload size: " << sei_msg->payload_size;
switch (sei_msg->type) {
case H264SEIMessage::kSEIRecoveryPoint:
READ_UE_OR_RETURN(&sei_msg->recovery_point.recovery_frame_cnt);
READ_BOOL_OR_RETURN(&sei_msg->recovery_point.exact_match_flag);
READ_BOOL_OR_RETURN(&sei_msg->recovery_point.broken_link_flag);
READ_BITS_OR_RETURN(2, &sei_msg->recovery_point.changing_slice_group_idc);
break;
default:
DebugL << "Unsupported SEI message";
break;
}
return kOk;
}
} // namespace media
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This file contains an implementation of an H264 Annex-B video stream parser.
#ifndef MEDIA_FILTERS_H264_PARSER_H_
#define MEDIA_FILTERS_H264_PARSER_H_
#include <stddef.h>
#include <stdint.h>
#include <sys/types.h>
#include <map>
#include <vector>
#include "macros.h"
#include "h264_bit_reader.h"
#include "ranges.h"
using namespace std;
namespace media {
struct SubsampleEntry {
uint32_t clear_bytes;
uint32_t cypher_bytes;
};
// For explanations of each struct and its members, see H.264 specification
// at http://www.itu.int/rec/T-REC-H.264.
struct MEDIA_EXPORT H264NALU {
H264NALU();
enum Type {
kUnspecified = 0,
kNonIDRSlice = 1,
kSliceDataA = 2,
kSliceDataB = 3,
kSliceDataC = 4,
kIDRSlice = 5,
kSEIMessage = 6,
kSPS = 7,
kPPS = 8,
kAUD = 9,
kEOSeq = 10,
kEOStream = 11,
kFiller = 12,
kSPSExt = 13,
kReserved14 = 14,
kReserved15 = 15,
kReserved16 = 16,
kReserved17 = 17,
kReserved18 = 18,
kCodedSliceAux = 19,
kCodedSliceExtension = 20,
};
// After (without) start code; we don't own the underlying memory
// and a shallow copy should be made when copying this struct.
const uint8_t* data;
off_t size; // From after start code to start code of next NALU (or EOS).
int nal_ref_idc;
int nal_unit_type;
};
enum {
kH264ScalingList4x4Length = 16,
kH264ScalingList8x8Length = 64,
};
struct MEDIA_EXPORT H264SPS {
H264SPS();
enum H264ProfileIDC {
kProfileIDCBaseline = 66,
kProfileIDCConstrainedBaseline = kProfileIDCBaseline,
kProfileIDCMain = 77,
kProfileIDScalableBaseline = 83,
kProfileIDScalableHigh = 86,
kProfileIDCHigh = 100,
kProfileIDHigh10 = 110,
kProfileIDSMultiviewHigh = 118,
kProfileIDHigh422 = 122,
kProfileIDStereoHigh = 128,
kProfileIDHigh444Predictive = 244,
};
enum AspectRatioIdc {
kExtendedSar = 255,
};
enum {
// Constants for HRD parameters (spec ch. E.2.2).
kBitRateScaleConstantTerm = 6, // Equation E-37.
kCPBSizeScaleConstantTerm = 4, // Equation E-38.
kDefaultInitialCPBRemovalDelayLength = 24,
kDefaultDPBOutputDelayLength = 24,
kDefaultTimeOffsetLength = 24,
};
int profile_idc;
bool constraint_set0_flag;
bool constraint_set1_flag;
bool constraint_set2_flag;
bool constraint_set3_flag;
bool constraint_set4_flag;
bool constraint_set5_flag;
int level_idc;
int seq_parameter_set_id;
int chroma_format_idc;
bool separate_colour_plane_flag;
int bit_depth_luma_minus8;
int bit_depth_chroma_minus8;
bool qpprime_y_zero_transform_bypass_flag;
bool seq_scaling_matrix_present_flag;
int scaling_list4x4[6][kH264ScalingList4x4Length];
int scaling_list8x8[6][kH264ScalingList8x8Length];
int log2_max_frame_num_minus4;
int pic_order_cnt_type;
int log2_max_pic_order_cnt_lsb_minus4;
bool delta_pic_order_always_zero_flag;
int offset_for_non_ref_pic;
int offset_for_top_to_bottom_field;
int num_ref_frames_in_pic_order_cnt_cycle;
int expected_delta_per_pic_order_cnt_cycle; // calculated
int offset_for_ref_frame[255];
int max_num_ref_frames;
bool gaps_in_frame_num_value_allowed_flag;
int pic_width_in_mbs_minus1;
int pic_height_in_map_units_minus1;
bool frame_mbs_only_flag;
bool mb_adaptive_frame_field_flag;
bool direct_8x8_inference_flag;
bool frame_cropping_flag;
int frame_crop_left_offset;
int frame_crop_right_offset;
int frame_crop_top_offset;
int frame_crop_bottom_offset;
bool vui_parameters_present_flag;
int sar_width; // Set to 0 when not specified.
int sar_height; // Set to 0 when not specified.
bool bitstream_restriction_flag;
int max_num_reorder_frames;
int max_dec_frame_buffering;
bool timing_info_present_flag;
int num_units_in_tick;
int time_scale;
bool fixed_frame_rate_flag;
// TODO(posciak): actually parse these instead of ParseAndIgnoreHRDParameters.
bool nal_hrd_parameters_present_flag;
int cpb_cnt_minus1;
int bit_rate_scale;
int cpb_size_scale;
int bit_rate_value_minus1[32];
int cpb_size_value_minus1[32];
bool cbr_flag[32];
int initial_cpb_removal_delay_length_minus_1;
int cpb_removal_delay_length_minus1;
int dpb_output_delay_length_minus1;
int time_offset_length;
bool low_delay_hrd_flag;
int chroma_array_type;
};
struct MEDIA_EXPORT H264PPS {
H264PPS();
int pic_parameter_set_id;
int seq_parameter_set_id;
bool entropy_coding_mode_flag;
bool bottom_field_pic_order_in_frame_present_flag;
int num_slice_groups_minus1;
// TODO(posciak): Slice groups not implemented, could be added at some point.
int num_ref_idx_l0_default_active_minus1;
int num_ref_idx_l1_default_active_minus1;
bool weighted_pred_flag;
int weighted_bipred_idc;
int pic_init_qp_minus26;
int pic_init_qs_minus26;
int chroma_qp_index_offset;
bool deblocking_filter_control_present_flag;
bool constrained_intra_pred_flag;
bool redundant_pic_cnt_present_flag;
bool transform_8x8_mode_flag;
bool pic_scaling_matrix_present_flag;
int scaling_list4x4[6][kH264ScalingList4x4Length];
int scaling_list8x8[6][kH264ScalingList8x8Length];
int second_chroma_qp_index_offset;
};
struct MEDIA_EXPORT H264ModificationOfPicNum {
int modification_of_pic_nums_idc;
union {
int abs_diff_pic_num_minus1;
int long_term_pic_num;
};
};
struct MEDIA_EXPORT H264WeightingFactors {
bool luma_weight_flag;
bool chroma_weight_flag;
int luma_weight[32];
int luma_offset[32];
int chroma_weight[32][2];
int chroma_offset[32][2];
};
struct MEDIA_EXPORT H264DecRefPicMarking {
int memory_mgmnt_control_operation;
int difference_of_pic_nums_minus1;
int long_term_pic_num;
int long_term_frame_idx;
int max_long_term_frame_idx_plus1;
};
struct MEDIA_EXPORT H264SliceHeader {
H264SliceHeader();
enum {
kRefListSize = 32,
kRefListModSize = kRefListSize
};
enum Type {
kPSlice = 0,
kBSlice = 1,
kISlice = 2,
kSPSlice = 3,
kSISlice = 4,
};
bool IsPSlice() const;
bool IsBSlice() const;
bool IsISlice() const;
bool IsSPSlice() const;
bool IsSISlice() const;
bool idr_pic_flag; // from NAL header
int nal_ref_idc; // from NAL header
const uint8_t* nalu_data; // from NAL header
off_t nalu_size; // from NAL header
off_t header_bit_size; // calculated
int first_mb_in_slice;
int slice_type;
int pic_parameter_set_id;
int colour_plane_id; // TODO(posciak): use this! http://crbug.com/139878
int frame_num;
bool field_pic_flag;
bool bottom_field_flag;
int idr_pic_id;
int pic_order_cnt_lsb;
int delta_pic_order_cnt_bottom;
int delta_pic_order_cnt0;
int delta_pic_order_cnt1;
int redundant_pic_cnt;
bool direct_spatial_mv_pred_flag;
bool num_ref_idx_active_override_flag;
int num_ref_idx_l0_active_minus1;
int num_ref_idx_l1_active_minus1;
bool ref_pic_list_modification_flag_l0;
bool ref_pic_list_modification_flag_l1;
H264ModificationOfPicNum ref_list_l0_modifications[kRefListModSize];
H264ModificationOfPicNum ref_list_l1_modifications[kRefListModSize];
int luma_log2_weight_denom;
int chroma_log2_weight_denom;
bool luma_weight_l0_flag;
bool chroma_weight_l0_flag;
H264WeightingFactors pred_weight_table_l0;
bool luma_weight_l1_flag;
bool chroma_weight_l1_flag;
H264WeightingFactors pred_weight_table_l1;
bool no_output_of_prior_pics_flag;
bool long_term_reference_flag;
bool adaptive_ref_pic_marking_mode_flag;
H264DecRefPicMarking ref_pic_marking[kRefListSize];
int cabac_init_idc;
int slice_qp_delta;
bool sp_for_switch_flag;
int slice_qs_delta;
int disable_deblocking_filter_idc;
int slice_alpha_c0_offset_div2;
int slice_beta_offset_div2;
// Calculated.
// Size in bits of dec_ref_pic_marking() syntax element.
size_t dec_ref_pic_marking_bit_size;
size_t pic_order_cnt_bit_size;
};
struct H264SEIRecoveryPoint {
int recovery_frame_cnt;
bool exact_match_flag;
bool broken_link_flag;
int changing_slice_group_idc;
};
struct MEDIA_EXPORT H264SEIMessage {
H264SEIMessage();
enum Type {
kSEIRecoveryPoint = 6,
};
int type;
int payload_size;
union {
// Placeholder; in future more supported types will contribute to more
// union members here.
H264SEIRecoveryPoint recovery_point;
};
};
// Class to parse an Annex-B H.264 stream,
// as specified in chapters 7 and Annex B of the H.264 spec.
class MEDIA_EXPORT H264Parser {
public:
enum Result {
kOk,
kInvalidStream, // error in stream
kUnsupportedStream, // stream not supported by the parser
kEOStream, // end of stream
};
// Find offset from start of data to next NALU start code
// and size of found start code (3 or 4 bytes).
// If no start code is found, offset is pointing to the first unprocessed byte
// (i.e. the first byte that was not considered as a possible start of a start
// code) and |*start_code_size| is set to 0.
// Preconditions:
// - |data_size| >= 0
// Postconditions:
// - |*offset| is between 0 and |data_size| included.
// It is strictly less than |data_size| if |data_size| > 0.
// - |*start_code_size| is either 0, 3 or 4.
static bool FindStartCode(const uint8_t* data,
off_t data_size,
off_t* offset,
off_t* start_code_size);
// Wrapper for FindStartCode() that skips over start codes that
// may appear inside of |encrypted_ranges_|.
// Returns true if a start code was found. Otherwise returns false.
static bool FindStartCodeInClearRanges(const uint8_t* data,
off_t data_size,
const Ranges<const uint8_t*>& ranges,
off_t* offset,
off_t* start_code_size);
H264Parser();
~H264Parser();
void Reset();
// Set current stream pointer to |stream| of |stream_size| in bytes,
// |stream| owned by caller.
// |subsamples| contains information about what parts of |stream| are
// encrypted.
void SetStream(const uint8_t* stream, off_t stream_size);
void SetEncryptedStream(const uint8_t* stream,
off_t stream_size,
const std::vector<SubsampleEntry>& subsamples);
// Read the stream to find the next NALU, identify it and return
// that information in |*nalu|. This advances the stream to the beginning
// of this NALU, but not past it, so subsequent calls to NALU-specific
// parsing functions (ParseSPS, etc.) will parse this NALU.
// If the caller wishes to skip the current NALU, it can call this function
// again, instead of any NALU-type specific parse functions below.
Result AdvanceToNextNALU(H264NALU* nalu);
// NALU-specific parsing functions.
// These should be called after AdvanceToNextNALU().
// SPSes and PPSes are owned by the parser class and the memory for their
// structures is managed here, not by the caller, as they are reused
// across NALUs.
//
// Parse an SPS/PPS NALU and save their data in the parser, returning id
// of the parsed structure in |*pps_id|/|*sps_id|.
// To get a pointer to a given SPS/PPS structure, use GetSPS()/GetPPS(),
// passing the returned |*sps_id|/|*pps_id| as parameter.
// TODO(posciak,fischman): consider replacing returning Result from Parse*()
// methods with a scoped_ptr and adding an AtEOS() function to check for EOS
// if Parse*() return NULL.
Result ParseSPS(int* sps_id);
Result ParsePPS(int* pps_id);
// Return a pointer to SPS/PPS with given |sps_id|/|pps_id| or NULL if not
// present.
const H264SPS* GetSPS(int sps_id) const;
const H264PPS* GetPPS(int pps_id) const;
// Slice headers and SEI messages are not used across NALUs by the parser
// and can be discarded after current NALU, so the parser does not store
// them, nor does it manage their memory.
// The caller has to provide and manage it instead.
// Parse a slice header, returning it in |*shdr|. |*nalu| must be set to
// the NALU returned from AdvanceToNextNALU() and corresponding to |*shdr|.
Result ParseSliceHeader(const H264NALU& nalu, H264SliceHeader* shdr);
// Parse a SEI message, returning it in |*sei_msg|, provided and managed
// by the caller.
Result ParseSEI(H264SEIMessage* sei_msg);
private:
// Move the stream pointer to the beginning of the next NALU,
// i.e. pointing at the next start code.
// Return true if a NALU has been found.
// If a NALU is found:
// - its size in bytes is returned in |*nalu_size| and includes
// the start code as well as the trailing zero bits.
// - the size in bytes of the start code is returned in |*start_code_size|.
bool LocateNALU(off_t* nalu_size, off_t* start_code_size);
// Exp-Golomb code parsing as specified in chapter 9.1 of the spec.
// Read one unsigned exp-Golomb code from the stream and return in |*val|.
Result ReadUE(int* val);
// Read one signed exp-Golomb code from the stream and return in |*val|.
Result ReadSE(int* val);
// Parse scaling lists (see spec).
Result ParseScalingList(int size, int* scaling_list, bool* use_default);
Result ParseSPSScalingLists(H264SPS* sps);
Result ParsePPSScalingLists(const H264SPS& sps, H264PPS* pps);
// Parse optional VUI parameters in SPS (see spec).
Result ParseVUIParameters(H264SPS* sps);
// Set |hrd_parameters_present| to true only if they are present.
Result ParseAndIgnoreHRDParameters(bool* hrd_parameters_present);
// Parse reference picture lists' modifications (see spec).
Result ParseRefPicListModifications(H264SliceHeader* shdr);
Result ParseRefPicListModification(int num_ref_idx_active_minus1,
H264ModificationOfPicNum* ref_list_mods);
// Parse prediction weight table (see spec).
Result ParsePredWeightTable(const H264SPS& sps, H264SliceHeader* shdr);
// Parse weighting factors (see spec).
Result ParseWeightingFactors(int num_ref_idx_active_minus1,
int chroma_array_type,
int luma_log2_weight_denom,
int chroma_log2_weight_denom,
H264WeightingFactors* w_facts);
// Parse decoded reference picture marking information (see spec).
Result ParseDecRefPicMarking(H264SliceHeader* shdr);
// Pointer to the current NALU in the stream.
const uint8_t* stream_;
// Bytes left in the stream after the current NALU.
off_t bytes_left_;
H264BitReader br_;
// PPSes and SPSes stored for future reference.
typedef std::map<int, H264SPS*> SPSById;
typedef std::map<int, H264PPS*> PPSById;
SPSById active_SPSes_;
PPSById active_PPSes_;
// Ranges of encrypted bytes in the buffer passed to
// SetEncryptedStream().
Ranges<const uint8_t*> encrypted_ranges_;
DISALLOW_COPY_AND_ASSIGN(H264Parser);
};
} // namespace media
#endif // MEDIA_FILTERS_H264_PARSER_H_
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stddef.h>
#include "Util/logger.h"
#include <algorithm>
#include "macros.h"
#include "h264_parser.h"
#include "h264_poc.h"
using namespace toolkit;
namespace media {
H264POC::H264POC() {
Reset();
}
H264POC::~H264POC() {
}
void H264POC::Reset() {
// It shouldn't be necessary to reset these values, but doing so will improve
// reproducibility for buggy streams.
ref_pic_order_cnt_msb_ = 0;
ref_pic_order_cnt_lsb_ = 0;
prev_frame_num_ = 0;
prev_frame_num_offset_ = 0;
}
// Check if a slice includes memory management control operation 5, which
// results in some |pic_order_cnt| state being cleared.
static bool HasMMCO5(const media::H264SliceHeader& slice_hdr) {
// Require that the frame actually has memory management control operations.
if (slice_hdr.nal_ref_idc == 0 ||
slice_hdr.idr_pic_flag ||
!slice_hdr.adaptive_ref_pic_marking_mode_flag) {
return false;
}
for (size_t i = 0; i < arraysize(slice_hdr.ref_pic_marking); i++) {
int32_t op = slice_hdr.ref_pic_marking[i].memory_mgmnt_control_operation;
if (op == 5)
return true;
// Stop at the end of the list.
if (op == 0)
return false;
}
// Should not get here, the list is always zero terminated.
return false;
}
bool H264POC::ComputePicOrderCnt(
const H264SPS* sps,
const H264SliceHeader& slice_hdr,
int32_t *pic_order_cnt) {
if (slice_hdr.field_pic_flag) {
DebugL << "Interlaced frames are not supported";
return false;
}
bool mmco5 = HasMMCO5(slice_hdr);
int32_t max_frame_num = 1 << (sps->log2_max_frame_num_minus4 + 4);
int32_t max_pic_order_cnt_lsb =
1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
// Check for invalid (including duplicate) |frame_num| values. All cases are
// treated as gaps, which is to say that nothing is done. (Gaps don't affect
// POC computation.)
if (!slice_hdr.idr_pic_flag &&
slice_hdr.frame_num != (prev_frame_num_ + 1) % max_frame_num) {
if (!sps->gaps_in_frame_num_value_allowed_flag){
//WarnL << "Invalid gap in frame_num";
}
}
// Based on T-REC-H.264 8.2.1, "Decoding process for picture order
// count", available from http://www.itu.int/rec/T-REC-H.264.
//
// Reorganized slightly from spec pseudocode to handle MMCO5 when storing
// state instead of when loading it.
switch (sps->pic_order_cnt_type) {
case 0: {
int32_t prev_pic_order_cnt_msb = ref_pic_order_cnt_msb_;
int32_t prev_pic_order_cnt_lsb = ref_pic_order_cnt_lsb_;
// For an IDR picture, clear the state.
if (slice_hdr.idr_pic_flag) {
prev_pic_order_cnt_msb = 0;
prev_pic_order_cnt_lsb = 0;
}
// 8-3. Derive |pic_order_cnt_msb|, accounting for wrapping which is
// detected when |pic_order_cnt_lsb| increases or decreases by at
// least half of its maximum.
int32_t pic_order_cnt_msb;
if ((slice_hdr.pic_order_cnt_lsb < prev_pic_order_cnt_lsb) &&
(prev_pic_order_cnt_lsb - slice_hdr.pic_order_cnt_lsb >=
max_pic_order_cnt_lsb / 2)) {
pic_order_cnt_msb = prev_pic_order_cnt_msb + max_pic_order_cnt_lsb;
} else if ((slice_hdr.pic_order_cnt_lsb > prev_pic_order_cnt_lsb) &&
(slice_hdr.pic_order_cnt_lsb - prev_pic_order_cnt_lsb >
max_pic_order_cnt_lsb / 2)) {
pic_order_cnt_msb = prev_pic_order_cnt_msb - max_pic_order_cnt_lsb;
} else {
pic_order_cnt_msb = prev_pic_order_cnt_msb;
}
// 8-4, 8-5. Derive |top_field_order_count| and |bottom_field_order_cnt|
// (assuming no interlacing).
int32_t top_foc = pic_order_cnt_msb + slice_hdr.pic_order_cnt_lsb;
int32_t bottom_foc = top_foc + slice_hdr.delta_pic_order_cnt_bottom;
*pic_order_cnt = min(top_foc, bottom_foc);
// Store state.
prev_frame_num_ = slice_hdr.frame_num;
if (slice_hdr.nal_ref_idc != 0) {
if (mmco5) {
ref_pic_order_cnt_msb_ = 0;
ref_pic_order_cnt_lsb_ = top_foc;
} else {
ref_pic_order_cnt_msb_ = pic_order_cnt_msb;
ref_pic_order_cnt_lsb_ = slice_hdr.pic_order_cnt_lsb;
}
}
break;
}
case 1: {
// 8-6. Derive |frame_num_offset|.
int32_t frame_num_offset;
if (slice_hdr.idr_pic_flag)
frame_num_offset = 0;
else if (prev_frame_num_ > slice_hdr.frame_num)
frame_num_offset = prev_frame_num_offset_ + max_frame_num;
else
frame_num_offset = prev_frame_num_offset_;
// 8-7. Derive |abs_frame_num|.
int32_t abs_frame_num;
if (sps->num_ref_frames_in_pic_order_cnt_cycle != 0)
abs_frame_num = frame_num_offset + slice_hdr.frame_num;
else
abs_frame_num = 0;
if (slice_hdr.nal_ref_idc == 0 && abs_frame_num > 0)
abs_frame_num--;
// 8-9. Derive |expected_pic_order_cnt| (the |pic_order_cnt| indicated
// by the cycle described in the SPS).
int32_t expected_pic_order_cnt = 0;
if (abs_frame_num > 0) {
// 8-8. Derive pic_order_cnt_cycle_cnt and
// frame_num_in_pic_order_cnt_cycle.
// Moved inside 8-9 to avoid division when this check is not done.
if (sps->num_ref_frames_in_pic_order_cnt_cycle == 0) {
ErrorL << "Invalid num_ref_frames_in_pic_order_cnt_cycle";
return false;
}
// H264Parser checks that num_ref_frames_in_pic_order_cnt_cycle < 255.
int32_t pic_order_cnt_cycle_cnt =
(abs_frame_num - 1) / sps->num_ref_frames_in_pic_order_cnt_cycle;
int32_t frame_num_in_pic_order_cnt_cycle =
(abs_frame_num - 1) % sps->num_ref_frames_in_pic_order_cnt_cycle;
// 8-9 continued.
expected_pic_order_cnt = pic_order_cnt_cycle_cnt *
sps->expected_delta_per_pic_order_cnt_cycle;
for (int32_t i = 0; i <= frame_num_in_pic_order_cnt_cycle; i++)
expected_pic_order_cnt += sps->offset_for_ref_frame[i];
}
if (slice_hdr.nal_ref_idc == 0)
expected_pic_order_cnt += sps->offset_for_non_ref_pic;
// 8-10. Derive |top_field_order_cnt| and |bottom_field_order_cnt|
// (assuming no interlacing).
int32_t top_foc = expected_pic_order_cnt + slice_hdr.delta_pic_order_cnt0;
int32_t bottom_foc = top_foc + sps->offset_for_top_to_bottom_field +
slice_hdr.delta_pic_order_cnt1;
*pic_order_cnt = min(top_foc, bottom_foc);
// Store state.
prev_frame_num_ = slice_hdr.frame_num;
prev_frame_num_offset_ = frame_num_offset;
if (mmco5)
prev_frame_num_offset_ = 0;
break;
}
case 2: {
// 8-11. Derive |frame_num_offset|.
int32_t frame_num_offset;
if (slice_hdr.idr_pic_flag)
frame_num_offset = 0;
else if (prev_frame_num_ > slice_hdr.frame_num)
frame_num_offset = prev_frame_num_offset_ + max_frame_num;
else
frame_num_offset = prev_frame_num_offset_;
// 8-12, 8-13. Derive |temp_pic_order_count| (it's always the
// |pic_order_cnt|, regardless of interlacing).
if (slice_hdr.idr_pic_flag)
*pic_order_cnt = 0;
else if (slice_hdr.nal_ref_idc == 0)
*pic_order_cnt = 2 * (frame_num_offset + slice_hdr.frame_num) - 1;
else
*pic_order_cnt = 2 * (frame_num_offset + slice_hdr.frame_num);
// Store state.
prev_frame_num_ = slice_hdr.frame_num;
prev_frame_num_offset_ = frame_num_offset;
if (mmco5)
prev_frame_num_offset_ = 0;
break;
}
default:
ErrorL << "Invalid pic_order_cnt_type: " << sps->pic_order_cnt_type;
return false;
}
return true;
}
} // namespace media
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_VIDEO_H264_POC_H_
#define MEDIA_VIDEO_H264_POC_H_
#include <stdint.h>
#include "macros.h"
using namespace std;
namespace media {
struct H264SPS;
struct H264SliceHeader;
class MEDIA_EXPORT H264POC {
public:
H264POC();
~H264POC();
// Compute the picture order count for a slice, storing the result into
// |*pic_order_cnt|.
bool ComputePicOrderCnt(
const H264SPS* sps,
const H264SliceHeader& slice_hdr,
int32_t* pic_order_cnt);
// Reset computation state. It's best (although not strictly required) to call
// this after a seek.
void Reset();
private:
int32_t ref_pic_order_cnt_msb_;
int32_t ref_pic_order_cnt_lsb_;
int32_t prev_frame_num_;
int32_t prev_frame_num_offset_;
DISALLOW_COPY_AND_ASSIGN(H264POC);
};
} // namespace media
#endif // MEDIA_VIDEO_H264_POC_H_
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file contains macros and macro-like constructs (e.g., templates) that
// are commonly used throughout Chromium source. (It may also contain things
// that are closely related to things that are commonly used that belong in this
// file.)
#ifndef BASE_MACROS_H_
#define BASE_MACROS_H_
#include <stddef.h> // For size_t.
// Put this in the declarations for a class to be uncopyable.
#define DISALLOW_COPY(TypeName) \
TypeName(const TypeName&) = delete
// Put this in the declarations for a class to be unassignable.
#define DISALLOW_ASSIGN(TypeName) \
void operator=(const TypeName&) = delete
// A macro to disallow the copy constructor and operator= functions.
// This should be used in the private: declarations for a class.
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&) = delete; \
void operator=(const TypeName&) = delete
// A macro to disallow all the implicit constructors, namely the
// default constructor, copy constructor and operator= functions.
//
// This should be used in the private: declarations for a class
// that wants to prevent anyone from instantiating it. This is
// especially useful for classes containing only static methods.
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
TypeName() = delete; \
DISALLOW_COPY_AND_ASSIGN(TypeName)
// The arraysize(arr) macro returns the # of elements in an array arr. The
// expression is a compile-time constant, and therefore can be used in defining
// new arrays, for example. If you use arraysize on a pointer by mistake, you
// will get a compile-time error. For the technical details, refer to
// http://blogs.msdn.com/b/the1/archive/2004/05/07/128242.aspx.
// This template function declaration is used in defining arraysize.
// Note that the function doesn't need an implementation, as we only
// use its type.
template <typename T, size_t N> char (&ArraySizeHelper(T (&array)[N]))[N];
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
// Used to explicitly mark the return value of a function as unused. If you are
// really sure you don't want to do anything with the return value of a function
// that has been marked WARN_UNUSED_RESULT, wrap it with this. Example:
//
// std::unique_ptr<MyType> my_var = ...;
// if (TakeOwnership(my_var.get()) == SUCCESS)
// ignore_result(my_var.release());
//
template<typename T>
inline void ignore_result(const T&) {
}
// The following enum should be used only as a constructor argument to indicate
// that the variable has static storage class, and that the constructor should
// do nothing to its state. It indicates to the reader that it is legal to
// declare a static instance of the class, provided the constructor is given
// the base::LINKER_INITIALIZED argument. Normally, it is unsafe to declare a
// static variable that has a constructor or a destructor because invocation
// order is undefined. However, IF the type can be initialized by filling with
// zeroes (which the loader does for static variables), AND the destructor also
// does nothing to the storage, AND there are no virtual methods, then a
// constructor declared as
// explicit MyClass(base::LinkerInitialized x) {}
// and invoked as
// static MyClass my_variable_name(base::LINKER_INITIALIZED);
namespace base {
enum LinkerInitialized { LINKER_INITIALIZED };
// Use these to declare and define a static local variable (static T;) so that
// it is leaked so that its destructors are not called at exit. If you need
// thread-safe initialization, use base/lazy_instance.h instead.
#define CR_DEFINE_STATIC_LOCAL(type, name, arguments) \
static type& name = *new type arguments
} // base
#define MEDIA_EXPORT
#include <assert.h>
#include "Util/logger.h"
using namespace toolkit;
#define DCHECK(x) if(!(x)) { ErrorL << "DCHECK " << #x <<endl; }
#define DCHECK_GT(x,y) if(!((x) > (y))) { ErrorL << "DCHECK_GT:" << #x << #y << endl; }
#define DCHECK_GE(x,y) if(!((x) >= (y))) { ErrorL << "DCHECK_GE:" << #x << #y << endl; }
#define DCHECK_LT(x,y) if(!((x) < (y))) { ErrorL << "DCHECK_LT:" << #x << #y << endl; }
#define NOTREACHED() ErrorL << "NOTREACHED" << endl;
#endif // BASE_MACROS_H_
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_BASE_RANGES_H_
#define MEDIA_BASE_RANGES_H_
#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <ostream>
#include <vector>
using namespace std;
namespace media {
// Ranges allows holding an ordered list of ranges of [start,end) intervals.
// The canonical example use-case is holding the list of ranges of buffered
// bytes or times in a <video> tag.
template <typename T> // Endpoint type; typically a base::TimeDelta or an int64_t.
class Ranges {
public:
// Allow copy & assign.
// Add (start,end) to this object, coallescing overlaps as appropriate.
// Returns the number of stored ranges, post coallescing.
size_t Add(T start, T end);
// Return the number of disjoint ranges.
size_t size() const;
// Return the "i"'th range's start & end (0-based).
T start(size_t i) const;
T end(size_t i) const;
// Clear all ranges.
void clear();
// Computes the intersection between this range and |other|.
Ranges<T> IntersectionWith(const Ranges<T>& other) const;
private:
// Wrapper around DCHECK_LT allowing comparisons of operator<<'able T's.
void DCheckLT(const T& lhs, const T& rhs) const;
// Disjoint, in increasing order of start.
std::vector<std::pair<T, T> > ranges_;
};
//////////////////////////////////////////////////////////////////////
// EVERYTHING BELOW HERE IS IMPLEMENTATION DETAIL!!
//////////////////////////////////////////////////////////////////////
template<class T>
size_t Ranges<T>::Add(T start, T end) {
if (start == end) // Nothing to be done with empty ranges.
return ranges_.size();
//DCheckLT(start, end);
size_t i;
// Walk along the array of ranges until |start| is no longer larger than the
// current interval's end.
for (i = 0; i < ranges_.size() && ranges_[i].second < start; ++i) {
// Empty body
}
// Now we know |start| belongs in the i'th slot.
// If i is the end of the range, append new range and done.
if (i == ranges_.size()) {
ranges_.push_back(std::make_pair(start, end));
return ranges_.size();
}
// If |end| is less than i->first, then [start,end) is a new (non-overlapping)
// i'th entry pushing everyone else back, and done.
if (end < ranges_[i].first) {
ranges_.insert(ranges_.begin() + i, std::make_pair(start, end));
return ranges_.size();
}
// Easy cases done. Getting here means there is overlap between [start,end)
// and the existing ranges.
// Now: start <= i->second && i->first <= end
if (start < ranges_[i].first)
ranges_[i].first = start;
if (ranges_[i].second < end)
ranges_[i].second = end;
// Now: [start,end) is contained in the i'th range, and we'd be done, except
// for the fact that the newly-extended i'th range might now overlap
// subsequent ranges. Merge until discontinuities appear. Note that there's
// no need to test/merge previous ranges, since needing that would mean the
// original loop went too far.
while ((i + 1) < ranges_.size() &&
ranges_[i + 1].first <= ranges_[i].second) {
ranges_[i].second = max(ranges_[i].second, ranges_[i + 1].second);
ranges_.erase(ranges_.begin() + i + 1);
}
return ranges_.size();
}
template<class T>
size_t Ranges<T>::size() const {
return ranges_.size();
}
template<class T>
T Ranges<T>::start(size_t i) const {
return ranges_[i].first;
}
template<class T>
T Ranges<T>::end(size_t i) const {
return ranges_[i].second;
}
template<class T>
void Ranges<T>::clear() {
ranges_.clear();
}
template<class T>
Ranges<T> Ranges<T>::IntersectionWith(const Ranges<T>& other) const {
Ranges<T> result;
size_t i = 0;
size_t j = 0;
while (i < size() && j < other.size()) {
T max_start = max(start(i), other.start(j));
T min_end = min(end(i), other.end(j));
// Add an intersection range to the result if the ranges overlap.
if (max_start < min_end)
result.Add(max_start, min_end);
if (end(i) < other.end(j))
++i;
else
++j;
}
return result;
}
} // namespace media
#endif // MEDIA_BASE_RANGES_H_
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
```
src
|
|-- Codec # 编码模块
| |-- AACEncoder.cpp # 对libfaac的封装
| |-- AACEncoder.h
| |-- H264Encoder.cpp # 对libx264的封装
| |-- H264Encoder.h
|
|-- Common # 杂项,一般文件
| |-- config.cpp # 主要功能是生成默认配置
| |-- config.h # 定义了一些宏、广播名常量、配置名常量
| |-- MediaSender.h # 一条专门的后台线程用来发送RTP、RTMP包
|
|-- Device # 原本这个文件夹是拿来做各种IPC(海康/大华/汉邦)适配的
| |-- base64.cpp # base64编解码
| |-- base64.h
| |-- Device.cpp # 输入YUV+PCM或H264+AAC生成流媒体源(rtmp/rtsp/hls/mp4)。
| |-- Device.h
| |-- PlayerProxy.cpp # 拉取rtsp/rtmp流生成流媒体源(rtmp/rtsp/hls/mp4)。
| |-- PlayerProxy.h
|
|-- H264 # H264帧处理代码,包括SPS/PPS的解析,POC计算等
| |-- h264_bit_reader.cpp # 移植于chrome
| |-- h264_bit_reader.h # 移植于chrome
| |-- h264_parser.cpp # 移植于chrome
| |-- h264_parser.h # 移植于chrome
| |-- h264_poc.cpp # 移植于chrome
| |-- h264_poc.h # 移植于chrome
| |-- macros.h # 移植于chrome
| |-- ranges.h # 移植于chrome
| |-- H264Parser.cpp # H264的POC、pts计算等
| |-- H264Parser.h
| |-- SPSParser.c # 移植于FFmpeg的sps/pps解析代码
| |-- SPSParser.h
|
|-- Http # Http[s]的服务器和客户端实现
| |-- HttpClient.cpp # Http客户端,可复用
| |-- HttpClient.h
| |-- HttpClientImp.cpp # Https客户端,派生于HttpClient
| |-- HttpClientImp.h
| |-- HttpDownloader.cpp # Http[s]文件下载器,支持断点续传
| |-- HttpDownloader.h
| |-- HttpRequester.cpp # 实现Http[s]API接口客户端,派生于HttpClientImp
| |-- HttpRequester.h
| |-- HttpSession.cpp # Http服务器,支持GET/POST命令。GET只能用于文件下载
| |-- HttpSession.h
| |-- HttpsSession.h # https服务器,派生于HttpSession
| |-- strCoding.cpp # http url转义和反转义
| |-- strCoding.h
|
|-- MediaFile # 媒体文件相关,包括mp4文件的读写,hls文件的生成
| |-- crc32.cpp # crc32计算,用于ts文件生成
| |-- crc32.h
| |-- HLSMaker.cpp # HLS文件生成,包括m3u8和ts文件生成
| |-- HLSMaker.h
| |-- MediaReader.cpp # mp4文件(只支持h264+aac)解析,转换成流媒体
| |-- MediaReader.h
| |-- MediaRecorder.cpp # 录制流媒体为mp4和hls
| |-- MediaRecorder.h
| |-- Mp4Maker.cpp # mp4文件生成,只支持h264+aac
| |-- Mp4Maker.h
| |-- TSMaker.cpp # ts文件生成,只支持h264+aac
| |-- TSMaker.h
|
|-- Player # 播放器
| |-- MediaPlayer.cpp # rtsp/rtmp播放器,只支持h264+acc
| |-- MediaPlayer.h
| |-- Player.cpp # 播放器音视频帧定义以及一些h264/aac处理工具函数
| |-- Player.h
| |-- PlayerBase.cpp
| |-- PlayerBase.h # 播放器基类,定义了一些虚函数
|
|-- Rtmp # rtmp协议支持
| |-- amf.cpp # amf格式的解析及编码
| |-- amf.h
| |-- Rtmp.h # rtmp包定义以及一些rtmp常量宏定义
| |-- RtmpMediaSource.cpp # rtmp流媒体源
| |-- RtmpMediaSource.h
| |-- RtmpParser.cpp # 解析rtmp媒体格式以及提取h264+aac
| |-- RtmpParser.h
| |-- RtmpPlayer.cpp # rtmp播放器
| |-- RtmpPlayer.h
| |-- RtmpPlayerImp.cpp # 派生于RtmpPlayer,结合RtmpParser
| |-- RtmpPlayerImp.h
| |-- RtmpProtocol.cpp # rtmp包序列化以及反序列化
| |-- RtmpProtocol.h
| |-- RtmpPusher.cpp # rtmp推流客户端
| |-- RtmpPusher.h
| |-- RtmpSession.cpp # rtmp服务器,支持播放及推流协议
| |-- RtmpSession.h
| |-- RtmpToRtspMediaSource.cpp # rtmp转rtsp实现
| |-- RtmpToRtspMediaSource.h
| |-- utils.cpp # 网络字节序与整形间的互转
| |-- utils.h
|
|-- RTP # RTP打包
| |-- RtpMaker.h # 打包类基类
| |-- RtpMakerAAC.cpp # aac的rtp打包实现
| |-- RtpMakerAAC.h
| |-- RtpMakerH264.cpp # h264的rtp打包实现
| |-- RtpMakerH264.h
|
|-- Rtsp # rtsp协议支持
| |-- RtpBroadCaster.cpp # rtp组播实现
| |-- RtpBroadCaster.h
| |-- RtpParser.cpp # 完成SDP解析以及rtp组包(提取h264+aac)
| |-- RtpParser.h
| |-- Rtsp.cpp # 定义了rtsp里面一些基本的方法及对象
| |-- Rtsp.h
| |-- RtspMediaSource.cpp # rtsp媒体源
| |-- RtspMediaSource.h
| |-- RtspPlayer.cpp # rtsp播放器实现
| |-- RtspPlayer.h
| |-- RtspPlayerImp.cpp # 派生于RtspPlayer,结合了RtpParser
| |-- RtspPlayerImp.h
| |-- RtspSession.cpp # rtsp服务器协议实现
| |-- RtspSession.h
| |-- RtspToRtmpMediaSource.cpp
| |-- RtspToRtmpMediaSource.h # rtsp转rtmp实现
| |-- UDPServer.cpp
| |-- UDPServer.h # udp端口分配器,用来实现rtp over udp
|
|-- Shell # 远程shell实现,可以实现简单的远程调试
| |-- CMD.cpp # 抽象了一些shell命令,可以简单的添加命令
| |-- CMD.h
| |-- ShellSession.cpp # shell会话类
| |-- ShellSession.h
|
|-- win32 # windows下命令行解析工具(unix下自带)
|-- getopt.c
|-- getopt.h
|-- tailor.h
```
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
* Copyright (c) 2018 huohuo <913481084@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
......@@ -32,7 +32,6 @@
#include "Common/config.h"
#include "RtspPlayer.h"
#include "H264/SPSParser.h"
#include "Util/MD5.h"
#include "Util/mini.h"
#include "Util/util.h"
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......@@ -117,7 +117,7 @@ protected:
* @param pucData
* @param uiLen
*/
void onRecvRtcp(int iTrackidx,SdpTrack::Ptr &track, unsigned char *pucData, unsigned int uiLen);
virtual void onRecvRtcp(int iTrackidx,SdpTrack::Ptr &track, unsigned char *pucData, unsigned int uiLen);
private:
bool handleReq_Options(const Parser &parser); //处理options方法
bool handleReq_Describe(const Parser &parser); //处理describe方法
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
* Copyright (c) 2019 火宣 <459502659@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......@@ -28,7 +28,6 @@
#include <algorithm>
#include "RtspDemuxer.h"
#include "Util/base64.h"
#include "H264/SPSParser.h"
#include "Extension/Factory.h"
using namespace std;
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论