vpx/webmdec.cc

225 lines
6.9 KiB
C++
Raw Normal View History

/*
* Copyright (c) 2013 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "./webmdec.h"
#include <cstring>
#include <cstdio>
third_party: Roll libwebm snapshot. 32d5ac4 mkvmuxerutil: Fix MSVC build. 6397597 vpxpes_parser: Fix MSVC build. 784b6fe mkvmuxer: Revert changes to IMkvWriter types. 030518e webm_info: Fix implicit conversion warnings. 46d5dee sample_muxer: Fix implicit conversion warnings. 22b0845 webmts: Fix implicit conversion warnings. ef464c2 mkvparser: Fix implicit conversion warnings. 0e9767e Merge "rename mingw64_toolchain.cmake to mingw-w64_toolchain" f47cbd5 cmake: Move cxx flag testing/setup into its own file. 87443a6 rename mingw64_toolchain.cmake to mingw-w64_toolchain 2aee04f msvc_runtime.cmake: Check for MSVC, not WIN32. eb50da8 Option to write timecode using fixed # of bytes c1991fe mkvmuxer: Add missing Segment member initializer. 10aed96 Android.mk: Make libwebm easier to build downstream. 5c50e31 Add support for parsing VPx track codec private data. 4cbdbf1 Fix Android build. bb48a3f mkvmuxerutil: remove stray 'int32' a1cba34 Support cross compile for windows via mingw64. 596f5e0 Add webm_info. ccf75f6 msvc/muxer_tests: Silence integer conversion warnings. 2ff2954 msvc/webm2pes: Silence integer and floating point conversion warnings. 1f24323 msvc/hdr_util: Silence double to float conversion warnings. 0744563 msvc/vpxpes_parser: Silence integer conversion warning. 59614b8 msvc/libwebm_util: Fix floating point to int conversion warning. 6481c24 webvtt: Fix include in vttreader. e6ed0f4 msvc/vpxpes2ts: Fix MSVC integer conversion warning. da64396 cmake/msvc: Disable C4996 project wide. 6ef8264 Merge "mkvparser::BlockEntry: inline EOS()" 3fa6aec mkvparser::BlockEntry: inline EOS() 26306f9 mkvmuxer: Remove unused Cluster ctor overload. 0d76597 mkvmuxer: Fix build with GCC 5.3. 0ba80bc mkvparser/sample: Minor clean up. 2e0e906 iosbuild.sh: Fix build. 918440a Makefile.unix: allow CXXFLAGS to be easily overridden 4ff5785 cmake: Add C++11 move ctor and member initializer tests. 402ef4d cmake: remove argc and argv from C++11 test main fns. cbe5c40 Restore original namespaces for mkvmuxer and mkvparser. 504e0f2 Mass file extension update. 79cb980 Android.mk: Update source file locations. 01db4c2 webmids: Move to common/ sub dir. 235ce59 mkvparser: Explicitly reference internal sources in includes. f578419 mkvmuxer: Move sources to mkvmuxer/ sub dir. 5f1065e webvtt: Organize and clean up webvtt support. 7abe8ac cmake: Add missing dumpvtt target. f2f87e2 Makefile.unix: Tidy things up. 12f6dc3 Use <stdint.h> types instead of custom typedefs. 0407360 mkvmuxer: Write last block in each Cluster with Duration 008aa63 mkvparser: move to mkvparser sub dir. e64bf75 Namespace reorg: Make everything a child of libwebm. 5fdb386 cmake: move c++11 checks into build/cxx11_tests.cmake. 3672488 Copy reference block values in Frame::CopyFrom() 91ca780 reapply clang-format 8d34215 Merge "Clean up AddAudioTrack in muxer_tests" 90861d4 Clean up AddAudioTrack in muxer_tests a9dfb3d Un-ignore webm files in testdata c5b76d8 Extract PES parser from WebM2Pes tests. 16524e8 cmake: Add include-what-you-use integration. 7015af5 iwyu/vpxpes2ts: Update includes. c1d6a70 iwyu/webm2pes: Update includes. 110e797 iwyu/libwebm_util: Update includes. 44e31fb iwyu/webm2pes_tests: Update includes. d919f96 iwyu/mkvwriter: Update includes. 75790e1 iwyu/mkvparser: Update includes. 5f673ca iwyu/webm2pes_main: Update includes. 747244a iwyu/vpxpes2ts_main: Update includes. 94c985f iwyu/mkvmuxerutil: Update includes. c365630 iwyu/mkvmuxer: Update includes. b15b8ef iwyu/file_util: Update includes. 3dfba95 iwyu/hdr_util: Update includes. baba8b1 iwyu/vttdemux: Update includes. 3212ec1 iwyu/webvttparser: Update includes. b6d8d92 iwyu/sample_muxer_metadata: Update includes. a9a1a01 iwyu/sample_muxer: Update includes. e020ffd iwyu/sample: Update includes. 18834bc iwyu/parser_tests: Update includes. 9c00ae3 iwyu/muxer_tests: Update includes. 41a17eb iwyu/test_util: Update includes b6174be muxer_tests: Fix windows brokenness. e092515 file_util: Remove tmpnam() usage in MSVC. b9dc4ac test_util: Don't pass NULL to std::string() in GetTestDataDir(). 1f74651 webmts: Move PES/TS sources to m2ts sub directory. 1b895e9 Rename libwebm_utils to libwebm_util. 2fabcd3 sample_muxer: Replace std::tmpnam() with libwebm::GetTempFileName(). e6a0033 Add file_util. 87f9bea Move hdr_util to common. 1f64aaf cmake: Expand C++11 tests. 6dc81c1 muxer_tests: Die immediately when unable to prep for file writing. 521ce4d webm2pes: Fix type limit warning. 64c4163 vpxpes2ts: Fix sign-compare and type-limits warnings. 741ba68 muxer_tests: Replace std::tmpnam() with GetTempFileName(). 6159e83 Merge "test_util: add missing include for close()" ff81c74 parser_tests: Fix sign compare warnings. 163f57d test_util: add missing include for close() 7c89eb5 Merge "test_util: Remove tmpnam() usage on non-MSVC targets." c4b8686 Merge "webm2pes_tests: Fix sign compare warnings." 9c9f546 Merge "muxer_tests: Fix sign compare warnings." 0fbefef webm2pes: Silence sign compare warnings. 599e4e8 cmake: Silence clang/gcc deprecation warnings. 82f376f test_util: Remove tmpnam() usage on non-MSVC targets. 4d31d6b webm2pes_tests: Fix sign compare warnings. 07ed7e0 muxer_tests: Fix sign compare warnings. ae2fbfe parser_tests: Silence sign compare warning. f488528 libwebm_utils: Silence sign compare warning. 777247b Add C++11 detection to cmake file. 9b89187 Add missing include to libwebm_utils.h. 421874a Merge "mkvmuxer: Fix GCC build." dd6ab35 Set the mastering metadata on the muxers colour 8b61ef5 mkvmuxer: Fix GCC build. 353b050 Add hdr_util. c92e080 mkvmuxer: Use kValueNotPresent in Colour/MasteringMetadata. 2d09128 Colour element: TransferFunction renamed to TransferCharacteristics. f2fc28e Colour element: Matrix renamed to MatrixCoefficients. e0b1135 cmake: Minor CMakeLists.txt refactor. 1e1872b Revert change from auto_ptr to unique_ptr in sample code. d7fc382 Track updates to the proposed Matroska Colour spec. 99981ee sample(mkvparser): Output Colour element when present. 375e416 mkvmuxer: Fix Colour element support. eaeca34 mkvmuxer: Fix bits per channel in the colour element. 1dab7f3 mkvparser: Avoid crash when encountering a Colour element. a1517aa sample_muxer: copy the Colour element. ea9dd94 Merge "webm2pes: Fix tests." 8635c5b Merge "mkvparser: Make omitted values detectable in the Colour element." ae4ae7e mkvparser: Make omitted values detectable in the Colour element. 8c8cba6 webm2pes: Fix tests. a281a22 mkvmuxer: Add support for the Colour element and its children. 41a9147 sample_muxer: clang-format include order fix. 939a64d Signal E_BUFFER_NOT_FULL in EBMLHeader::Parse fb1406e mkvparser: Add support for the Colour element and its children. 22bfdf7 Merge "parser_tests: Add validation of cues." b873000 parser_tests: Add validation of cues. 799891e Update .gitignore to include some new binaries e051c60 Merge "Update muxer test gold files" b81d5f0 Update muxer test gold files 48b1e9a mkvparser: clang format run 93c4690 webm2pes: Add PES packet parsing tests. 65ca38f Merge "test_util: Fix gcc build." 520ca6c Merge "parser_tests: Fix gcc build." 37a38ca test_util: Fix gcc build. ee0ebba parser_tests: Fix gcc build. c32f970 Replace auto_ptr usage with unique_ptr. e569ab0 webm2pes/ts: Fix gcc build. 2e55d6c Merge "add bitcode embedding support for ios" 0cfb2dc add bitcode embedding support for ios bb8cefd webm2ts: Converts WebM VPx video to a MPEG TS. 453bf44 webm2pes: Begin addition of tests. 9299bbb libwebm: Googletest integration. 3bec1ba Merge changes I7bcb5b3e,I8ce733be,I98a928ff,I71910f24 5c83bbe Fix ParseElementHeader to support 0 payload elements be35869 libwebm_utils: Add FileDeleter. d6db1e1 webm2pes: Add a WebM parser init method. aa3593e webm2pes: Rename Convert to ConvertToFile(). e8fca12 webm2pes: Fix super frame splitting. 3cb96b6 webm2pes: Move main() and helper functions into their own files. 021432b webm2pes: Fix the linux build. 82ac5fc Remove RELEASE.TXT. 852e173 webm2pes: Split super frames and packetize large frames. faf85c2 webm2pes: Refactor header/optional header writing. 7c19266 Add Webm2Pes. 01fdee4 mkvmuxer: Disallow AddTrack() after Tracks element is output. 1ad314e mkvparser: EBMLHeader::Parse: remove dead init Change-Id: I542bd5e34586f29d4d15771ec4bd728defe0769e
2016-03-24 21:12:51 +01:00
#include "third_party/libwebm/mkvparser/mkvparser.h"
#include "third_party/libwebm/mkvparser/mkvreader.h"
namespace {
void reset(struct WebmInputContext *const webm_ctx) {
if (webm_ctx->reader != NULL) {
mkvparser::MkvReader *const reader =
reinterpret_cast<mkvparser::MkvReader *>(webm_ctx->reader);
delete reader;
}
if (webm_ctx->segment != NULL) {
mkvparser::Segment *const segment =
reinterpret_cast<mkvparser::Segment *>(webm_ctx->segment);
delete segment;
}
if (webm_ctx->buffer != NULL) {
delete[] webm_ctx->buffer;
}
webm_ctx->reader = NULL;
webm_ctx->segment = NULL;
webm_ctx->buffer = NULL;
webm_ctx->cluster = NULL;
webm_ctx->block_entry = NULL;
webm_ctx->block = NULL;
webm_ctx->block_frame_index = 0;
webm_ctx->video_track_index = 0;
webm_ctx->timestamp_ns = 0;
Try again to merge branch 'frame-parallel' into master branch. In frame parallel decode, libvpx decoder decodes several frames on all cpus in parallel fashion. If not being flushed, it will only return frame when all the cpus are busy. If getting flushed, it will return all the frames in the decoder. Compare with current serial decode mode in which libvpx decoder is idle between decode calls, libvpx decoder is busy between decode calls. Current frame parallel decode will only speed up the decoding for frame parallel encoded videos. For non frame parallel encoded videos, frame parallel decode is slower than serial decode due to lack of loopfilter worker thread. There are still some known issues that need to be addressed. For example: decode frame parallel videos with segmentation enabled is not right sometimes. * frame-parallel: Add error handling for frame parallel decode and unit test for that. Fix a bug in frame parallel decode and add a unit test for that. Add two test vectors to test frame parallel decode. Add key frame seeking to webmdec and webm_video_source. Implement frame parallel decode for VP9. Increase the thread test range to cover 5, 6, 7, 8 threads. Fix a bug in adding frame parallel unit test. Add VP9 frame-parallel unit test. Manually pick "Make the api behavior conform to api spec." from master branch. Move vp9_dec_build_inter_predictors_* to decoder folder. Add segmentation map array for current and last frame segmentation. Include the right header for VP9 worker thread. Move vp9_thread.* to common. ctrl_get_reference does not need user_priv. Seperate the frame buffers from VP9 encoder/decoder structure. Revert "Revert "Revert "Revert 3 patches from Hangyu to get Chrome to build:""" Conflicts: test/codec_factory.h test/decode_test_driver.cc test/decode_test_driver.h test/invalid_file_test.cc test/test-data.sha1 test/test.mk test/test_vectors.cc vp8/vp8_dx_iface.c vp9/common/vp9_alloccommon.c vp9/common/vp9_entropymode.c vp9/common/vp9_loopfilter_thread.c vp9/common/vp9_loopfilter_thread.h vp9/common/vp9_mvref_common.c vp9/common/vp9_onyxc_int.h vp9/common/vp9_reconinter.c vp9/decoder/vp9_decodeframe.c vp9/decoder/vp9_decodeframe.h vp9/decoder/vp9_decodemv.c vp9/decoder/vp9_decoder.c vp9/decoder/vp9_decoder.h vp9/encoder/vp9_encoder.c vp9/encoder/vp9_pickmode.c vp9/encoder/vp9_rdopt.c vp9/vp9_cx_iface.c vp9/vp9_dx_iface.c This reverts commit a18da9760a74d9ce6fb9f875706dc639c95402f5. Change-Id: I361442ffec1586d036ea2e0ee97ce4f077585f02
2015-01-27 21:26:28 +01:00
webm_ctx->is_key_frame = false;
}
void get_first_cluster(struct WebmInputContext *const webm_ctx) {
mkvparser::Segment *const segment =
reinterpret_cast<mkvparser::Segment *>(webm_ctx->segment);
const mkvparser::Cluster *const cluster = segment->GetFirst();
webm_ctx->cluster = cluster;
}
void rewind_and_reset(struct WebmInputContext *const webm_ctx,
struct VpxInputContext *const vpx_ctx) {
rewind(vpx_ctx->file);
reset(webm_ctx);
}
} // namespace
int file_is_webm(struct WebmInputContext *webm_ctx,
struct VpxInputContext *vpx_ctx) {
mkvparser::MkvReader *const reader = new mkvparser::MkvReader(vpx_ctx->file);
webm_ctx->reader = reader;
webm_ctx->reached_eos = 0;
mkvparser::EBMLHeader header;
long long pos = 0;
if (header.Parse(reader, pos) < 0) {
rewind_and_reset(webm_ctx, vpx_ctx);
return 0;
}
mkvparser::Segment *segment;
if (mkvparser::Segment::CreateInstance(reader, pos, segment)) {
rewind_and_reset(webm_ctx, vpx_ctx);
return 0;
}
webm_ctx->segment = segment;
if (segment->Load() < 0) {
rewind_and_reset(webm_ctx, vpx_ctx);
return 0;
}
const mkvparser::Tracks *const tracks = segment->GetTracks();
const mkvparser::VideoTrack *video_track = NULL;
for (unsigned long i = 0; i < tracks->GetTracksCount(); ++i) {
const mkvparser::Track *const track = tracks->GetTrackByIndex(i);
if (track->GetType() == mkvparser::Track::kVideo) {
video_track = static_cast<const mkvparser::VideoTrack *>(track);
webm_ctx->video_track_index = static_cast<int>(track->GetNumber());
break;
}
}
if (video_track == NULL || video_track->GetCodecId() == NULL) {
rewind_and_reset(webm_ctx, vpx_ctx);
return 0;
}
if (!strncmp(video_track->GetCodecId(), "V_VP8", 5)) {
vpx_ctx->fourcc = VP8_FOURCC;
} else if (!strncmp(video_track->GetCodecId(), "V_VP9", 5)) {
vpx_ctx->fourcc = VP9_FOURCC;
} else {
rewind_and_reset(webm_ctx, vpx_ctx);
return 0;
}
vpx_ctx->framerate.denominator = 0;
vpx_ctx->framerate.numerator = 0;
vpx_ctx->width = static_cast<uint32_t>(video_track->GetWidth());
vpx_ctx->height = static_cast<uint32_t>(video_track->GetHeight());
get_first_cluster(webm_ctx);
return 1;
}
int webm_read_frame(struct WebmInputContext *webm_ctx, uint8_t **buffer,
size_t *buffer_size) {
// This check is needed for frame parallel decoding, in which case this
// function could be called even after it has reached end of input stream.
if (webm_ctx->reached_eos) {
return 1;
}
mkvparser::Segment *const segment =
reinterpret_cast<mkvparser::Segment *>(webm_ctx->segment);
const mkvparser::Cluster *cluster =
reinterpret_cast<const mkvparser::Cluster *>(webm_ctx->cluster);
const mkvparser::Block *block =
reinterpret_cast<const mkvparser::Block *>(webm_ctx->block);
const mkvparser::BlockEntry *block_entry =
reinterpret_cast<const mkvparser::BlockEntry *>(webm_ctx->block_entry);
bool block_entry_eos = false;
do {
long status = 0;
bool get_new_block = false;
if (block_entry == NULL && !block_entry_eos) {
status = cluster->GetFirst(block_entry);
get_new_block = true;
} else if (block_entry_eos || block_entry->EOS()) {
cluster = segment->GetNext(cluster);
if (cluster == NULL || cluster->EOS()) {
*buffer_size = 0;
webm_ctx->reached_eos = 1;
return 1;
}
status = cluster->GetFirst(block_entry);
block_entry_eos = false;
get_new_block = true;
} else if (block == NULL ||
webm_ctx->block_frame_index == block->GetFrameCount() ||
block->GetTrackNumber() != webm_ctx->video_track_index) {
status = cluster->GetNext(block_entry, block_entry);
if (block_entry == NULL || block_entry->EOS()) {
block_entry_eos = true;
continue;
}
get_new_block = true;
}
if (status || block_entry == NULL) {
return -1;
}
if (get_new_block) {
block = block_entry->GetBlock();
if (block == NULL) return -1;
webm_ctx->block_frame_index = 0;
}
} while (block_entry_eos ||
block->GetTrackNumber() != webm_ctx->video_track_index);
webm_ctx->cluster = cluster;
webm_ctx->block_entry = block_entry;
webm_ctx->block = block;
const mkvparser::Block::Frame &frame =
block->GetFrame(webm_ctx->block_frame_index);
++webm_ctx->block_frame_index;
if (frame.len > static_cast<long>(*buffer_size)) {
delete[] * buffer;
*buffer = new uint8_t[frame.len];
if (*buffer == NULL) {
return -1;
}
webm_ctx->buffer = *buffer;
}
*buffer_size = frame.len;
webm_ctx->timestamp_ns = block->GetTime(cluster);
Try again to merge branch 'frame-parallel' into master branch. In frame parallel decode, libvpx decoder decodes several frames on all cpus in parallel fashion. If not being flushed, it will only return frame when all the cpus are busy. If getting flushed, it will return all the frames in the decoder. Compare with current serial decode mode in which libvpx decoder is idle between decode calls, libvpx decoder is busy between decode calls. Current frame parallel decode will only speed up the decoding for frame parallel encoded videos. For non frame parallel encoded videos, frame parallel decode is slower than serial decode due to lack of loopfilter worker thread. There are still some known issues that need to be addressed. For example: decode frame parallel videos with segmentation enabled is not right sometimes. * frame-parallel: Add error handling for frame parallel decode and unit test for that. Fix a bug in frame parallel decode and add a unit test for that. Add two test vectors to test frame parallel decode. Add key frame seeking to webmdec and webm_video_source. Implement frame parallel decode for VP9. Increase the thread test range to cover 5, 6, 7, 8 threads. Fix a bug in adding frame parallel unit test. Add VP9 frame-parallel unit test. Manually pick "Make the api behavior conform to api spec." from master branch. Move vp9_dec_build_inter_predictors_* to decoder folder. Add segmentation map array for current and last frame segmentation. Include the right header for VP9 worker thread. Move vp9_thread.* to common. ctrl_get_reference does not need user_priv. Seperate the frame buffers from VP9 encoder/decoder structure. Revert "Revert "Revert "Revert 3 patches from Hangyu to get Chrome to build:""" Conflicts: test/codec_factory.h test/decode_test_driver.cc test/decode_test_driver.h test/invalid_file_test.cc test/test-data.sha1 test/test.mk test/test_vectors.cc vp8/vp8_dx_iface.c vp9/common/vp9_alloccommon.c vp9/common/vp9_entropymode.c vp9/common/vp9_loopfilter_thread.c vp9/common/vp9_loopfilter_thread.h vp9/common/vp9_mvref_common.c vp9/common/vp9_onyxc_int.h vp9/common/vp9_reconinter.c vp9/decoder/vp9_decodeframe.c vp9/decoder/vp9_decodeframe.h vp9/decoder/vp9_decodemv.c vp9/decoder/vp9_decoder.c vp9/decoder/vp9_decoder.h vp9/encoder/vp9_encoder.c vp9/encoder/vp9_pickmode.c vp9/encoder/vp9_rdopt.c vp9/vp9_cx_iface.c vp9/vp9_dx_iface.c This reverts commit a18da9760a74d9ce6fb9f875706dc639c95402f5. Change-Id: I361442ffec1586d036ea2e0ee97ce4f077585f02
2015-01-27 21:26:28 +01:00
webm_ctx->is_key_frame = block->IsKey();
mkvparser::MkvReader *const reader =
reinterpret_cast<mkvparser::MkvReader *>(webm_ctx->reader);
return frame.Read(reader, *buffer) ? -1 : 0;
}
int webm_guess_framerate(struct WebmInputContext *webm_ctx,
struct VpxInputContext *vpx_ctx) {
uint32_t i = 0;
uint8_t *buffer = NULL;
size_t buffer_size = 0;
while (webm_ctx->timestamp_ns < 1000000000 && i < 50) {
if (webm_read_frame(webm_ctx, &buffer, &buffer_size)) {
break;
}
++i;
}
vpx_ctx->framerate.numerator = (i - 1) * 1000000;
vpx_ctx->framerate.denominator =
static_cast<int>(webm_ctx->timestamp_ns / 1000);
delete[] buffer;
get_first_cluster(webm_ctx);
webm_ctx->block = NULL;
webm_ctx->block_entry = NULL;
webm_ctx->block_frame_index = 0;
webm_ctx->timestamp_ns = 0;
webm_ctx->reached_eos = 0;
return 0;
}
void webm_free(struct WebmInputContext *webm_ctx) { reset(webm_ctx); }