diff --git a/packager/media/base/video_stream_info.cc b/packager/media/base/video_stream_info.cc index a82ef2c7d6..52b287a2e6 100644 --- a/packager/media/base/video_stream_info.cc +++ b/packager/media/base/video_stream_info.cc @@ -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() {} diff --git a/packager/media/formats/mp4/box_definitions.cc b/packager/media/formats/mp4/box_definitions.cc index 2358c36428..2f0e2fb82b 100644 --- a/packager/media/formats/mp4/box_definitions.cc +++ b/packager/media/formats/mp4/box_definitions.cc @@ -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 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; } diff --git a/packager/media/formats/mp4/box_definitions.h b/packager/media/formats/mp4/box_definitions.h index 6f2280fd8e..03566c85bf 100644 --- a/packager/media/formats/mp4/box_definitions.h +++ b/packager/media/formats/mp4/box_definitions.h @@ -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; }; diff --git a/packager/media/formats/mp4/mp4_media_parser_unittest.cc b/packager/media/formats/mp4/mp4_media_parser_unittest.cc index 3bbd0e07fc..8c803fb64b 100644 --- a/packager/media/formats/mp4/mp4_media_parser_unittest.cc +++ b/packager/media/formats/mp4/mp4_media_parser_unittest.cc @@ -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(stream_map_[kVideoTrackId].get()) ->pixel_width()); - EXPECT_EQ(1u, + EXPECT_EQ(9u, reinterpret_cast(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(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(stream_map_[kVideoTrackId].get()) diff --git a/packager/media/formats/mp4/mp4_muxer.cc b/packager/media/formats/mp4/mp4_muxer.cc index f2386e3f13..3b905376c2 100644 --- a/packager/media/formats/mp4/mp4_muxer.cc +++ b/packager/media/formats/mp4/mp4_muxer.cc @@ -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(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; diff --git a/packager/media/test/data/README b/packager/media/test/data/README index ee0d0ab0f9..d91d650cb4 100644 --- a/packager/media/test/data/README +++ b/packager/media/test/data/README @@ -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". diff --git a/packager/media/test/data/bear-640x360-non_square_pixel-with_pasp.mp4 b/packager/media/test/data/bear-640x360-non_square_pixel-with_pasp.mp4 new file mode 100644 index 0000000000..6f13e70d3a Binary files /dev/null and b/packager/media/test/data/bear-640x360-non_square_pixel-with_pasp.mp4 differ diff --git a/packager/media/test/data/bear-640x360-non_square_pixel-without_pasp.mp4 b/packager/media/test/data/bear-640x360-non_square_pixel-without_pasp.mp4 new file mode 100644 index 0000000000..07a058e21a Binary files /dev/null and b/packager/media/test/data/bear-640x360-non_square_pixel-without_pasp.mp4 differ diff --git a/packager/media/test/data/hb2_v_frag.mp4 b/packager/media/test/data/hb2_v_frag.mp4 deleted file mode 100644 index 2b271f71f1..0000000000 Binary files a/packager/media/test/data/hb2_v_frag.mp4 and /dev/null differ diff --git a/packager/packager.gyp b/packager/packager.gyp index 6104bd1037..a3de0609af 100644 --- a/packager/packager.gyp +++ b/packager/packager.gyp @@ -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', ],