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',
|
||||
'../../third_party/curl/curl.gyp:libcurl',
|
||||
'../../third_party/openssl/openssl.gyp:openssl',
|
||||
'../filters/filters.gyp:filters',
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
|
@ -6,13 +6,12 @@
|
|||
|
||||
#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/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 {
|
||||
|
@ -73,21 +72,6 @@ VideoStreamInfo::VideoStreamInfo(int track_id,
|
|||
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.";
|
||||
}
|
||||
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() {}
|
||||
|
|
|
@ -67,6 +67,9 @@ class VideoStreamInfo : public StreamInfo {
|
|||
uint8_t nalu_length_size() const { return nalu_length_size_; }
|
||||
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.
|
||||
/// @return The codec string.
|
||||
static std::string GetCodecString(VideoCodec codec,
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "packager/base/logging.h"
|
||||
|
||||
namespace edash_packager {
|
||||
|
||||
|
|
|
@ -20,9 +20,10 @@ namespace media {
|
|||
} \
|
||||
} 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) {
|
||||
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.
|
||||
|
@ -56,20 +57,28 @@ void ExtractSarFromDecoderConfig(
|
|||
uint16_t sps_length = 0;
|
||||
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;
|
||||
int sps_id;
|
||||
RCHECK(parser.ParseSPSFromArray(reader.data() + reader.pos(), sps_length,
|
||||
&sps_id) == H264Parser::kOk);
|
||||
RCHECK(parser.ParseSPSFromArray(sps_data, sps_data_size, &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
|
||||
|
|
|
@ -23,9 +23,18 @@ namespace media {
|
|||
// |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);
|
||||
void ExtractSarFromDecoderConfig(const uint8_t* avc_decoder_config_data,
|
||||
size_t avc_decoder_config_data_size,
|
||||
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
|
||||
// at http://www.itu.int/rec/T-REC-H.264.
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#include "packager/base/logging.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/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 edash_packager
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "packager/media/base/video_stream_info.h"
|
||||
#include "packager/media/file/file.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_reader.h"
|
||||
#include "packager/media/formats/mp4/es_descriptor.h"
|
||||
|
@ -368,6 +369,15 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) {
|
|||
entry.avcc.profile_compatibility,
|
||||
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;
|
||||
DVLOG(1) << "is_video_track_encrypted_: " << is_encrypted;
|
||||
streams.push_back(new VideoStreamInfo(track->header.track_id,
|
||||
|
@ -378,8 +388,8 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) {
|
|||
track->media.header.language,
|
||||
entry.width,
|
||||
entry.height,
|
||||
entry.pixel_aspect.h_spacing,
|
||||
entry.pixel_aspect.v_spacing,
|
||||
pixel_width,
|
||||
pixel_height,
|
||||
0, // trick_play_rate
|
||||
entry.avcc.length_size,
|
||||
&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
|
||||
// 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 =
|
||||
static_cast<double>(video_info->pixel_width()) /
|
||||
video_info->pixel_height();
|
||||
static_cast<double>(pixel_width) / pixel_height;
|
||||
trak->header.width = video_info->width() * sample_aspect_ratio * 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.height = video_info->height();
|
||||
video.avcc.data = video_info->extra_data();
|
||||
if (video_info->pixel_width() != 1 || video_info->pixel_height() != 1) {
|
||||
video.pixel_aspect.h_spacing = video_info->pixel_width();
|
||||
video.pixel_aspect.v_spacing = video_info->pixel_height();
|
||||
if (pixel_width != 1 || pixel_height != 1) {
|
||||
video.pixel_aspect.h_spacing = pixel_width;
|
||||
video.pixel_aspect.v_spacing = pixel_height;
|
||||
}
|
||||
|
||||
SampleDescription& sample_description =
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "packager/media/base/media_sample.h"
|
||||
#include "packager/media/base/status.h"
|
||||
#include "packager/media/base/video_stream_info.h"
|
||||
#include "packager/media/filters/h264_parser.h"
|
||||
#include "packager/media/formats/mp2t/adts_header.h"
|
||||
|
||||
#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(
|
||||
kCodecH264, decoder_config_record[1], decoder_config_record[2],
|
||||
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