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:
parent
5a38dc9c12
commit
2a95367dd4
|
@ -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',
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -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() {}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
|
|
||||||
namespace edash_packager {
|
namespace edash_packager {
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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],
|
||||||
|
|
|
@ -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 =
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue