Generate tkhd and pasp boxes properly with non-square pixels
- Width/Height in tkhd box should be display resolution instead of coded resolution. - pasp was not generated earlier. - Assuming SAR as 1:1 if it failed to be extracted successfully. - Also update test files for mp4_media_parser_unittest. This fixes Issue #35. Change-Id: Iedbe6a44465aac6723b6ea2de30aed180821eccd
This commit is contained in:
parent
4f60bfc6c3
commit
e5b6096857
|
@ -83,6 +83,11 @@ VideoStreamInfo::VideoStreamInfo(int track_id,
|
|||
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() {}
|
||||
|
|
|
@ -372,9 +372,6 @@ bool TrackHeader::ReadWrite(BoxBuffer* buffer) {
|
|||
// Set default value for volume, if track is audio, 0x100 else 0.
|
||||
if (volume == -1)
|
||||
volume = (width != 0 && height != 0) ? 0 : 0x100;
|
||||
// Convert integer to 16.16 fix point.
|
||||
width <<= 16;
|
||||
height <<= 16;
|
||||
}
|
||||
std::vector<uint8_t> matrix(kUnityMatrix,
|
||||
kUnityMatrix + arraysize(kUnityMatrix));
|
||||
|
@ -386,9 +383,6 @@ bool TrackHeader::ReadWrite(BoxBuffer* buffer) {
|
|||
buffer->ReadWriteVector(&matrix, matrix.size()) &&
|
||||
buffer->ReadWriteUInt32(&width) &&
|
||||
buffer->ReadWriteUInt32(&height));
|
||||
// Convert 16.16 fixed point to integer.
|
||||
width >>= 16;
|
||||
height >>= 16;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1001,8 +995,7 @@ bool VideoSampleEntry::ReadWrite(BoxBuffer* buffer) {
|
|||
buffer->ReadWriteUInt16(&video_depth) &&
|
||||
buffer->ReadWriteInt16(&predefined));
|
||||
|
||||
RCHECK(buffer->PrepareChildren() &&
|
||||
buffer->TryReadWriteChild(&pixel_aspect));
|
||||
RCHECK(buffer->PrepareChildren());
|
||||
|
||||
if (format == FOURCC_ENCV) {
|
||||
if (buffer->Reading()) {
|
||||
|
@ -1021,6 +1014,7 @@ bool VideoSampleEntry::ReadWrite(BoxBuffer* buffer) {
|
|||
(format == FOURCC_ENCV && sinf.format.format == FOURCC_AVC1)) {
|
||||
RCHECK(buffer->ReadWriteChild(&avcc));
|
||||
}
|
||||
RCHECK(buffer->TryReadWriteChild(&pixel_aspect));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -134,6 +134,8 @@ struct TrackHeader : FullBox {
|
|||
int16_t layer;
|
||||
int16_t alternate_group;
|
||||
int16_t volume;
|
||||
// width and height specify the track's visual presentation size as
|
||||
// fixed-point 16.16 values.
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
};
|
||||
|
|
|
@ -114,15 +114,13 @@ TEST_F(MP4MediaParserTest, UnalignedAppend) {
|
|||
// 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));
|
||||
EXPECT_TRUE(ParseMP4File("bear-640x360-non_square_pixel-with_pasp.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,
|
||||
const int kVideoTrackId = 1;
|
||||
EXPECT_EQ(8u,
|
||||
reinterpret_cast<VideoStreamInfo*>(stream_map_[kVideoTrackId].get())
|
||||
->pixel_width());
|
||||
EXPECT_EQ(1u,
|
||||
EXPECT_EQ(9u,
|
||||
reinterpret_cast<VideoStreamInfo*>(stream_map_[kVideoTrackId].get())
|
||||
->pixel_height());
|
||||
}
|
||||
|
@ -132,13 +130,11 @@ TEST_F(MP4MediaParserTest, PixelWidthPixelHeightFromPaspBox) {
|
|||
// 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));
|
||||
// This file doesn't have pasp. The stream should extract pixel width and
|
||||
// height from SPS.
|
||||
EXPECT_TRUE(
|
||||
ParseMP4File("bear-640x360-non_square_pixel-without_pasp.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())
|
||||
|
@ -156,10 +152,8 @@ TEST_F(MP4MediaParserTest,
|
|||
// 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));
|
||||
EXPECT_TRUE(ParseMP4File("bear-640x360-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())
|
||||
|
|
|
@ -159,8 +159,14 @@ void MP4Muxer::GenerateVideoTrak(const VideoStreamInfo* video_info,
|
|||
uint32_t track_id) {
|
||||
InitializeTrak(video_info, trak);
|
||||
|
||||
trak->header.width = video_info->width();
|
||||
trak->header.height = video_info->height();
|
||||
// width and height specify the track's visual presentation size as
|
||||
// fixed-point 16.16 values.
|
||||
const double sample_aspect_ratio =
|
||||
static_cast<double>(video_info->pixel_width()) /
|
||||
video_info->pixel_height();
|
||||
trak->header.width = video_info->width() * sample_aspect_ratio * 0x10000;
|
||||
trak->header.height = video_info->height() * 0x10000;
|
||||
|
||||
trak->media.handler.type = kVideo;
|
||||
|
||||
VideoSampleEntry video;
|
||||
|
@ -168,6 +174,10 @@ 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();
|
||||
}
|
||||
|
||||
SampleDescription& sample_description =
|
||||
trak->media.information.sample_table.description;
|
||||
|
|
|
@ -44,6 +44,10 @@ bear-640x360-v_frag-cenc.mp4 - A fragmented MP4 version of the video track of be
|
|||
[1] 30313233343536373839303132333435
|
||||
[2] ebdd62f16814d27b68ef122afce4ae3c
|
||||
|
||||
// Non square pixels.
|
||||
bear-640x360-non_square_pixel-with_pasp.mp4 - A non-square pixel version of the video track of bear-640x360.mp4 with PixelAspectRatio box.
|
||||
bear-640x360-non_square_pixel-without_pasp.mp4 - A non-square pixel version of the video track of bear-640x360.mp4 without PixelAspectRatio box.
|
||||
|
||||
// Container Tests (additional containers derived from bear.ogv)
|
||||
bear.ac3 -- created using "avconv -i bear.ogv -f ac3 -b 192k bear.ac3".
|
||||
bear.adts -- created using "avconv -i bear.ogv -f adts -strict experimental bear.adts".
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -97,7 +97,7 @@
|
|||
'media/filters/filters.gyp:filters_unittest',
|
||||
'media/formats/mp2t/mp2t.gyp:mp2t_unittest',
|
||||
'media/formats/mp4/mp4.gyp:mp4_unittest',
|
||||
# 'media/formats/wvm/wvm.gyp:wvm_unittest',
|
||||
'media/formats/wvm/wvm.gyp:wvm_unittest',
|
||||
'mpd/mpd.gyp:mpd_unittest',
|
||||
'packager_test',
|
||||
],
|
||||
|
|
Loading…
Reference in New Issue