Move SAR extraction out of video_stream_info.cc

This fixes a circular dependency of media_base depends on filter and
filter depends on media_base.

Also added code to extract sar in WvmMediaParser if it is not yet
extracted when setting extra_data.

Change-Id: I1b5aef2444e4134c9b6663911ac5e5c4c220404a
This commit is contained in:
Kongqun Yang 2015-08-20 12:06:02 -07:00 committed by KongQun Yang
parent 5a38dc9c12
commit 2a95367dd4
10 changed files with 99 additions and 39 deletions

View File

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

View File

@ -6,13 +6,12 @@
#include "packager/media/base/video_stream_info.h" #include "packager/media/base/video_stream_info.h"
#include "base/logging.h" #include "packager/base/logging.h"
#include "packager/base/stl_util.h" #include "packager/base/stl_util.h"
#include "packager/base/strings/string_number_conversions.h" #include "packager/base/strings/string_number_conversions.h"
#include "packager/base/strings/string_util.h" #include "packager/base/strings/string_util.h"
#include "packager/base/strings/stringprintf.h" #include "packager/base/strings/stringprintf.h"
#include "packager/media/base/limits.h" #include "packager/media/base/limits.h"
#include "packager/media/filters/h264_parser.h"
namespace edash_packager { namespace edash_packager {
namespace media { namespace media {
@ -73,21 +72,6 @@ VideoStreamInfo::VideoStreamInfo(int track_id,
pixel_height_(pixel_height), pixel_height_(pixel_height),
trick_play_rate_(trick_play_rate), trick_play_rate_(trick_play_rate),
nalu_length_size_(nalu_length_size) { 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.";
}
if (pixel_width_ == 0 || pixel_height_ == 0) {
LOG(WARNING) << "SAR is not extracted successfully. Assuming 1:1.";
pixel_width_ = 1;
pixel_height_ = 1;
}
} }
VideoStreamInfo::~VideoStreamInfo() {} VideoStreamInfo::~VideoStreamInfo() {}

View File

@ -67,6 +67,9 @@ class VideoStreamInfo : public StreamInfo {
uint8_t nalu_length_size() const { return nalu_length_size_; } uint8_t nalu_length_size() const { return nalu_length_size_; }
int16_t trick_play_rate() const { return trick_play_rate_; } int16_t trick_play_rate() const { return trick_play_rate_; }
void set_pixel_width(uint32_t pixel_width) { pixel_width_ = pixel_width; }
void set_pixel_height(uint32_t pixel_height) { pixel_height_ = pixel_height; }
/// @param profile,compatible_profiles,level are only used by H.264 codec. /// @param profile,compatible_profiles,level are only used by H.264 codec.
/// @return The codec string. /// @return The codec string.
static std::string GetCodecString(VideoCodec codec, static std::string GetCodecString(VideoCodec codec,

View File

@ -10,7 +10,7 @@
#include <algorithm> #include <algorithm>
#include "base/logging.h" #include "packager/base/logging.h"
namespace edash_packager { namespace edash_packager {

View File

@ -20,9 +20,10 @@ namespace media {
} \ } \
} while (0) } while (0)
void ExtractSarFromDecoderConfig( void ExtractSarFromDecoderConfig(const uint8_t* avc_decoder_config_data,
const uint8_t* avc_decoder_config_data, size_t avc_decoder_config_data_size, size_t avc_decoder_config_data_size,
uint32_t* sar_width, uint32_t* sar_height) { uint32_t* sar_width,
uint32_t* sar_height) {
BufferReader reader(avc_decoder_config_data, avc_decoder_config_data_size); BufferReader reader(avc_decoder_config_data, avc_decoder_config_data_size);
uint8_t value = 0; uint8_t value = 0;
// version check, must be 1. // version check, must be 1.
@ -56,20 +57,28 @@ void ExtractSarFromDecoderConfig(
uint16_t sps_length = 0; uint16_t sps_length = 0;
RCHECK(reader.Read2(&sps_length)); RCHECK(reader.Read2(&sps_length));
ExtractSarFromSps(reader.data() + reader.pos(), sps_length, sar_width,
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).
}
void ExtractSarFromSps(const uint8_t* sps_data,
size_t sps_data_size,
uint32_t* sar_width,
uint32_t* sar_height) {
H264Parser parser; H264Parser parser;
int sps_id; int sps_id;
RCHECK(parser.ParseSPSFromArray(reader.data() + reader.pos(), sps_length, RCHECK(parser.ParseSPSFromArray(sps_data, sps_data_size, &sps_id) ==
&sps_id) == H264Parser::kOk); H264Parser::kOk);
const H264SPS& sps = *parser.GetSPS(sps_id); const H264SPS& sps = *parser.GetSPS(sps_id);
// 0 means it wasn't in the SPS and therefore assume 1. // 0 means it wasn't in the SPS and therefore assume 1.
*sar_width = sps.sar_width == 0 ? 1 : sps.sar_width; *sar_width = sps.sar_width == 0 ? 1 : sps.sar_width;
*sar_height = sps.sar_height == 0 ? 1 : sps.sar_height; *sar_height = sps.sar_height == 0 ? 1 : sps.sar_height;
DVLOG(2) << "Found sar_width: " << *sar_width DVLOG(2) << "Found sar_width: " << *sar_width
<< " sar_height: " << *sar_height; << " 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 #undef RCHECK

View File

@ -23,9 +23,18 @@ namespace media {
// |avc_decoder_config_data|. // |avc_decoder_config_data|.
// If the value is 0 or ommited in |avc_decoder_config_data|, then 1 is // If the value is 0 or ommited in |avc_decoder_config_data|, then 1 is
// assigned. // assigned.
void ExtractSarFromDecoderConfig( void ExtractSarFromDecoderConfig(const uint8_t* avc_decoder_config_data,
const uint8_t* avc_decoder_config_data, size_t avc_decoder_config_data_size, size_t avc_decoder_config_data_size,
uint32_t* sar_width, uint32_t* sar_height); uint32_t* sar_width,
uint32_t* sar_height);
// |sps_data| must be a valid SPS specified in ISO/IEC 14496-10.
// On success, |sar_width| and |sar_height| contain pixel width and height
// respectively.
void ExtractSarFromSps(const uint8_t* sps_data,
size_t sps_data_size,
uint32_t* sar_width,
uint32_t* sar_height);
// For explanations of each struct and its members, see H.264 specification // For explanations of each struct and its members, see H.264 specification
// at http://www.itu.int/rec/T-REC-H.264. // at http://www.itu.int/rec/T-REC-H.264.

View File

@ -6,7 +6,6 @@
#include "packager/base/logging.h" #include "packager/base/logging.h"
#include "packager/base/stl_util.h" #include "packager/base/stl_util.h"
#include "packager/base/strings/string_number_conversions.h"
#include "packager/media/test/test_data_util.h" #include "packager/media/test/test_data_util.h"
#include "packager/media/filters/h264_parser.h" #include "packager/media/filters/h264_parser.h"
@ -66,5 +65,33 @@ TEST(H264ParserTest, StreamFileParsing) {
} }
} }
TEST(H264ParserTest, ExtractSarFromDecoderConfig) {
const uint8_t kDecoderConfig[] = {
0x01, 0x64, 0x00, 0x1E, 0xFF, 0xE1, 0x00, 0x1D, 0x67, 0x64, 0x00, 0x1E,
0xAC, 0xD9, 0x40, 0xB4, 0x2F, 0xF9, 0x7F, 0xF0, 0x00, 0x80, 0x00, 0x91,
0x00, 0x00, 0x03, 0x03, 0xE9, 0x00, 0x00, 0xEA, 0x60, 0x0F, 0x16, 0x2D,
0x96, 0x01, 0x00, 0x06, 0x68, 0xEB, 0xE3, 0xCB, 0x22, 0xC0};
uint32_t pixel_width = 0;
uint32_t pixel_height = 0;
ExtractSarFromDecoderConfig(kDecoderConfig, arraysize(kDecoderConfig),
&pixel_width, &pixel_height);
EXPECT_EQ(8u, pixel_width);
EXPECT_EQ(9u, pixel_height);
}
TEST(H264ParserTest, ExtractSarFromSps) {
const uint8_t kSps[] = {0x67, 0x64, 0x00, 0x1E, 0xAC, 0xD9, 0x40, 0xB4,
0x2F, 0xF9, 0x7F, 0xF0, 0x00, 0x80, 0x00, 0x91,
0x00, 0x00, 0x03, 0x03, 0xE9, 0x00, 0x00, 0xEA,
0x60, 0x0F, 0x16, 0x2D, 0x96};
uint32_t pixel_width = 0;
uint32_t pixel_height = 0;
ExtractSarFromSps(kSps, arraysize(kSps), &pixel_width, &pixel_height);
EXPECT_EQ(8u, pixel_width);
EXPECT_EQ(9u, pixel_height);
}
} // namespace media } // namespace media
} // namespace edash_packager } // namespace edash_packager

View File

@ -20,6 +20,7 @@
#include "packager/media/base/video_stream_info.h" #include "packager/media/base/video_stream_info.h"
#include "packager/media/file/file.h" #include "packager/media/file/file.h"
#include "packager/media/file/file_closer.h" #include "packager/media/file/file_closer.h"
#include "packager/media/filters/h264_parser.h"
#include "packager/media/formats/mp4/box_definitions.h" #include "packager/media/formats/mp4/box_definitions.h"
#include "packager/media/formats/mp4/box_reader.h" #include "packager/media/formats/mp4/box_reader.h"
#include "packager/media/formats/mp4/es_descriptor.h" #include "packager/media/formats/mp4/es_descriptor.h"
@ -368,6 +369,15 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) {
entry.avcc.profile_compatibility, entry.avcc.profile_compatibility,
entry.avcc.avc_level); entry.avcc.avc_level);
uint32_t pixel_width = entry.pixel_aspect.h_spacing;
uint32_t pixel_height = entry.pixel_aspect.v_spacing;
if (pixel_width == 0 || pixel_height == 0) {
if (!entry.avcc.sps_list.empty()) {
const std::vector<uint8_t>& sps = entry.avcc.sps_list[0];
ExtractSarFromSps(&sps[0], sps.size(), &pixel_width, &pixel_height);
}
}
bool is_encrypted = entry.sinf.info.track_encryption.is_encrypted; bool is_encrypted = entry.sinf.info.track_encryption.is_encrypted;
DVLOG(1) << "is_video_track_encrypted_: " << is_encrypted; DVLOG(1) << "is_video_track_encrypted_: " << is_encrypted;
streams.push_back(new VideoStreamInfo(track->header.track_id, streams.push_back(new VideoStreamInfo(track->header.track_id,
@ -378,8 +388,8 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) {
track->media.header.language, track->media.header.language,
entry.width, entry.width,
entry.height, entry.height,
entry.pixel_aspect.h_spacing, pixel_width,
entry.pixel_aspect.v_spacing, pixel_height,
0, // trick_play_rate 0, // trick_play_rate
entry.avcc.length_size, entry.avcc.length_size,
&entry.avcc.data[0], &entry.avcc.data[0],

View File

@ -161,9 +161,15 @@ void MP4Muxer::GenerateVideoTrak(const VideoStreamInfo* video_info,
// width and height specify the track's visual presentation size as // width and height specify the track's visual presentation size as
// fixed-point 16.16 values. // fixed-point 16.16 values.
uint32_t pixel_width = video_info->pixel_width();
uint32_t pixel_height = video_info->pixel_height();
if (pixel_width == 0 || pixel_height == 0) {
LOG(WARNING) << "pixel width/height are not set. Assuming 1:1.";
pixel_width = 1;
pixel_height = 1;
}
const double sample_aspect_ratio = const double sample_aspect_ratio =
static_cast<double>(video_info->pixel_width()) / static_cast<double>(pixel_width) / pixel_height;
video_info->pixel_height();
trak->header.width = video_info->width() * sample_aspect_ratio * 0x10000; trak->header.width = video_info->width() * sample_aspect_ratio * 0x10000;
trak->header.height = video_info->height() * 0x10000; trak->header.height = video_info->height() * 0x10000;
@ -174,9 +180,9 @@ void MP4Muxer::GenerateVideoTrak(const VideoStreamInfo* video_info,
video.width = video_info->width(); video.width = video_info->width();
video.height = video_info->height(); video.height = video_info->height();
video.avcc.data = video_info->extra_data(); video.avcc.data = video_info->extra_data();
if (video_info->pixel_width() != 1 || video_info->pixel_height() != 1) { if (pixel_width != 1 || pixel_height != 1) {
video.pixel_aspect.h_spacing = video_info->pixel_width(); video.pixel_aspect.h_spacing = pixel_width;
video.pixel_aspect.v_spacing = video_info->pixel_height(); video.pixel_aspect.v_spacing = pixel_height;
} }
SampleDescription& sample_description = SampleDescription& sample_description =

View File

@ -15,6 +15,7 @@
#include "packager/media/base/media_sample.h" #include "packager/media/base/media_sample.h"
#include "packager/media/base/status.h" #include "packager/media/base/status.h"
#include "packager/media/base/video_stream_info.h" #include "packager/media/base/video_stream_info.h"
#include "packager/media/filters/h264_parser.h"
#include "packager/media/formats/mp2t/adts_header.h" #include "packager/media/formats/mp2t/adts_header.h"
#define HAS_HEADER_EXTENSION(x) ((x != 0xBC) && (x != 0xBE) && (x != 0xBF) \ #define HAS_HEADER_EXTENSION(x) ((x != 0xBC) && (x != 0xBE) && (x != 0xBF) \
@ -805,6 +806,18 @@ bool WvmMediaParser::Output(bool output_encrypted_sample) {
stream_infos_[i]->set_codec_string(VideoStreamInfo::GetCodecString( stream_infos_[i]->set_codec_string(VideoStreamInfo::GetCodecString(
kCodecH264, decoder_config_record[1], decoder_config_record[2], kCodecH264, decoder_config_record[1], decoder_config_record[2],
decoder_config_record[3])); decoder_config_record[3]));
VideoStreamInfo* video_stream_info =
reinterpret_cast<VideoStreamInfo*>(stream_infos_[i].get());
uint32_t pixel_width = video_stream_info->pixel_width();
uint32_t pixel_height = video_stream_info->pixel_height();
if (pixel_width == 0 || pixel_height == 0) {
ExtractSarFromDecoderConfig(&decoder_config_record[0],
decoder_config_record.size(),
&pixel_width, &pixel_height);
video_stream_info->set_pixel_width(pixel_width);
video_stream_info->set_pixel_height(pixel_height);
}
} }
} }
} }