diff --git a/packager/media/codecs/h264_parser.cc b/packager/media/codecs/h264_parser.cc index 5d3348ab73..f57361d8a9 100644 --- a/packager/media/codecs/h264_parser.cc +++ b/packager/media/codecs/h264_parser.cc @@ -985,8 +985,8 @@ H264Parser::Result H264Parser::ParseSliceHeader(const Nalu& nalu, shdr->idr_pic_flag = (nalu.type() == 5); shdr->nal_ref_idc = nalu.ref_idc(); - shdr->nalu_data = nalu.data() + nalu.header_size(); - shdr->nalu_size = nalu.payload_size(); + shdr->nalu_data = nalu.data(); + shdr->nalu_size = nalu.header_size() + nalu.payload_size(); READ_UE_OR_RETURN(&shdr->first_mb_in_slice); READ_UE_OR_RETURN(&shdr->slice_type); @@ -1116,9 +1116,7 @@ H264Parser::Result H264Parser::ParseSliceHeader(const Nalu& nalu, return kUnsupportedStream; } - size_t epb = br->NumEmulationPreventionBytesRead(); - shdr->header_bit_size = (shdr->nalu_size - epb) * 8 - br->NumBitsLeft(); - + shdr->header_bit_size = nalu.payload_size() * 8 - br->NumBitsLeft(); return kOk; } diff --git a/packager/media/codecs/h264_parser.h b/packager/media/codecs/h264_parser.h index 66717c62db..eb97f94ba8 100644 --- a/packager/media/codecs/h264_parser.h +++ b/packager/media/codecs/h264_parser.h @@ -165,9 +165,17 @@ struct H264SliceHeader { bool idr_pic_flag; // from NAL header int nal_ref_idc; // from NAL header - const uint8_t* nalu_data; // from NAL header - off_t nalu_size; // from NAL header - off_t header_bit_size; // calculated + // Points to the beginning of the nal unit. + const uint8_t* nalu_data; + + // Size of whole nalu unit. + off_t nalu_size; + + // This is the size of the slice header not including the nalu header byte. + // Sturcture: |NALU Header| Slice Header | Slice Data | + // Size: |<- 8bits ->|<- header_bit_size ->|<- Rest of nalu ->| + // Note that this is not a field in the H.264 spec. + off_t header_bit_size; int first_mb_in_slice; int slice_type; diff --git a/packager/media/codecs/h264_parser_unittest.cc b/packager/media/codecs/h264_parser_unittest.cc index 2a7329ff36..842ad38504 100644 --- a/packager/media/codecs/h264_parser_unittest.cc +++ b/packager/media/codecs/h264_parser_unittest.cc @@ -11,6 +11,22 @@ namespace shaka { namespace media { +namespace { +// SPS, PPS (for first slice), slice header from test-25fps.h264 file. +const uint8_t kSps[] = { + 0x27, 0x4D, 0x40, 0x0D, 0xA9, 0x18, 0x28, 0x3E, 0x60, 0x0D, + 0x41, 0x80, 0x41, 0xAD, 0xB0, 0xAD, 0x7B, 0xDF, 0x01, +}; +const uint8_t kPps[] = { + 0x28, 0xDE, 0x9, 0x88, +}; +// This is the prefix of a video slice that only has the header. +// The actual slice header size is 30 bits (not including the nalu header). +const uint8_t kVideoSliceTrimmed[] = { + 0x25, 0xB8, 0x20, 0x20, 0x63, +}; +} // namespace + TEST(H264ParserTest, StreamFileParsing) { std::vector buffer = ReadTestDataFile("test-25fps.h264"); @@ -65,6 +81,25 @@ TEST(H264ParserTest, StreamFileParsing) { } } +// Verify that SliceHeader::nalu_data points to the beginning of nal unit. +// Also verify that header_bit_size is set correctly. +TEST(H264ParserTest, SliceHeaderSize) { + H264Parser parser; + int unused_id; + Nalu nalu; + ASSERT_TRUE(nalu.Initialize(Nalu::kH264, kSps, arraysize(kSps))); + ASSERT_EQ(H264Parser::kOk, parser.ParseSps(nalu, &unused_id)); + ASSERT_TRUE(nalu.Initialize(Nalu::kH264, kPps, arraysize(kPps))); + ASSERT_EQ(H264Parser::kOk, parser.ParsePps(nalu, &unused_id)); + ASSERT_TRUE(nalu.Initialize(Nalu::kH264, kVideoSliceTrimmed, + arraysize(kVideoSliceTrimmed))); + + H264SliceHeader slice_header; + ASSERT_EQ(H264Parser::kOk, parser.ParseSliceHeader(nalu, &slice_header)); + EXPECT_EQ(nalu.data(), slice_header.nalu_data); + EXPECT_EQ(30u, slice_header.header_bit_size); +} + TEST(H264ParserTest, ExtractResolutionFromSpsData) { const uint8_t kSps[] = {0x67, 0x64, 0x00, 0x1E, 0xAC, 0xD9, 0x40, 0xB4, 0x2F, 0xF9, 0x7F, 0xF0, 0x00, 0x80, 0x00, 0x91, diff --git a/packager/media/codecs/h265_parser.cc b/packager/media/codecs/h265_parser.cc index 3909111ec4..7292c55a24 100644 --- a/packager/media/codecs/h265_parser.cc +++ b/packager/media/codecs/h265_parser.cc @@ -390,10 +390,7 @@ H265Parser::Result H265Parser::ParseSliceHeader(const Nalu& nalu, TRUE_OR_RETURN(br->SkipBits(extension_length * 8)); } - size_t epb = br->NumEmulationPreventionBytesRead(); - slice_header->header_bit_size = - (nalu.payload_size() - epb) * 8 - br->NumBitsLeft(); - + slice_header->header_bit_size = nalu.payload_size() * 8 - br->NumBitsLeft(); return kOk; } diff --git a/packager/media/codecs/h265_parser.h b/packager/media/codecs/h265_parser.h index 5f535b1b4c..0c9b696449 100644 --- a/packager/media/codecs/h265_parser.h +++ b/packager/media/codecs/h265_parser.h @@ -218,6 +218,10 @@ struct H265SliceHeader { // Many of the fields here are required when parsing so the default here may // not be valid. + // This is the size of the slice header not including the nalu header byte. + // Sturcture: |NALU Header | Slice Header | Slice Data | + // Size: |<- 16bits ->|<- header_bit_size ->|<- Rest of nalu ->| + // Note that this is not a field in the H.265 spec. int header_bit_size = 0; bool first_slice_segment_in_pic_flag = false;