Add pixel_{width,height} to VideoStreamInfo

- Added logic to container parsers to extract pixel width and height.
- If the container doesn't contain the pixel width and height of the
  stream and the stream is H264, this parses the SPS to get the
  sar_width and sar_height.
- If extracted sar_width and sar_height are 0s then they imply 1s.
- Add hb2_v_frag.mp4 for test media. This does not have a
  'pasp' box and has sar_width = 8 sar_height = 9.

Change-Id: I4a06ce95582547bec19adb7905e7612c5a1f359e
This commit is contained in:
Rintaro Kuroiwa 2015-06-17 15:42:56 -07:00
parent 2cf673055c
commit c3c971ebd9
14 changed files with 395 additions and 150 deletions

View File

@ -78,6 +78,7 @@
'../../base/base.gyp:base',
'../../third_party/curl/curl.gyp:libcurl',
'../../third_party/openssl/openssl.gyp:openssl',
'../filters/filters.gyp:filters',
],
},
{

View File

@ -39,14 +39,12 @@ StreamInfo::~StreamInfo() {}
std::string StreamInfo::ToString() const {
return base::StringPrintf(
"type: %s\n codec_string: %s\n time_scale: %d\n duration: %" PRIu64 " "
"(%.1f seconds)\n language: %s\n is_encrypted: %s\n",
"type: %s\n codec_string: %s\n time_scale: %d\n duration: "
"%" PRIu64 " (%.1f seconds)\n language: %s\n is_encrypted: %s\n",
(stream_type_ == kStreamAudio ? "Audio" : "Video"),
codec_string_.c_str(),
time_scale_,
duration_,
static_cast<double>(duration_) / time_scale_,
language_.c_str(),
time_scale_, duration_,
static_cast<double>(duration_) / time_scale_, language_.c_str(),
is_encrypted_ ? "true" : "false");
}

View File

@ -6,10 +6,13 @@
#include "packager/media/base/video_stream_info.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "packager/base/strings/string_number_conversions.h"
#include "packager/base/strings/string_util.h"
#include "packager/base/strings/stringprintf.h"
#include "packager/media/base/limits.h"
#include "packager/media/filters/h264_parser.h"
namespace edash_packager {
namespace media {
@ -36,6 +39,7 @@ std::string VideoCodecToString(VideoCodec video_codec) {
return "UnknownVideoCodec";
}
}
} // namespace
VideoStreamInfo::VideoStreamInfo(int track_id,
@ -46,6 +50,8 @@ VideoStreamInfo::VideoStreamInfo(int track_id,
const std::string& language,
uint16_t width,
uint16_t height,
uint32_t pixel_width,
uint32_t pixel_height,
int16_t trick_play_rate,
uint8_t nalu_length_size,
const uint8_t* extra_data,
@ -63,8 +69,20 @@ VideoStreamInfo::VideoStreamInfo(int track_id,
codec_(codec),
width_(width),
height_(height),
pixel_width_(pixel_width),
pixel_height_(pixel_height),
trick_play_rate_(trick_play_rate),
nalu_length_size_(nalu_length_size) {
// If H264 and the pixel width and height were not passed in, parse the extra
// data to get the sar width and height.
if ((pixel_width_ == 0 || pixel_height_ == 0) &&
codec == kCodecH264 &&
extra_data && extra_data_size > 0) {
ExtractSarFromDecoderConfig(extra_data, extra_data_size, &pixel_width_,
&pixel_height_);
DVLOG_IF(2, pixel_width_ == 0 || pixel_height_ == 0)
<< "Failed to extract sar_width and sar_height.";
}
}
VideoStreamInfo::~VideoStreamInfo() {}
@ -78,14 +96,13 @@ bool VideoStreamInfo::IsValidConfig() const {
std::string VideoStreamInfo::ToString() const {
return base::StringPrintf(
"%s codec: %s\n width: %d\n height: %d\n trick_play_rate: %d\n"
" nalu_length_size: %d\n",
"%s codec: %s\n width: %d\n height: %d\n pixel_width: %d\n pixel_height: "
"%d\n trick_play_rate: %d\n nalu_length_size: %d\n",
StreamInfo::ToString().c_str(),
VideoCodecToString(codec_).c_str(),
width_,
height_,
trick_play_rate_,
nalu_length_size_);
width_, height_,
pixel_width_, pixel_height_,
trick_play_rate_, nalu_length_size_);
}
std::string VideoStreamInfo::GetCodecString(VideoCodec codec,

View File

@ -28,6 +28,11 @@ enum VideoCodec {
class VideoStreamInfo : public StreamInfo {
public:
/// Construct an initialized video stream info object.
/// If @a codec is @a kCodecH264 and either @pixel_width and @pixel_height is
/// 0 (unknown), then this tries to parse @extra_data to extract the pixel
/// width and height from it.
/// @param pixel_width is the width of the pixel. 0 if unknown.
/// @param pixel_height is the height of the pixels. 0 if unknown.
VideoStreamInfo(int track_id,
uint32_t time_scale,
uint64_t duration,
@ -36,6 +41,8 @@ class VideoStreamInfo : public StreamInfo {
const std::string& language,
uint16_t width,
uint16_t height,
uint32_t pixel_width,
uint32_t pixel_height,
int16_t trick_play_rate,
uint8_t nalu_length_size,
const uint8_t* extra_data,
@ -51,6 +58,12 @@ class VideoStreamInfo : public StreamInfo {
VideoCodec codec() const { return codec_; }
uint16_t width() const { return width_; }
uint16_t height() const { return height_; }
/// Returns the pixel width.
/// @return 0 if unknown.
uint32_t pixel_width() const { return pixel_width_; }
/// Returns the pixel height.
/// @return 0 if unknown.
uint32_t pixel_height() const { return pixel_height_; }
uint8_t nalu_length_size() const { return nalu_length_size_; }
int16_t trick_play_rate() const { return trick_play_rate_; }
@ -67,6 +80,11 @@ class VideoStreamInfo : public StreamInfo {
VideoCodec codec_;
uint16_t width_;
uint16_t height_;
// pixel_width_:pixel_height_ is the sample aspect ratio.
// 0 means unknown.
uint32_t pixel_width_;
uint32_t pixel_height_;
int16_t trick_play_rate_; // Non-zero for trick-play streams.
// Specifies the normalized size of the NAL unit length field. Can be 1, 2 or

View File

@ -63,6 +63,10 @@ scoped_refptr<StreamInfo> CreateVideoStreamInfo(
param.language,
param.width,
param.height,
// TODO(rkuroiwa): Once MedianInfo proto change that
// adds pizel_{width,height} lands, add tests.
0, // No pixel width.
0, // No pixel height.
0, // trick_play_rate
param.nalu_length_size,
vector_as_array(&param.extra_data),

View File

@ -7,10 +7,73 @@
#include "packager/base/logging.h"
#include "packager/base/memory/scoped_ptr.h"
#include "packager/base/stl_util.h"
#include "packager/media/base/buffer_reader.h"
namespace edash_packager {
namespace media {
#define RCHECK(x) \
do { \
if (!(x)) { \
LOG(ERROR) << "Failure while parsing AVCDecoderConfig: " << #x; \
return; \
} \
} while (0)
void ExtractSarFromDecoderConfig(
const uint8_t* avc_decoder_config_data, size_t avc_decoder_config_data_size,
uint32_t* sar_width, uint32_t* sar_height) {
BufferReader reader(avc_decoder_config_data, avc_decoder_config_data_size);
uint8_t value = 0;
// version check, must be 1.
RCHECK(reader.Read1(&value));
RCHECK(value == 1);
// avc profile. No value check.
RCHECK(reader.Read1(&value));
// profile compatibility. No value check.
RCHECK(reader.Read1(&value));
// avc level indication. No value check.
RCHECK(reader.Read1(&value));
// reserved and length sized minus one.
RCHECK(reader.Read1(&value));
// upper 6 bits are reserved and must be 111111.
RCHECK((value & 0xFC) == 0xFC);
// reserved and num sps.
RCHECK(reader.Read1(&value));
// upper 3 bits are reserved for 0b111.
RCHECK((value & 0xE0) == 0xE0);
const uint8_t num_sps = value & 0x1F;
if (num_sps < 1) {
LOG(ERROR) << "No SPS found.";
return;
}
uint16_t sps_length = 0;
RCHECK(reader.Read2(&sps_length));
H264Parser parser;
int sps_id;
RCHECK(parser.ParseSPSFromArray(reader.data() + reader.pos(), sps_length,
&sps_id) == H264Parser::kOk);
const H264SPS& sps = *parser.GetSPS(sps_id);
// 0 means it wasn't in the SPS and therefore assume 1.
*sar_width = sps.sar_width == 0 ? 1 : sps.sar_width;
*sar_height = sps.sar_height == 0 ? 1 : sps.sar_height;
DVLOG(2) << "Found sar_width: " << *sar_width
<< " sar_height: " << *sar_height;
// It is unlikely to have more than one SPS in practice. Also there's
// no way to change the sar_{width,height} dynamically from VideoStreamInfo.
// So skip the rest (if there are any).
}
#undef RCHECK
bool H264SliceHeader::IsPSlice() const {
return (slice_type % 5 == kPSlice);
}
@ -888,6 +951,28 @@ H264Parser::Result H264Parser::ParsePPS(int* pps_id) {
return kOk;
}
H264Parser::Result H264Parser::ParseSPSFromArray(
const uint8_t* sps_data,
size_t sps_data_length,
int* sps_id) {
br_.Initialize(sps_data, sps_data_length);
int data;
READ_BITS_OR_RETURN(1, &data);
// First bit must be 0.
TRUE_OR_RETURN(data == 0);
int nal_ref_idc;
READ_BITS_OR_RETURN(2, &nal_ref_idc);
// From the spec "nal_ref_idc shall not be equal to 0 for sequence parameter
// set".
TRUE_OR_RETURN(nal_ref_idc != 0);
int nal_unit_type;
READ_BITS_OR_RETURN(5, &nal_unit_type);
TRUE_OR_RETURN(nal_unit_type == H264NALU::kSPS);
return ParseSPS(sps_id);
}
H264Parser::Result H264Parser::ParseRefPicListModification(
int num_ref_idx_active_minus1,
H264ModificationOfPicNum* ref_list_mods) {

View File

@ -17,6 +17,16 @@
namespace edash_packager {
namespace media {
// |avc_decoder_config_data| must be AVCDecoderConfigurationRecord specified
// in ISO/IEC 14496-15.
// On success, |sar_width| and |sar_height| are set to the data specified in
// |avc_decoder_config_data|.
// If the value is 0 or ommited in |avc_decoder_config_data|, then 1 is
// assigned.
void ExtractSarFromDecoderConfig(
const uint8_t* avc_decoder_config_data, size_t avc_decoder_config_data_size,
uint32_t* sar_width, uint32_t* sar_height);
// For explanations of each struct and its members, see H.264 specification
// at http://www.itu.int/rec/T-REC-H.264.
struct H264NALU {
@ -314,6 +324,11 @@ class H264Parser {
Result ParseSPS(int* sps_id);
Result ParsePPS(int* pps_id);
// Samme as ParseSPS but instead uses |sps_data|.
Result ParseSPSFromArray(const uint8_t* sps_data,
size_t sps_data_size,
int* sps_id);
// Return a pointer to SPS/PPS with given |sps_id|/|pps_id| or NULL if not
// present.
const H264SPS* GetSPS(int sps_id);

View File

@ -363,6 +363,8 @@ bool EsParserH264::UpdateVideoDecoderConfig(const H264SPS* sps) {
std::string(),
width,
height,
sps->sar_width == 0 ? 1 : sps->sar_width,
sps->sar_height == 0 ? 1 : sps->sar_height,
0,
H264ByteToUnitStreamConverter::kUnitStreamNaluLengthSize,
decoder_config_record.data(),

View File

@ -12,6 +12,7 @@
#include "packager/base/stl_util.h"
#include "packager/media/base/media_sample.h"
#include "packager/media/base/timestamp.h"
#include "packager/media/base/video_stream_info.h"
#include "packager/media/filters/h264_parser.h"
#include "packager/media/formats/mp2t/es_parser_h264.h"
#include "packager/media/test/test_data_util.h"
@ -131,6 +132,8 @@ class EsParserH264Test : public testing::Test {
}
void NewVideoConfig(scoped_refptr<StreamInfo>& config) {
DVLOG(1) << config->ToString();
stream_map_[config->track_id()] = config;
}
size_t sample_count() const { return sample_count_; }
@ -143,6 +146,8 @@ class EsParserH264Test : public testing::Test {
std::vector<Packet> access_units_;
protected:
typedef std::map<int, scoped_refptr<StreamInfo> > StreamMap;
StreamMap stream_map_;
size_t sample_count_;
bool first_frame_is_key_frame_;
};
@ -198,7 +203,6 @@ void EsParserH264Test::ProcessPesPackets(
es_parser.Flush();
}
TEST_F(EsParserH264Test, OneAccessUnitPerPes) {
LoadStream("bear.h264");
@ -280,6 +284,21 @@ TEST_F(EsParserH264Test, NonIFrameStart) {
EXPECT_TRUE(first_frame_is_key_frame());
}
// Verify that the parser can get the the sar width and height.
TEST_F(EsParserH264Test, PixelWidthPixelHeight) {
LoadStream("bear.h264");
std::vector<Packet> pes_packets(access_units_);
ProcessPesPackets(pes_packets);
const int kVideoTrackId = 0;
EXPECT_EQ(1u,
reinterpret_cast<VideoStreamInfo*>(stream_map_[kVideoTrackId].get())
->pixel_width());
EXPECT_EQ(1u,
reinterpret_cast<VideoStreamInfo*>(stream_map_[kVideoTrackId].get())
->pixel_height());
}
} // namespace mp2t
} // namespace media
} // namespace edash_packager

View File

@ -378,6 +378,8 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) {
track->media.header.language,
entry.width,
entry.height,
entry.pixel_aspect.h_spacing,
entry.pixel_aspect.v_spacing,
0, // trick_play_rate
entry.avcc.length_size,
&entry.avcc.data[0],

View File

@ -12,6 +12,7 @@
#include "packager/media/base/key_source.h"
#include "packager/media/base/media_sample.h"
#include "packager/media/base/stream_info.h"
#include "packager/media/base/video_stream_info.h"
#include "packager/media/formats/mp4/mp4_media_parser.h"
#include "packager/media/test/test_data_util.h"
@ -41,6 +42,8 @@ class MP4MediaParserTest : public testing::Test {
}
protected:
typedef std::map<int, scoped_refptr<StreamInfo> > StreamMap;
StreamMap stream_map_;
scoped_ptr<MP4MediaParser> parser_;
size_t num_streams_;
size_t num_samples_;
@ -70,6 +73,7 @@ class MP4MediaParserTest : public testing::Test {
iter != streams.end();
++iter) {
DVLOG(2) << (*iter)->ToString();
stream_map_[(*iter)->track_id()] = *iter;
}
num_streams_ = streams.size();
num_samples_ = 0;
@ -106,6 +110,65 @@ TEST_F(MP4MediaParserTest, UnalignedAppend) {
EXPECT_EQ(201u, num_samples_);
}
// Verify that the pixel width and pixel height are extracted correctly if
// the container has a 'pasp' box.
TEST_F(MP4MediaParserTest, PixelWidthPixelHeightFromPaspBox) {
// This content has a 'pasp' box that has the aspect ratio.
EXPECT_TRUE(ParseMP4File("bear-1280x720.mp4", 512));
// Track ID 2 has the video stream which should have pixel width and height
// both 1.
const int kVideoTrackId = 2;
EXPECT_EQ(1u,
reinterpret_cast<VideoStreamInfo*>(stream_map_[kVideoTrackId].get())
->pixel_width());
EXPECT_EQ(1u,
reinterpret_cast<VideoStreamInfo*>(stream_map_[kVideoTrackId].get())
->pixel_height());
}
// Verify that pixel width and height can be extracted from the
// extra data (AVCDecoderConfigurationRecord) for H264.
// No 'pasp' box.
TEST_F(MP4MediaParserTest,
PixelWidthPixelHeightFromAVCDecoderConfigurationRecord) {
// This file doesn't have pasp. SPS for the video has
// sar_width = sar_height = 0. So the stream info should return 1 for both
// pixel_width and pixel_height.
EXPECT_TRUE(ParseMP4File("hb2_v_frag.mp4", 512));
// Track ID 1 has the video stream which should have pixel width and height
// both 1.
const int kVideoTrackId = 1;
EXPECT_EQ(8u,
reinterpret_cast<VideoStreamInfo*>(stream_map_[kVideoTrackId].get())
->pixel_width());
EXPECT_EQ(9u,
reinterpret_cast<VideoStreamInfo*>(stream_map_[kVideoTrackId].get())
->pixel_height());
}
// Verify that pixel width and height can be extracted from the
// extra data (AVCDecoderConfigurationRecord) for H264.
// If sar_width and sar_height are not set, then they should both be 1.
TEST_F(MP4MediaParserTest,
PixelWidthPixelHeightFromAVCDecoderConfigurationRecordNotSet) {
// This file doesn't have pasp. SPS for the video has
// sar_width = sar_height = 0. So the stream info should return 1 for both
// pixel_width and pixel_height.
EXPECT_TRUE(ParseMP4File("bear-1280x720-av_frag.mp4", 512));
// Track ID 1 has the video stream which should have pixel width and height
// both 1.
const int kVideoTrackId = 1;
EXPECT_EQ(1u,
reinterpret_cast<VideoStreamInfo*>(stream_map_[kVideoTrackId].get())
->pixel_width());
EXPECT_EQ(1u,
reinterpret_cast<VideoStreamInfo*>(stream_map_[kVideoTrackId].get())
->pixel_height());
}
TEST_F(MP4MediaParserTest, BytewiseAppend) {
// Ensure no incremental errors occur when parsing
EXPECT_TRUE(ParseMP4File("bear-1280x720-av_frag.mp4", 1));

View File

@ -569,6 +569,8 @@ bool WvmMediaParser::ParseIndexEntry() {
uint32_t time_scale = kMpeg2ClockRate;
uint16_t video_width = 0;
uint16_t video_height = 0;
uint32_t pixel_width = 0;
uint32_t pixel_height = 0;
uint8_t nalu_length_size = kNaluLengthSize;
uint8_t num_channels = 0;
int audio_pes_stream_id = 0;
@ -584,147 +586,154 @@ bool WvmMediaParser::ParseIndexEntry() {
for (uint8_t idx = 0; idx < num_index_entries; ++idx) {
if (index_metadata_max_size < (2 * sizeof(uint8_t)) + sizeof(uint32_t)) {
return false;
}
uint8_t tag = *read_ptr_index;
++read_ptr_index;
uint8_t type = *read_ptr_index;
++read_ptr_index;
uint32_t length = ntohlFromBuffer(read_ptr_index);
read_ptr_index += sizeof(uint32_t);
index_metadata_max_size -= (2 * sizeof(uint8_t)) + sizeof(uint32_t);
if (index_metadata_max_size < length) {
return false;
}
int value = 0;
Tag tagtype = Unset;
std::vector<uint8_t> binary_data(length);
switch (Type(type)) {
case Type_uint8:
if (length == sizeof(uint8_t)) {
tagtype = GetTag(tag, length, read_ptr_index, &value);
} else {
return false;
}
break;
case Type_int8:
if (length == sizeof(int8_t)) {
tagtype = GetTag(tag, length, read_ptr_index, &value);
} else {
return false;
}
break;
case Type_uint16:
if (length == sizeof(uint16_t)) {
tagtype = GetTag(tag, length, read_ptr_index, &value);
} else {
return false;
}
break;
case Type_int16:
if (length == sizeof(int16_t)) {
tagtype = GetTag(tag, length, read_ptr_index, &value);
} else {
return false;
}
break;
case Type_uint32:
if (length == sizeof(uint32_t)) {
tagtype = GetTag(tag, length, read_ptr_index, &value);
} else {
return false;
}
break;
case Type_int32:
if (length == sizeof(int32_t)) {
tagtype = GetTag(tag, length, read_ptr_index, &value);
} else {
return false;
}
break;
case Type_uint64:
if (length == sizeof(uint64_t)) {
tagtype = GetTag(tag, length, read_ptr_index, &value);
} else {
return false;
}
break;
case Type_int64:
if (length == sizeof(int64_t)) {
tagtype = GetTag(tag, length, read_ptr_index, &value);
} else {
return false;
}
break;
case Type_string:
case Type_BinaryData:
memcpy(&binary_data[0], read_ptr_index, length);
tagtype = Tag(tag);
break;
default:
break;
}
}
uint8_t tag = *read_ptr_index;
++read_ptr_index;
uint8_t type = *read_ptr_index;
++read_ptr_index;
uint32_t length = ntohlFromBuffer(read_ptr_index);
read_ptr_index += sizeof(uint32_t);
index_metadata_max_size -= (2 * sizeof(uint8_t)) + sizeof(uint32_t);
if (index_metadata_max_size < length) {
return false;
}
int64_t value = 0;
Tag tagtype = Unset;
std::vector<uint8_t> binary_data(length);
switch (Type(type)) {
case Type_uint8:
if (length == sizeof(uint8_t)) {
tagtype = GetTag(tag, length, read_ptr_index, &value);
} else {
return false;
}
break;
case Type_int8:
if (length == sizeof(int8_t)) {
tagtype = GetTag(tag, length, read_ptr_index, &value);
} else {
return false;
}
break;
case Type_uint16:
if (length == sizeof(uint16_t)) {
tagtype = GetTag(tag, length, read_ptr_index, &value);
} else {
return false;
}
break;
case Type_int16:
if (length == sizeof(int16_t)) {
tagtype = GetTag(tag, length, read_ptr_index, &value);
} else {
return false;
}
break;
case Type_uint32:
if (length == sizeof(uint32_t)) {
tagtype = GetTag(tag, length, read_ptr_index, &value);
} else {
return false;
}
break;
case Type_int32:
if (length == sizeof(int32_t)) {
tagtype = GetTag(tag, length, read_ptr_index, &value);
} else {
return false;
}
break;
case Type_uint64:
if (length == sizeof(uint64_t)) {
tagtype = GetTag(tag, length, read_ptr_index, &value);
} else {
return false;
}
break;
case Type_int64:
if (length == sizeof(int64_t)) {
tagtype = GetTag(tag, length, read_ptr_index, &value);
} else {
return false;
}
break;
case Type_string:
case Type_BinaryData:
memcpy(&binary_data[0], read_ptr_index, length);
tagtype = Tag(tag);
break;
default:
break;
}
switch (tagtype) {
case TrackDuration:
track_duration = value;
break;
case TrackTrickPlayRate:
trick_play_rate = value;
break;
case VideoStreamId:
video_pes_stream_id = value;
break;
case AudioStreamId:
audio_pes_stream_id = value;
break;
case VideoWidth:
video_width = (uint16_t)value;
break;
case VideoHeight:
video_height = (uint16_t)value;
break;
case AudioNumChannels:
num_channels = (uint8_t)value;
break;
case VideoType:
has_video = true;
break;
case AudioType:
has_audio = true;
break;
default:
break;
}
switch (tagtype) {
case TrackDuration:
track_duration = value;
break;
case TrackTrickPlayRate:
trick_play_rate = value;
break;
case VideoStreamId:
video_pes_stream_id = value;
break;
case AudioStreamId:
audio_pes_stream_id = value;
break;
case VideoWidth:
video_width = (uint16_t)value;
break;
case VideoHeight:
video_height = (uint16_t)value;
break;
case AudioNumChannels:
num_channels = (uint8_t)value;
break;
case VideoType:
has_video = true;
break;
case AudioType:
has_audio = true;
break;
case VideoPixelWidth:
pixel_width = static_cast<uint32_t>(value);
break;
case VideoPixelHeight:
pixel_height = static_cast<uint32_t>(value);
break;
default:
break;
}
read_ptr_index += length;
index_metadata_max_size -= length;
}
// End Index metadata
index_size = read_ptr_index - &index_data_[0];
read_ptr_index += length;
index_metadata_max_size -= length;
}
// End Index metadata
index_size = read_ptr_index - &index_data_[0];
// Extra data for both audio and video streams not set here, but in
// Output().
if (has_video) {
VideoCodec video_codec = kCodecH264;
stream_infos_.push_back(new VideoStreamInfo(
stream_id_count_, time_scale, track_duration, video_codec,
video_codec_string, std::string(), video_width, video_height,
trick_play_rate, nalu_length_size, NULL, 0, true));
program_demux_stream_map_[base::UintToString(index_program_id_) + ":" +
base::UintToString(video_pes_stream_id)] =
stream_id_count_++;
}
if (has_audio) {
AudioCodec audio_codec = kCodecAAC;
stream_infos_.push_back(new AudioStreamInfo(
stream_id_count_, time_scale, track_duration, audio_codec,
audio_codec_string, std::string(), kAacSampleSizeBits, num_channels,
sampling_frequency, NULL, 0, true));
program_demux_stream_map_[base::UintToString(index_program_id_) + ":" +
base::UintToString(audio_pes_stream_id)] =
stream_id_count_++;
}
// Extra data for both audio and video streams not set here, but in
// Output().
if (has_video) {
VideoCodec video_codec = kCodecH264;
stream_infos_.push_back(new VideoStreamInfo(
stream_id_count_, time_scale, track_duration, video_codec,
video_codec_string, std::string(), video_width, video_height,
pixel_width, pixel_height, trick_play_rate, nalu_length_size, NULL, 0,
true));
program_demux_stream_map_[base::UintToString(index_program_id_) + ":" +
base::UintToString(video_pes_stream_id)] =
stream_id_count_++;
}
if (has_audio) {
AudioCodec audio_codec = kCodecAAC;
stream_infos_.push_back(new AudioStreamInfo(
stream_id_count_, time_scale, track_duration, audio_codec,
audio_codec_string, std::string(), kAacSampleSizeBits, num_channels,
sampling_frequency, NULL, 0, true));
program_demux_stream_map_[base::UintToString(index_program_id_) + ":" +
base::UintToString(audio_pes_stream_id)] =
stream_id_count_++;
}
}
index_program_id_++;

View File

@ -163,6 +163,18 @@ TEST_F(WvmMediaParserTest, ParseWvmWithoutKeySource) {
EXPECT_EQ(kExpectedVideoFrameCount, video_frame_count_);
EXPECT_EQ(kExpectedAudioFrameCount, audio_frame_count_);
EXPECT_EQ(kExpectedEncryptedSampleCount, encrypted_sample_count_);
// Also verify that the pixel width and height have the right values.
// Track 0 and 2 are videos and they both have pixel_width = 8 and
// pixel_height = 9.
EXPECT_EQ(8u, reinterpret_cast<VideoStreamInfo*>(stream_map_[0].get())
->pixel_width());
EXPECT_EQ(8u, reinterpret_cast<VideoStreamInfo*>(stream_map_[2].get())
->pixel_width());
EXPECT_EQ(9u, reinterpret_cast<VideoStreamInfo*>(stream_map_[0].get())
->pixel_height());
EXPECT_EQ(9u, reinterpret_cast<VideoStreamInfo*>(stream_map_[2].get())
->pixel_height());
}
TEST_F(WvmMediaParserTest, ParseWvmInitWithoutKeySource) {

Binary file not shown.