Add support for parsing VPx track codec private data.
Currently only the VP9 profile level is supported. http://www.webmproject.org/vp9/profiles/ Change-Id: Iff7238e104621b53fdd51a67d752bd72b2dbbacb
This commit is contained in:
parent
4cbdbf1978
commit
5c50e310e7
@ -111,4 +111,72 @@ bool CopyColour(const mkvparser::Colour& parser_colour,
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Format of VPx private data:
|
||||
//
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | ID Byte | Length | |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
|
||||
// | |
|
||||
// : Bytes 1..Length of Codec Feature :
|
||||
// | |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
//
|
||||
// ID Byte Format
|
||||
// ID byte is an unsigned byte.
|
||||
// 0 1 2 3 4 5 6 7
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
// |X| ID |
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
//
|
||||
// The X bit is reserved.
|
||||
//
|
||||
// Currently only profile level is supported. ID byte must be set to 1, and
|
||||
// length must be 1. Supported values are:
|
||||
//
|
||||
// 10: Level 1
|
||||
// 11: Level 1.1
|
||||
// 20: Level 2
|
||||
// 21: Level 2.1
|
||||
// 30: Level 3
|
||||
// 31: Level 3.1
|
||||
// 40: Level 4
|
||||
// 41: Level 4.1
|
||||
// 50: Level 5
|
||||
// 51: Level 5.1
|
||||
// 52: Level 5.2
|
||||
// 60: Level 6
|
||||
// 61: Level 6.1
|
||||
// 62: Level 6.2
|
||||
//
|
||||
// See the following link for more information:
|
||||
// http://www.webmproject.org/vp9/profiles/
|
||||
int ParseVpxCodecPrivate(const uint8_t* private_data, int32_t length) {
|
||||
const int kVpxCodecPrivateLength = 3;
|
||||
if (!private_data || length != kVpxCodecPrivateLength)
|
||||
return 0;
|
||||
|
||||
const uint8_t id_byte = *private_data;
|
||||
if (id_byte != 1)
|
||||
return 0;
|
||||
|
||||
const int kVpxProfileLength = 1;
|
||||
const uint8_t length_byte = private_data[1];
|
||||
if (length_byte != kVpxProfileLength)
|
||||
return 0;
|
||||
|
||||
const int level = static_cast<int>(private_data[2]);
|
||||
|
||||
const int kNumLevels = 14;
|
||||
const int levels[kNumLevels] = {10, 11, 20, 21, 30, 31, 40,
|
||||
41, 50, 51, 52, 60, 61, 62};
|
||||
|
||||
for (int i = 0; i < kNumLevels; ++i) {
|
||||
if (level == levels[i])
|
||||
return level;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
} // namespace libwebm
|
||||
|
@ -8,6 +8,8 @@
|
||||
#ifndef LIBWEBM_COMMON_HDR_UTIL_H_
|
||||
#define LIBWEBM_COMMON_HDR_UTIL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "mkvmuxer/mkvmuxer.h"
|
||||
@ -41,6 +43,9 @@ bool ColourValuePresent(long long value);
|
||||
bool CopyColour(const mkvparser::Colour& parser_colour,
|
||||
mkvmuxer::Colour* muxer_colour);
|
||||
|
||||
// Returns VP9 profile upon success or 0 upon failure.
|
||||
int ParseVpxCodecPrivate(const uint8_t* private_data, int32_t length);
|
||||
|
||||
} // namespace libwebm
|
||||
|
||||
#endif // LIBWEBM_COMMON_HDR_UTIL_H_
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
|
||||
#include "common/hdr_util.h"
|
||||
#include "mkvparser/mkvparser.h"
|
||||
#include "mkvparser/mkvreader.h"
|
||||
#include "testing/test_util.h"
|
||||
@ -662,6 +663,27 @@ TEST_F(ParserTest, StereoModeParsedCorrectly) {
|
||||
EXPECT_EQ(144, video_track->GetDisplayHeight());
|
||||
}
|
||||
|
||||
TEST_F(ParserTest, Vp9CodecProfileTest) {
|
||||
const int kCodecPrivateLength = 3;
|
||||
|
||||
// Test invalid codec private data; all of these should return 0.
|
||||
const uint8_t bad_codec_private[kCodecPrivateLength] = {0, 0, 0};
|
||||
EXPECT_EQ(0, libwebm::ParseVpxCodecPrivate(NULL, kCodecPrivateLength));
|
||||
EXPECT_EQ(0, libwebm::ParseVpxCodecPrivate(&bad_codec_private[0], 0));
|
||||
EXPECT_EQ(0, libwebm::ParseVpxCodecPrivate(&bad_codec_private[0],
|
||||
kCodecPrivateLength));
|
||||
const uint8_t good_codec_private[kCodecPrivateLength] = {1, 1, 11};
|
||||
|
||||
// Test parse of codec private chunks, but lie about length.
|
||||
EXPECT_EQ(0, libwebm::ParseVpxCodecPrivate(&bad_codec_private[0], 0));
|
||||
EXPECT_EQ(0, libwebm::ParseVpxCodecPrivate(&good_codec_private[0], 0));
|
||||
|
||||
// Test a valid codec private; this should return 11.
|
||||
// ID: 1, Length: 1, Profile: 11
|
||||
EXPECT_EQ(11, libwebm::ParseVpxCodecPrivate(&good_codec_private[0],
|
||||
kCodecPrivateLength));
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
|
15
webm_info.cc
15
webm_info.cc
@ -16,6 +16,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "common/hdr_util.h"
|
||||
#include "common/indent.h"
|
||||
#include "common/webm_constants.h"
|
||||
#include "common/webm_endian.h"
|
||||
@ -364,10 +365,22 @@ bool OutputTracks(const mkvparser::Segment& segment, const Options& options,
|
||||
size_t private_size;
|
||||
const unsigned char* const private_data =
|
||||
track->GetCodecPrivate(private_size);
|
||||
if (private_data)
|
||||
if (private_data) {
|
||||
fprintf(o, "%sPrivateData(size): %d\n", indent->indent_str().c_str(),
|
||||
static_cast<int>(private_size));
|
||||
|
||||
if (track_type == mkvparser::Track::kVideo) {
|
||||
const std::string codec_id = track->GetCodecId();
|
||||
const std::string v_vp9 = "V_VP9";
|
||||
if (codec_id == v_vp9) {
|
||||
const int vp9_profile_level =
|
||||
libwebm::ParseVpxCodecPrivate(private_data, private_size);
|
||||
fprintf(o, "%sVP9 profile level: %d\n", indent->indent_str().c_str(),
|
||||
vp9_profile_level);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const uint64_t default_duration = track->GetDefaultDuration();
|
||||
if (default_duration > 0)
|
||||
fprintf(o, "%sDefaultDuration: %" PRIu64 "\n",
|
||||
|
Loading…
Reference in New Issue
Block a user