Merge "codec2: fix drain flow and EOS work reporting"
diff --git a/C2VDAAdaptor.cpp b/C2VDAAdaptor.cpp
index ecfcbef..3a960d9 100644
--- a/C2VDAAdaptor.cpp
+++ b/C2VDAAdaptor.cpp
@@ -11,6 +11,7 @@
#include <native_pixmap_handle.h>
#include <v4l2_device.h>
#include <v4l2_slice_video_decode_accelerator.h>
+#include <video_pixel_format.h>
#include <videodev2.h>
#include <utils/Log.h>
@@ -80,20 +81,28 @@
void C2VDAAdaptor::importBufferForPicture(int32_t pictureBufferId, HalPixelFormat format,
int dmabufFd,
const std::vector<VideoFramePlane>& planes) {
- // per change ag/3262504, format should be passed to VDA, however it also matters to VDA API
- // change.
- // TODO(johnylin): pass format to VDA after updating VDA codes to latest.
- (void)format;
-
CHECK(mVDA);
CHECK_LT(pictureBufferId, static_cast<int32_t>(mNumOutputBuffers));
+ media::VideoPixelFormat pixelFormat;
+ switch (format) {
+ case HalPixelFormat::YV12:
+ pixelFormat = media::PIXEL_FORMAT_YV12;
+ break;
+ case HalPixelFormat::NV12:
+ pixelFormat = media::PIXEL_FORMAT_NV12;
+ break;
+ default:
+ LOG_ALWAYS_FATAL("Unsupported format: 0x%x", format);
+ return;
+ }
+
media::NativePixmapHandle handle;
handle.fds.emplace_back(base::FileDescriptor(dmabufFd, true));
for (const auto& plane : planes) {
handle.planes.emplace_back(plane.mStride, plane.mOffset, 0, 0);
}
- mVDA->ImportBufferForPicture(pictureBufferId, handle);
+ mVDA->ImportBufferForPicture(pictureBufferId, pixelFormat, handle);
}
void C2VDAAdaptor::reusePictureBuffer(int32_t pictureBufferId) {
diff --git a/vda/accelerated_video_decoder.h b/vda/accelerated_video_decoder.h
index fe1c711..238e34d 100644
--- a/vda/accelerated_video_decoder.h
+++ b/vda/accelerated_video_decoder.h
@@ -1,6 +1,7 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 77118c9
#ifndef ACCELERATED_VIDEO_DECODER_H_
#define ACCELERATED_VIDEO_DECODER_H_
diff --git a/vda/bit_reader.cc b/vda/bit_reader.cc
index 953d144..95e7634 100644
--- a/vda/bit_reader.cc
+++ b/vda/bit_reader.cc
@@ -1,6 +1,7 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 2de6929
#include "bit_reader.h"
@@ -15,7 +16,7 @@
DCHECK_GE(size, 0);
}
-BitReader::~BitReader() {}
+BitReader::~BitReader() = default;
bool BitReader::ReadString(int num_bits, std::string* str) {
DCHECK_EQ(num_bits % 8, 0);
diff --git a/vda/bit_reader.h b/vda/bit_reader.h
index 2b3fad0..dfc2b0b 100644
--- a/vda/bit_reader.h
+++ b/vda/bit_reader.h
@@ -1,6 +1,7 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 43ddd7a
#ifndef BIT_READER_H_
#define BIT_READER_H_
@@ -14,8 +15,7 @@
namespace media {
-class BitReader
- : NON_EXPORTED_BASE(private BitReaderCore::ByteStreamProvider) {
+class BitReader : private BitReaderCore::ByteStreamProvider {
public:
// Initialize the reader to start reading at |data|, |size| being size
// of |data| in bytes.
diff --git a/vda/bit_reader_core.cc b/vda/bit_reader_core.cc
index 220ea03..92b3211 100644
--- a/vda/bit_reader_core.cc
+++ b/vda/bit_reader_core.cc
@@ -1,6 +1,7 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 2de6929
#include "bit_reader_core.h"
@@ -14,11 +15,9 @@
namespace media {
-BitReaderCore::ByteStreamProvider::ByteStreamProvider() {
-}
+BitReaderCore::ByteStreamProvider::ByteStreamProvider() = default;
-BitReaderCore::ByteStreamProvider::~ByteStreamProvider() {
-}
+BitReaderCore::ByteStreamProvider::~ByteStreamProvider() = default;
BitReaderCore::BitReaderCore(ByteStreamProvider* byte_stream_provider)
: byte_stream_provider_(byte_stream_provider),
@@ -29,8 +28,7 @@
reg_next_(0) {
}
-BitReaderCore::~BitReaderCore() {
-}
+BitReaderCore::~BitReaderCore() = default;
bool BitReaderCore::ReadFlag(bool* flag) {
if (nbits_ == 0 && !Refill(1))
diff --git a/vda/bit_reader_core.h b/vda/bit_reader_core.h
index 9e73018..62a21e2 100644
--- a/vda/bit_reader_core.h
+++ b/vda/bit_reader_core.h
@@ -1,6 +1,7 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 1323b9c
#ifndef BIT_READER_CORE_H_
#define BIT_READER_CORE_H_
diff --git a/vda/bitstream_buffer.cc b/vda/bitstream_buffer.cc
index 4f71755..36b8d06 100644
--- a/vda/bitstream_buffer.cc
+++ b/vda/bitstream_buffer.cc
@@ -1,6 +1,7 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 2de6929
#include "bitstream_buffer.h"
@@ -22,6 +23,6 @@
BitstreamBuffer::BitstreamBuffer(const BitstreamBuffer& other) = default;
-BitstreamBuffer::~BitstreamBuffer() {}
+BitstreamBuffer::~BitstreamBuffer() = default;
} // namespace media
diff --git a/vda/bitstream_buffer.h b/vda/bitstream_buffer.h
index 88555a2..3a267a0 100644
--- a/vda/bitstream_buffer.h
+++ b/vda/bitstream_buffer.h
@@ -1,6 +1,7 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 39a7f93
#ifndef MEDIA_BASE_BITSTREAM_BUFFER_H_
#define MEDIA_BASE_BITSTREAM_BUFFER_H_
diff --git a/vda/h264_bit_reader.cc b/vda/h264_bit_reader.cc
index 7c536b3..6713655 100644
--- a/vda/h264_bit_reader.cc
+++ b/vda/h264_bit_reader.cc
@@ -1,6 +1,7 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 2de6929
#include "base/logging.h"
#include "h264_bit_reader.h"
@@ -15,7 +16,7 @@
prev_two_bytes_(0),
emulation_prevention_bytes_(0) {}
-H264BitReader::~H264BitReader() {}
+H264BitReader::~H264BitReader() = default;
bool H264BitReader::Initialize(const uint8_t* data, off_t size) {
DCHECK(data);
diff --git a/vda/h264_bit_reader.h b/vda/h264_bit_reader.h
index 156b524..aa162ce 100644
--- a/vda/h264_bit_reader.h
+++ b/vda/h264_bit_reader.h
@@ -3,6 +3,7 @@
// found in the LICENSE file.
//
// This file contains an implementation of an H264 Annex-B video stream parser.
+// Note: ported from Chromium commit head: 77be7ae
#ifndef H264_BIT_READER_H_
#define H264_BIT_READER_H_
diff --git a/vda/h264_decoder.cc b/vda/h264_decoder.cc
index 3964059..abaaac5 100644
--- a/vda/h264_decoder.cc
+++ b/vda/h264_decoder.cc
@@ -1,6 +1,7 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: c3bd64c
#include <algorithm>
#include <limits>
@@ -16,22 +17,22 @@
namespace media {
-H264Decoder::H264Accelerator::H264Accelerator() {}
+H264Decoder::H264Accelerator::H264Accelerator() = default;
-H264Decoder::H264Accelerator::~H264Accelerator() {}
+H264Decoder::H264Accelerator::~H264Accelerator() = default;
H264Decoder::H264Decoder(H264Accelerator* accelerator)
- : max_frame_num_(0),
+ : state_(kNeedStreamMetadata),
+ max_frame_num_(0),
max_pic_num_(0),
max_long_term_frame_idx_(0),
max_num_reorder_frames_(0),
accelerator_(accelerator) {
DCHECK(accelerator_);
Reset();
- state_ = kNeedStreamMetadata;
}
-H264Decoder::~H264Decoder() {}
+H264Decoder::~H264Decoder() = default;
void H264Decoder::Reset() {
curr_pic_ = nullptr;
@@ -177,6 +178,8 @@
sizeof(curr_pic_->ref_pic_marking));
}
+ curr_pic_->visible_rect = visible_rect_;
+
return true;
}
@@ -1107,10 +1110,24 @@
if (max_dpb_mbs == 0)
return false;
- size_t max_dpb_size = std::min(max_dpb_mbs / (width_mb * height_mb),
- static_cast<int>(H264DPB::kDPBMaxSize));
- if (max_dpb_size == 0) {
- DVLOG(1) << "Invalid DPB Size";
+ // MaxDpbFrames from level limits per spec.
+ size_t max_dpb_frames = std::min(max_dpb_mbs / (width_mb * height_mb),
+ static_cast<int>(H264DPB::kDPBMaxSize));
+ DVLOG(1) << "MaxDpbFrames: " << max_dpb_frames
+ << ", max_num_ref_frames: " << sps->max_num_ref_frames
+ << ", max_dec_frame_buffering: " << sps->max_dec_frame_buffering;
+
+ // Set DPB size to at least the level limit, or what the stream requires.
+ size_t max_dpb_size =
+ std::max(static_cast<int>(max_dpb_frames),
+ std::max(sps->max_num_ref_frames, sps->max_dec_frame_buffering));
+ // Some non-conforming streams specify more frames are needed than the current
+ // level limit. Allow this, but only up to the maximum number of reference
+ // frames allowed per spec.
+ DVLOG_IF(1, max_dpb_size > max_dpb_frames)
+ << "Invalid stream, DPB size > MaxDpbFrames";
+ if (max_dpb_size == 0 || max_dpb_size > H264DPB::kDPBMaxSize) {
+ DVLOG(1) << "Invalid DPB size: " << max_dpb_size;
return false;
}
@@ -1124,6 +1141,12 @@
dpb_.set_max_num_pics(max_dpb_size);
}
+ Rect new_visible_rect = sps->GetVisibleRect().value_or(Rect());
+ if (visible_rect_ != new_visible_rect) {
+ DVLOG(2) << "New visible rect: " << new_visible_rect.ToString();
+ visible_rect_ = new_visible_rect;
+ }
+
if (!UpdateMaxNumReorderFrames(sps))
return false;
DVLOG(1) << "max_num_reorder_frames: " << max_num_reorder_frames_;
@@ -1320,7 +1343,7 @@
if (state_ != kDecoding)
break;
- // else fallthrough
+ // else fallthrough
case H264NALU::kIDRSlice: {
// TODO(posciak): the IDR may require an SPS that we don't have
// available. For now we'd fail if that happens, but ideally we'd like
diff --git a/vda/h264_decoder.h b/vda/h264_decoder.h
index 27a4c10..82ab98f 100644
--- a/vda/h264_decoder.h
+++ b/vda/h264_decoder.h
@@ -1,6 +1,7 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 77be7ae
#ifndef H264_DECODER_H_
#define H264_DECODER_H_
@@ -16,6 +17,7 @@
#include "accelerated_video_decoder.h"
#include "h264_dpb.h"
#include "h264_parser.h"
+#include "rect.h"
#include "size.h"
namespace media {
@@ -266,6 +268,8 @@
// Output picture size.
Size pic_size_;
+ // Output visible cropping rect.
+ Rect visible_rect_;
// PicOrderCount of the previously outputted frame.
int last_output_poc_;
diff --git a/vda/h264_dpb.cc b/vda/h264_dpb.cc
index 0e1b411..af0b5e0 100644
--- a/vda/h264_dpb.cc
+++ b/vda/h264_dpb.cc
@@ -1,6 +1,7 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 2de6929
#include <string.h>
@@ -44,14 +45,14 @@
memset(&ref_pic_marking, 0, sizeof(ref_pic_marking));
}
-H264Picture::~H264Picture() {}
+H264Picture::~H264Picture() = default;
V4L2H264Picture* H264Picture::AsV4L2H264Picture() {
return nullptr;
}
H264DPB::H264DPB() : max_num_pics_(0) {}
-H264DPB::~H264DPB() {}
+H264DPB::~H264DPB() = default;
void H264DPB::Clear() {
pics_.clear();
diff --git a/vda/h264_dpb.h b/vda/h264_dpb.h
index 6be9f21..3da284e 100644
--- a/vda/h264_dpb.h
+++ b/vda/h264_dpb.h
@@ -4,6 +4,7 @@
//
// This file contains an implementation of an H.264 Decoded Picture Buffer
// used in H264 decoders.
+// Note: ported from Chromium commit head: 70340ce
#ifndef H264_DPB_H_
#define H264_DPB_H_
@@ -15,6 +16,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "h264_parser.h"
+#include "rect.h"
namespace media {
@@ -22,7 +24,7 @@
// A picture (a frame or a field) in the H.264 spec sense.
// See spec at http://www.itu.int/rec/T-REC-H.264
-class H264Picture : public base::RefCounted<H264Picture> {
+class H264Picture : public base::RefCountedThreadSafe<H264Picture> {
public:
using Vector = std::vector<scoped_refptr<H264Picture>>;
@@ -82,8 +84,12 @@
// Position in DPB (i.e. index in DPB).
int dpb_position;
+ // The visible size of picture. This could be either parsed from SPS, or set
+ // to Rect(0, 0) for indicating invalid values or not available.
+ Rect visible_rect;
+
protected:
- friend class base::RefCounted<H264Picture>;
+ friend class base::RefCountedThreadSafe<H264Picture>;
virtual ~H264Picture();
private:
diff --git a/vda/h264_parser.cc b/vda/h264_parser.cc
index 0f37924..94b1e10 100644
--- a/vda/h264_parser.cc
+++ b/vda/h264_parser.cc
@@ -1,8 +1,10 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 2de6929
#include "h264_parser.h"
+#include "subsample_entry.h"
#include <limits>
#include <memory>
@@ -64,6 +66,60 @@
map_unit * (pic_height_in_map_units_minus1 + 1));
}
+// Also based on section 7.4.2.1.1.
+base::Optional<Rect> H264SPS::GetVisibleRect() const {
+ base::Optional<Size> coded_size = GetCodedSize();
+ if (!coded_size)
+ return base::nullopt;
+
+ if (!frame_cropping_flag)
+ return Rect(coded_size.value());
+
+ int crop_unit_x;
+ int crop_unit_y;
+ if (chroma_array_type == 0) {
+ crop_unit_x = 1;
+ crop_unit_y = frame_mbs_only_flag ? 1 : 2;
+ } else {
+ // Section 6.2.
+ // |chroma_format_idc| may be:
+ // 1 => 4:2:0
+ // 2 => 4:2:2
+ // 3 => 4:4:4
+ // Everything else has |chroma_array_type| == 0.
+ int sub_width_c = chroma_format_idc > 2 ? 1 : 2;
+ int sub_height_c = chroma_format_idc > 1 ? 1 : 2;
+ crop_unit_x = sub_width_c;
+ crop_unit_y = sub_height_c * (frame_mbs_only_flag ? 1 : 2);
+ }
+
+ // Verify that the values are not too large before multiplying.
+ if (coded_size->width() / crop_unit_x < frame_crop_left_offset ||
+ coded_size->width() / crop_unit_x < frame_crop_right_offset ||
+ coded_size->height() / crop_unit_y < frame_crop_top_offset ||
+ coded_size->height() / crop_unit_y < frame_crop_bottom_offset) {
+ DVLOG(1) << "Frame cropping exceeds coded size.";
+ return base::nullopt;
+ }
+ int crop_left = crop_unit_x * frame_crop_left_offset;
+ int crop_right = crop_unit_x * frame_crop_right_offset;
+ int crop_top = crop_unit_y * frame_crop_top_offset;
+ int crop_bottom = crop_unit_y * frame_crop_bottom_offset;
+
+ // Verify that the values are sane. Note that some decoders also require that
+ // crops are smaller than a macroblock and/or that crops must be adjacent to
+ // at least one corner of the coded frame.
+ if (coded_size->width() - crop_left <= crop_right ||
+ coded_size->height() - crop_top <= crop_bottom) {
+ DVLOG(1) << "Frame cropping excludes entire frame.";
+ return base::nullopt;
+ }
+
+ return Rect(crop_left, crop_top,
+ coded_size->width() - crop_left - crop_right,
+ coded_size->height() - crop_top - crop_bottom);
+}
+
H264PPS::H264PPS() {
memset(this, 0, sizeof(*this));
}
@@ -134,12 +190,10 @@
// ISO 14496 part 10
// VUI parameters: Table E-1 "Meaning of sample aspect ratio indicator"
-static const int kTableSarWidth[] = {
- 0, 1, 12, 10, 16, 40, 24, 20, 32, 80, 18, 15, 64, 160, 4, 3, 2
-};
-static const int kTableSarHeight[] = {
- 0, 1, 11, 11, 11, 33, 11, 11, 11, 33, 11, 11, 33, 99, 3, 2, 1
-};
+static const int kTableSarWidth[] = {0, 1, 12, 10, 16, 40, 24, 20, 32,
+ 80, 18, 15, 64, 160, 4, 3, 2};
+static const int kTableSarHeight[] = {0, 1, 11, 11, 11, 33, 11, 11, 11,
+ 33, 11, 11, 33, 99, 3, 2, 1};
static_assert(arraysize(kTableSarWidth) == arraysize(kTableSarHeight),
"sar tables must have the same size");
@@ -147,8 +201,7 @@
Reset();
}
-H264Parser::~H264Parser() {
-}
+H264Parser::~H264Parser() = default;
void H264Parser::Reset() {
stream_ = NULL;
@@ -217,6 +270,19 @@
off_t bytes_left = data_size;
while (bytes_left >= 3) {
+ // The start code is "\0\0\1", ones are more unusual than zeroes, so let's
+ // search for it first.
+ const uint8_t* tmp =
+ reinterpret_cast<const uint8_t*>(memchr(data + 2, 1, bytes_left - 2));
+ if (!tmp) {
+ data += bytes_left - 2;
+ bytes_left = 2;
+ break;
+ }
+ tmp -= 2;
+ bytes_left -= tmp - data;
+ data = tmp;
+
if (IsStartCode(data)) {
// Found three-byte start code, set pointer at its beginning.
*offset = data_size - bytes_left;
@@ -251,8 +317,7 @@
off_t nalu_start_off = 0;
off_t annexb_start_code_size = 0;
- if (!FindStartCodeInClearRanges(stream_, bytes_left_,
- encrypted_ranges_,
+ if (!FindStartCodeInClearRanges(stream_, bytes_left_, encrypted_ranges_,
&nalu_start_off, &annexb_start_code_size)) {
DVLOG(4) << "Could not find start code, end of stream?";
return false;
@@ -277,10 +342,9 @@
// belong to the current NALU.
off_t next_start_code_size = 0;
off_t nalu_size_without_start_code = 0;
- if (!FindStartCodeInClearRanges(nalu_data, max_nalu_data_size,
- encrypted_ranges_,
- &nalu_size_without_start_code,
- &next_start_code_size)) {
+ if (!FindStartCodeInClearRanges(
+ nalu_data, max_nalu_data_size, encrypted_ranges_,
+ &nalu_size_without_start_code, &next_start_code_size)) {
nalu_size_without_start_code = max_nalu_data_size;
}
*nalu_size = nalu_size_without_start_code + annexb_start_code_size;
@@ -288,6 +352,7 @@
return true;
}
+// static
bool H264Parser::FindStartCodeInClearRanges(
const uint8_t* data,
off_t data_size,
@@ -325,6 +390,30 @@
return true;
}
+// static
+bool H264Parser::ParseNALUs(const uint8_t* stream,
+ size_t stream_size,
+ std::vector<H264NALU>* nalus) {
+ DCHECK(nalus);
+ H264Parser parser;
+ parser.SetStream(stream, stream_size);
+
+ while (true) {
+ H264NALU nalu;
+ const H264Parser::Result result = parser.AdvanceToNextNALU(&nalu);
+ if (result == H264Parser::kOk) {
+ nalus->push_back(nalu);
+ } else if (result == media::H264Parser::kEOStream) {
+ return true;
+ } else {
+ DLOG(ERROR) << "Unexpected H264 parser result";
+ return false;
+ }
+ }
+ NOTREACHED();
+ return false;
+}
+
H264Parser::Result H264Parser::ReadUE(int* val) {
int num_bits = -1;
int bit;
@@ -381,6 +470,8 @@
if (!LocateNALU(&nalu_size_with_start_code, &start_code_size)) {
DVLOG(4) << "Could not find next NALU, bytes left in stream: "
<< bytes_left_;
+ stream_ = nullptr;
+ bytes_left_ = 0;
return kEOStream;
}
@@ -389,8 +480,11 @@
DVLOG(4) << "NALU found: size=" << nalu_size_with_start_code;
// Initialize bit reader at the start of found NALU.
- if (!br_.Initialize(nalu->data, nalu->size))
+ if (!br_.Initialize(nalu->data, nalu->size)) {
+ stream_ = nullptr;
+ bytes_left_ = 0;
return kEOStream;
+ }
// Move parser state to after this NALU, so next time AdvanceToNextNALU
// is called, we will effectively be skipping it;
@@ -417,22 +511,26 @@
// Default scaling lists (per spec).
static const int kDefault4x4Intra[kH264ScalingList4x4Length] = {
- 6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, 32, 37, 37, 42, };
+ 6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, 32, 37, 37, 42,
+};
static const int kDefault4x4Inter[kH264ScalingList4x4Length] = {
- 10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34, };
+ 10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34,
+};
static const int kDefault8x8Intra[kH264ScalingList8x8Length] = {
6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18, 18, 18, 18, 23,
23, 23, 23, 23, 23, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27,
27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31,
- 31, 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42, };
+ 31, 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42,
+};
static const int kDefault8x8Inter[kH264ScalingList8x8Length] = {
9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19, 19, 19, 19, 21,
21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, 24,
24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27,
- 27, 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35, };
+ 27, 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35,
+};
static inline void DefaultScalingList4x4(
int i,
@@ -579,8 +677,7 @@
if (seq_scaling_list_present_flag) {
res = ParseScalingList(arraysize(sps->scaling_list4x4[i]),
- sps->scaling_list4x4[i],
- &use_default);
+ sps->scaling_list4x4[i], &use_default);
if (res != kOk)
return res;
@@ -588,8 +685,8 @@
DefaultScalingList4x4(i, sps->scaling_list4x4);
} else {
- FallbackScalingList4x4(
- i, kDefault4x4Intra, kDefault4x4Inter, sps->scaling_list4x4);
+ FallbackScalingList4x4(i, kDefault4x4Intra, kDefault4x4Inter,
+ sps->scaling_list4x4);
}
}
@@ -599,8 +696,7 @@
if (seq_scaling_list_present_flag) {
res = ParseScalingList(arraysize(sps->scaling_list8x8[i]),
- sps->scaling_list8x8[i],
- &use_default);
+ sps->scaling_list8x8[i], &use_default);
if (res != kOk)
return res;
@@ -608,8 +704,8 @@
DefaultScalingList8x8(i, sps->scaling_list8x8);
} else {
- FallbackScalingList8x8(
- i, kDefault8x8Intra, kDefault8x8Inter, sps->scaling_list8x8);
+ FallbackScalingList8x8(i, kDefault8x8Intra, kDefault8x8Inter,
+ sps->scaling_list8x8);
}
}
@@ -628,8 +724,7 @@
if (pic_scaling_list_present_flag) {
res = ParseScalingList(arraysize(pps->scaling_list4x4[i]),
- pps->scaling_list4x4[i],
- &use_default);
+ pps->scaling_list4x4[i], &use_default);
if (res != kOk)
return res;
@@ -639,14 +734,12 @@
} else {
if (!sps.seq_scaling_matrix_present_flag) {
// Table 7-2 fallback rule A in spec.
- FallbackScalingList4x4(
- i, kDefault4x4Intra, kDefault4x4Inter, pps->scaling_list4x4);
+ FallbackScalingList4x4(i, kDefault4x4Intra, kDefault4x4Inter,
+ pps->scaling_list4x4);
} else {
// Table 7-2 fallback rule B in spec.
- FallbackScalingList4x4(i,
- sps.scaling_list4x4[0],
- sps.scaling_list4x4[3],
- pps->scaling_list4x4);
+ FallbackScalingList4x4(i, sps.scaling_list4x4[0],
+ sps.scaling_list4x4[3], pps->scaling_list4x4);
}
}
}
@@ -657,8 +750,7 @@
if (pic_scaling_list_present_flag) {
res = ParseScalingList(arraysize(pps->scaling_list8x8[i]),
- pps->scaling_list8x8[i],
- &use_default);
+ pps->scaling_list8x8[i], &use_default);
if (res != kOk)
return res;
@@ -668,14 +760,12 @@
} else {
if (!sps.seq_scaling_matrix_present_flag) {
// Table 7-2 fallback rule A in spec.
- FallbackScalingList8x8(
- i, kDefault8x8Intra, kDefault8x8Inter, pps->scaling_list8x8);
+ FallbackScalingList8x8(i, kDefault8x8Intra, kDefault8x8Inter,
+ pps->scaling_list8x8);
} else {
// Table 7-2 fallback rule B in spec.
- FallbackScalingList8x8(i,
- sps.scaling_list8x8[0],
- sps.scaling_list8x8[1],
- pps->scaling_list8x8);
+ FallbackScalingList8x8(i, sps.scaling_list8x8[0],
+ sps.scaling_list8x8[1], pps->scaling_list8x8);
}
}
}
@@ -697,8 +787,8 @@
IN_RANGE_OR_RETURN(cpb_cnt_minus1, 0, 31);
READ_BITS_OR_RETURN(8, &data); // bit_rate_scale, cpb_size_scale
for (int i = 0; i <= cpb_cnt_minus1; ++i) {
- READ_UE_OR_RETURN(&data); // bit_rate_value_minus1[i]
- READ_UE_OR_RETURN(&data); // cpb_size_value_minus1[i]
+ READ_UE_OR_RETURN(&data); // bit_rate_value_minus1[i]
+ READ_UE_OR_RETURN(&data); // cpb_size_value_minus1[i]
READ_BOOL_OR_RETURN(&data); // cbr_flag
}
READ_BITS_OR_RETURN(20, &data); // cpb/dpb delays, etc.
@@ -755,7 +845,7 @@
READ_BITS_OR_RETURN(16, &data); // num_units_in_tick
READ_BITS_OR_RETURN(16, &data); // time_scale
READ_BITS_OR_RETURN(16, &data); // time_scale
- READ_BOOL_OR_RETURN(&data); // fixed_frame_rate_flag
+ READ_BOOL_OR_RETURN(&data); // fixed_frame_rate_flag
}
// Read and ignore NAL HRD parameters, if present.
@@ -769,22 +859,22 @@
if (res != kOk)
return res;
- if (hrd_parameters_present) // One of NAL or VCL params present is enough.
+ if (hrd_parameters_present) // One of NAL or VCL params present is enough.
READ_BOOL_OR_RETURN(&data); // low_delay_hrd_flag
READ_BOOL_OR_RETURN(&data); // pic_struct_present_flag
READ_BOOL_OR_RETURN(&sps->bitstream_restriction_flag);
if (sps->bitstream_restriction_flag) {
READ_BOOL_OR_RETURN(&data); // motion_vectors_over_pic_boundaries_flag
- READ_UE_OR_RETURN(&data); // max_bytes_per_pic_denom
- READ_UE_OR_RETURN(&data); // max_bits_per_mb_denom
- READ_UE_OR_RETURN(&data); // log2_max_mv_length_horizontal
- READ_UE_OR_RETURN(&data); // log2_max_mv_length_vertical
+ READ_UE_OR_RETURN(&data); // max_bytes_per_pic_denom
+ READ_UE_OR_RETURN(&data); // max_bits_per_mb_denom
+ READ_UE_OR_RETURN(&data); // log2_max_mv_length_horizontal
+ READ_UE_OR_RETURN(&data); // log2_max_mv_length_vertical
READ_UE_OR_RETURN(&sps->max_num_reorder_frames);
READ_UE_OR_RETURN(&sps->max_dec_frame_buffering);
TRUE_OR_RETURN(sps->max_dec_frame_buffering >= sps->max_num_ref_frames);
- IN_RANGE_OR_RETURN(
- sps->max_num_reorder_frames, 0, sps->max_dec_frame_buffering);
+ IN_RANGE_OR_RETURN(sps->max_num_reorder_frames, 0,
+ sps->max_dec_frame_buffering);
}
return kOk;
@@ -1072,7 +1162,6 @@
int luma_log2_weight_denom,
int chroma_log2_weight_denom,
H264WeightingFactors* w_facts) {
-
int def_luma_weight = 1 << luma_log2_weight_denom;
int def_chroma_weight = 1 << chroma_log2_weight_denom;
@@ -1120,20 +1209,18 @@
READ_UE_OR_RETURN(&shdr->chroma_log2_weight_denom);
TRUE_OR_RETURN(shdr->chroma_log2_weight_denom < 8);
- Result res = ParseWeightingFactors(shdr->num_ref_idx_l0_active_minus1,
- sps.chroma_array_type,
- shdr->luma_log2_weight_denom,
- shdr->chroma_log2_weight_denom,
- &shdr->pred_weight_table_l0);
+ Result res = ParseWeightingFactors(
+ shdr->num_ref_idx_l0_active_minus1, sps.chroma_array_type,
+ shdr->luma_log2_weight_denom, shdr->chroma_log2_weight_denom,
+ &shdr->pred_weight_table_l0);
if (res != kOk)
return res;
if (shdr->IsBSlice()) {
- res = ParseWeightingFactors(shdr->num_ref_idx_l1_active_minus1,
- sps.chroma_array_type,
- shdr->luma_log2_weight_denom,
- shdr->chroma_log2_weight_denom,
- &shdr->pred_weight_table_l1);
+ res = ParseWeightingFactors(
+ shdr->num_ref_idx_l1_active_minus1, sps.chroma_array_type,
+ shdr->luma_log2_weight_denom, shdr->chroma_log2_weight_denom,
+ &shdr->pred_weight_table_l1);
if (res != kOk)
return res;
}
diff --git a/vda/h264_parser.h b/vda/h264_parser.h
index fdd3f77..a29685a 100644
--- a/vda/h264_parser.h
+++ b/vda/h264_parser.h
@@ -3,6 +3,7 @@
// found in the LICENSE file.
//
// This file contains an implementation of an H264 Annex-B video stream parser.
+// Note: ported from Chromium commit head: 0a918e9
#ifndef H264_PARSER_H_
#define H264_PARSER_H_
@@ -19,6 +20,7 @@
#include "base/optional.h"
#include "h264_bit_reader.h"
#include "ranges.h"
+#include "rect.h"
#include "size.h"
#include "subsample_entry.h"
@@ -142,8 +144,8 @@
int frame_crop_bottom_offset;
bool vui_parameters_present_flag;
- int sar_width; // Set to 0 when not specified.
- int sar_height; // Set to 0 when not specified.
+ int sar_width; // Set to 0 when not specified.
+ int sar_height; // Set to 0 when not specified.
bool bitstream_restriction_flag;
int max_num_reorder_frames;
int max_dec_frame_buffering;
@@ -181,6 +183,7 @@
// base::nullopt if they encounter integer overflow. They do not verify that
// the results are in-spec for the given profile or level.
base::Optional<Size> GetCodedSize() const;
+ base::Optional<Rect> GetVisibleRect() const;
};
struct H264PPS {
@@ -239,10 +242,7 @@
struct H264SliceHeader {
H264SliceHeader();
- enum {
- kRefListSize = 32,
- kRefListModSize = kRefListSize
- };
+ enum { kRefListSize = 32, kRefListModSize = kRefListSize };
enum Type {
kPSlice = 0,
@@ -258,11 +258,11 @@
bool IsSPSlice() const;
bool IsSISlice() const;
- bool idr_pic_flag; // from NAL header
- int nal_ref_idc; // from NAL header
+ 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
+ off_t nalu_size; // from NAL header
+ off_t header_bit_size; // calculated
int first_mb_in_slice;
int slice_type;
@@ -377,6 +377,12 @@
off_t* offset,
off_t* start_code_size);
+ // Parses the input stream and returns all the NALUs through |nalus|. Returns
+ // false if the stream is invalid.
+ static bool ParseNALUs(const uint8_t* stream,
+ size_t stream_size,
+ std::vector<H264NALU>* nalus);
+
H264Parser();
~H264Parser();
diff --git a/vda/native_pixmap_handle.cc b/vda/native_pixmap_handle.cc
index fa994f9..050a683 100644
--- a/vda/native_pixmap_handle.cc
+++ b/vda/native_pixmap_handle.cc
@@ -1,6 +1,7 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: a9d98e6
#include "native_pixmap_handle.h"
diff --git a/vda/native_pixmap_handle.h b/vda/native_pixmap_handle.h
index 9a284e4..62e2294 100644
--- a/vda/native_pixmap_handle.h
+++ b/vda/native_pixmap_handle.h
@@ -1,6 +1,7 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: a9d98e6
#ifndef NATIVE_PIXMAP_HANDLE_H_
#define NATIVE_PIXMAP_HANDLE_H_
@@ -14,8 +15,16 @@
// NativePixmapPlane is used to carry the plane related information for GBM
// buffer. More fields can be added if they are plane specific.
struct NativePixmapPlane {
+ // This is the same value as DRM_FORMAT_MOD_INVALID, which is not a valid
+ // modifier. We use this to indicate that layout information
+ // (tiling/compression) if any will be communicated out of band.
+ static constexpr uint64_t kNoModifier = 0x00ffffffffffffffULL;
+
NativePixmapPlane();
- NativePixmapPlane(int stride, int offset, uint64_t size, uint64_t modifier);
+ NativePixmapPlane(int stride,
+ int offset,
+ uint64_t size,
+ uint64_t modifier = kNoModifier);
NativePixmapPlane(const NativePixmapPlane& other);
~NativePixmapPlane();
diff --git a/vda/picture.cc b/vda/picture.cc
index a086725..8933bc5 100644
--- a/vda/picture.cc
+++ b/vda/picture.cc
@@ -1,6 +1,7 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 2de6929
#include "picture.h"
@@ -18,7 +19,7 @@
PictureBuffer::PictureBuffer(const PictureBuffer& other) = default;
-PictureBuffer::~PictureBuffer() {}
+PictureBuffer::~PictureBuffer() = default;
Picture::Picture(int32_t picture_buffer_id,
int32_t bitstream_buffer_id,
diff --git a/vda/picture.h b/vda/picture.h
index 3dbf0e9..e07b677 100644
--- a/vda/picture.h
+++ b/vda/picture.h
@@ -1,6 +1,7 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: d264e47
#ifndef PICTURE_H_
#define PICTURE_H_
diff --git a/vda/ranges.cc b/vda/ranges.cc
index 00400b5..4394011 100644
--- a/vda/ranges.cc
+++ b/vda/ranges.cc
@@ -1,6 +1,7 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: a4f94d3
#include "ranges.h"
diff --git a/vda/ranges.h b/vda/ranges.h
index 98b32ce..6a76ae4 100644
--- a/vda/ranges.h
+++ b/vda/ranges.h
@@ -1,6 +1,7 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 1323b9c
#ifndef RANGES_H_
#define RANGES_H_
diff --git a/vda/rect.h b/vda/rect.h
index d9640b2..b23e19d 100644
--- a/vda/rect.h
+++ b/vda/rect.h
@@ -1,6 +1,8 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 0e161fe
+// Note: only necessary functions are ported from gfx::Rect
// Defines a simple integer rectangle class. The containment semantics
// are array-like; that is, the coordinate (x, y) is considered to be
diff --git a/vda/shared_memory_region.cc b/vda/shared_memory_region.cc
index ed56559..775a5f2 100644
--- a/vda/shared_memory_region.cc
+++ b/vda/shared_memory_region.cc
@@ -1,6 +1,7 @@
// Copyright (c) 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 60f9667
#include "base/sys_info.h"
#include "shared_memory_region.h"
diff --git a/vda/shared_memory_region.h b/vda/shared_memory_region.h
index ce9a322..3c5d4b3 100644
--- a/vda/shared_memory_region.h
+++ b/vda/shared_memory_region.h
@@ -1,6 +1,7 @@
// Copyright (c) 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 60f9667
#ifndef SHARED_MEMORY_REGION_H_
#define SHARED_MEMORY_REGION_H_
diff --git a/vda/size.h b/vda/size.h
index 4806ddc..c3e8c82 100644
--- a/vda/size.h
+++ b/vda/size.h
@@ -1,6 +1,8 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: a8e9f71
+// Note: only necessary functions are ported from gfx::Size
#ifndef SIZE_H_
#define SIZE_H_
diff --git a/vda/subsample_entry.h b/vda/subsample_entry.h
index e7529fb..1e0bfad 100644
--- a/vda/subsample_entry.h
+++ b/vda/subsample_entry.h
@@ -1,6 +1,7 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 7014d6d
#ifndef SUBSAMPLE_ENTRY_H_
#define SUBSAMPLE_ENTRY_H_
diff --git a/vda/v4l2_device.cc b/vda/v4l2_device.cc
index 16446d3..78ef474 100644
--- a/vda/v4l2_device.cc
+++ b/vda/v4l2_device.cc
@@ -1,6 +1,8 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 09ea0d2
+// Note: it's also merged with generic_v4l2_device.cc (head: a9d98e6)
#include <errno.h>
#include <fcntl.h>
@@ -15,6 +17,10 @@
#include "base/strings/stringprintf.h"
#include "v4l2_device.h"
+#define DVLOGF(level) DVLOG(level) << __func__ << "(): "
+#define VLOGF(level) VLOG(level) << __func__ << "(): "
+#define VPLOGF(level) VPLOG(level) << __func__ << "(): "
+
namespace media {
V4L2Device::V4L2Device() {}
@@ -47,7 +53,7 @@
return PIXEL_FORMAT_ARGB;
default:
- DVLOG(1) << "Add more cases as needed";
+ DVLOGF(1) << "Add more cases as needed";
return PIXEL_FORMAT_UNKNOWN;
}
}
@@ -131,7 +137,7 @@
break;
default:
- DVLOG(1) << "Unhandled pixelformat " << std::hex << "0x" << pix_fmt;
+ VLOGF(1) << "Unhandled pixelformat " << std::hex << "0x" << pix_fmt;
return profiles;
}
@@ -156,7 +162,7 @@
nfds = 1;
if (poll_device) {
- DVLOG(3) << "Poll(): adding device fd to poll() set";
+ DVLOGF(5) << "Poll(): adding device fd to poll() set";
pollfds[nfds].fd = device_fd_.get();
pollfds[nfds].events = POLLIN | POLLOUT | POLLERR | POLLPRI;
pollfd = nfds;
@@ -164,7 +170,7 @@
}
if (HANDLE_EINTR(poll(pollfds, nfds, -1)) == -1) {
- DPLOG(ERROR) << "poll() failed";
+ VPLOGF(1) << "poll() failed";
return false;
}
*event_pending = (pollfd != -1 && pollfds[pollfd].revents & POLLPRI);
@@ -185,19 +191,19 @@
}
bool V4L2Device::SetDevicePollInterrupt() {
- DVLOG(3) << "SetDevicePollInterrupt()";
+ DVLOGF(4);
const uint64_t buf = 1;
if (HANDLE_EINTR(write(device_poll_interrupt_fd_.get(), &buf, sizeof(buf))) ==
-1) {
- DPLOG(ERROR) << "SetDevicePollInterrupt(): write() failed";
+ VPLOGF(1) << "write() failed";
return false;
}
return true;
}
bool V4L2Device::ClearDevicePollInterrupt() {
- DVLOG(3) << "ClearDevicePollInterrupt()";
+ DVLOGF(5);
uint64_t buf;
if (HANDLE_EINTR(read(device_poll_interrupt_fd_.get(), &buf, sizeof(buf))) ==
@@ -206,7 +212,7 @@
// No interrupt flag set, and we're reading nonblocking. Not an error.
return true;
} else {
- DPLOG(ERROR) << "ClearDevicePollInterrupt(): read() failed";
+ VPLOGF(1) << "read() failed";
return false;
}
}
@@ -214,22 +220,23 @@
}
bool V4L2Device::Open(Type type, uint32_t v4l2_pixfmt) {
+ VLOGF(2);
std::string path = GetDevicePathFor(type, v4l2_pixfmt);
if (path.empty()) {
- DVLOG(1) << "No devices supporting " << std::hex << "0x" << v4l2_pixfmt
+ VLOGF(1) << "No devices supporting " << std::hex << "0x" << v4l2_pixfmt
<< " for type: " << static_cast<int>(type);
return false;
}
if (!OpenDevicePath(path, type)) {
- LOG(ERROR) << "Failed opening " << path;
+ VLOGF(1) << "Failed opening " << path;
return false;
}
device_poll_interrupt_fd_.reset(eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC));
if (!device_poll_interrupt_fd_.is_valid()) {
- LOG(ERROR) << "Failed creating a poll interrupt fd";
+ VLOGF(1) << "Failed creating a poll interrupt fd";
return false;
}
@@ -240,6 +247,7 @@
int index,
size_t num_planes,
enum v4l2_buf_type buf_type) {
+ VLOGF(2);
DCHECK(V4L2_TYPE_IS_MULTIPLANAR(buf_type));
std::vector<base::ScopedFD> dmabuf_fds;
@@ -270,7 +278,7 @@
const auto& devices = GetDevicesForType(type);
for (const auto& device : devices) {
if (!OpenDevicePath(device.first, type)) {
- LOG(ERROR) << "Failed opening " << device.first;
+ VLOGF(1) << "Failed opening " << device.first;
continue;
}
@@ -320,15 +328,15 @@
}
if (max_resolution->IsEmpty()) {
max_resolution->SetSize(1920, 1088);
- LOG(ERROR) << "GetSupportedResolution failed to get maximum resolution for "
- << "fourcc " << std::hex << pixelformat
- << ", fall back to " << max_resolution->ToString();
+ VLOGF(1) << "GetSupportedResolution failed to get maximum resolution for "
+ << "fourcc " << std::hex << pixelformat
+ << ", fall back to " << max_resolution->ToString();
}
if (min_resolution->IsEmpty()) {
min_resolution->SetSize(16, 16);
- LOG(ERROR) << "GetSupportedResolution failed to get minimum resolution for "
- << "fourcc " << std::hex << pixelformat
- << ", fall back to " << min_resolution->ToString();
+ VLOGF(1) << "GetSupportedResolution failed to get minimum resolution for "
+ << "fourcc " << std::hex << pixelformat
+ << ", fall back to " << min_resolution->ToString();
}
}
@@ -341,8 +349,8 @@
fmtdesc.type = buf_type;
for (; Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0; ++fmtdesc.index) {
- DVLOG(1) << "Found " << fmtdesc.description << std::hex << " (0x"
- << fmtdesc.pixelformat << ")";
+ DVLOGF(3) << "Found " << fmtdesc.description << std::hex << " (0x"
+ << fmtdesc.pixelformat << ")";
pixelformats.push_back(fmtdesc.pixelformat);
}
@@ -373,9 +381,9 @@
profile.profile = video_codec_profile;
profiles.push_back(profile);
- DVLOG(1) << "Found decoder profile " << GetProfileName(profile.profile)
- << ", resolutions: " << profile.min_resolution.ToString() << " "
- << profile.max_resolution.ToString();
+ DVLOGF(3) << "Found decoder profile " << GetProfileName(profile.profile)
+ << ", resolutions: " << profile.min_resolution.ToString() << " "
+ << profile.max_resolution.ToString();
}
}
@@ -394,6 +402,7 @@
}
void V4L2Device::CloseDevice() {
+ VLOGF(2);
device_fd_.reset();
}
@@ -433,7 +442,7 @@
const auto& supported_pixelformats =
EnumerateSupportedPixelformats(buf_type);
if (!supported_pixelformats.empty()) {
- DVLOG(1) << "Found device: " << path;
+ DVLOGF(3) << "Found device: " << path;
devices.push_back(std::make_pair(path, supported_pixelformats));
}
diff --git a/vda/v4l2_device.h b/vda/v4l2_device.h
index 41dd616..f64cbf7 100644
--- a/vda/v4l2_device.h
+++ b/vda/v4l2_device.h
@@ -5,6 +5,8 @@
// This file defines the V4L2Device interface which is used by the
// V4L2DecodeAccelerator class to delegate/pass the device specific
// handling of any of the functionalities.
+// Note: ported from Chromium commit head: fb70f64
+// Note: it's also merged with generic_v4l2_device.h (head: fb70f64)
#ifndef V4L2_DEVICE_H_
#define V4L2_DEVICE_H_
diff --git a/vda/v4l2_slice_video_decode_accelerator.cc b/vda/v4l2_slice_video_decode_accelerator.cc
index fcbf614..5da373a 100644
--- a/vda/v4l2_slice_video_decode_accelerator.cc
+++ b/vda/v4l2_slice_video_decode_accelerator.cc
@@ -1,6 +1,7 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 85fdf90
#include "v4l2_slice_video_decode_accelerator.h"
@@ -27,21 +28,20 @@
#include "base/threading/thread_task_runner_handle.h"
#include "shared_memory_region.h"
-#define LOGF(level) LOG(level) << __func__ << "(): "
-#define DLOGF(level) DLOG(level) << __func__ << "(): "
#define DVLOGF(level) DVLOG(level) << __func__ << "(): "
-#define PLOGF(level) PLOG(level) << __func__ << "(): "
+#define VLOGF(level) VLOG(level) << __func__ << "(): "
+#define VPLOGF(level) VPLOG(level) << __func__ << "(): "
-#define NOTIFY_ERROR(x) \
- do { \
- LOGF(ERROR) << "Setting error state:" << x; \
- SetErrorState(x); \
+#define NOTIFY_ERROR(x) \
+ do { \
+ VLOGF(1) << "Setting error state: " << x; \
+ SetErrorState(x); \
} while (0)
#define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value, type_str) \
do { \
if (device_->Ioctl(type, arg) != 0) { \
- PLOGF(ERROR) << "ioctl() failed: " << type_str; \
+ VPLOGF(1) << "ioctl() failed: " << type_str; \
return value; \
} \
} while (0)
@@ -52,10 +52,10 @@
#define IOCTL_OR_ERROR_RETURN_FALSE(type, arg) \
IOCTL_OR_ERROR_RETURN_VALUE(type, arg, false, #type)
-#define IOCTL_OR_LOG_ERROR(type, arg) \
- do { \
- if (device_->Ioctl(type, arg) != 0) \
- PLOGF(ERROR) << "ioctl() failed: " << #type; \
+#define IOCTL_OR_LOG_ERROR(type, arg) \
+ do { \
+ if (device_->Ioctl(type, arg) != 0) \
+ VPLOGF(1) << "ioctl() failed: " << #type; \
} while (0)
namespace media {
@@ -84,6 +84,11 @@
int input_record() const { return input_record_; }
int output_record() const { return output_record_; }
uint32_t config_store() const { return config_store_; }
+ Rect visible_rect() const { return visible_rect_; }
+
+ void set_visible_rect(const Rect& visible_rect) {
+ visible_rect_ = visible_rect;
+ }
// Take references to each reference surface and keep them until the
// target surface is decoded.
@@ -108,6 +113,7 @@
int input_record_;
int output_record_;
uint32_t config_store_;
+ Rect visible_rect_;
bool decoded_;
ReleaseCB release_cb_;
@@ -474,7 +480,7 @@
bool V4L2SliceVideoDecodeAccelerator::Initialize(const Config& config,
Client* client) {
- DVLOGF(3) << "profile: " << config.profile;
+ VLOGF(3) << "profile: " << config.profile;
DCHECK(child_task_runner_->BelongsToCurrentThread());
DCHECK_EQ(state_, kUninitialized);
@@ -506,8 +512,8 @@
V4L2Device::VideoCodecProfileToV4L2PixFmt(video_profile_, true);
if (!device_->Open(V4L2Device::Type::kDecoder, input_format_fourcc_)) {
- DVLOGF(1) << "Failed to open device for profile: " << config.profile
- << " fourcc: " << std::hex << "0x" << input_format_fourcc_;
+ VLOGF(1) << "Failed to open device for profile: " << config.profile
+ << " fourcc: " << std::hex << "0x" << input_format_fourcc_;
return false;
}
@@ -532,8 +538,8 @@
const __u32 kCapsRequired = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps);
if ((caps.capabilities & kCapsRequired) != kCapsRequired) {
- LOGF(ERROR) << "ioctl() failed: VIDIOC_QUERYCAP"
- << ", caps check failed: 0x" << std::hex << caps.capabilities;
+ VLOGF(1) << "ioctl() failed: VIDIOC_QUERYCAP"
+ << ", caps check failed: 0x" << std::hex << caps.capabilities;
return false;
}
@@ -541,7 +547,7 @@
return false;
if (!decoder_thread_.Start()) {
- DLOGF(ERROR) << "device thread failed to start";
+ VLOGF(1) << "device thread failed to start";
return false;
}
decoder_thread_task_runner_ = decoder_thread_.task_runner();
@@ -554,12 +560,12 @@
FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::InitializeTask,
base::Unretained(this)));
- DVLOGF(1) << "V4L2SliceVideoDecodeAccelerator initialized";
+ VLOGF(2) << "V4L2SliceVideoDecodeAccelerator initialized";
return true;
}
void V4L2SliceVideoDecodeAccelerator::InitializeTask() {
- DVLOGF(3);
+ VLOGF(2);
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
DCHECK_EQ(state_, kInitialized);
@@ -572,7 +578,7 @@
}
void V4L2SliceVideoDecodeAccelerator::Destroy() {
- DVLOGF(3);
+ VLOGF(2);
DCHECK(child_task_runner_->BelongsToCurrentThread());
if (decoder_thread_.IsRunning()) {
@@ -585,11 +591,11 @@
}
delete this;
- DVLOGF(3) << "Destroyed";
+ VLOGF(2) << "Destroyed";
}
void V4L2SliceVideoDecodeAccelerator::DestroyTask() {
- DVLOGF(3);
+ DVLOGF(2);
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
state_ = kError;
@@ -675,7 +681,7 @@
}
if (output_format_fourcc_ == 0) {
- LOGF(ERROR) << "Could not find a usable output format";
+ VLOGF(1) << "Could not find a usable output format";
return false;
}
@@ -691,7 +697,7 @@
}
bool V4L2SliceVideoDecodeAccelerator::CreateInputBuffers() {
- DVLOGF(3);
+ VLOGF(2);
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
DCHECK(!input_streamon_);
DCHECK(input_buffer_map_.empty());
@@ -703,7 +709,7 @@
reqbufs.memory = V4L2_MEMORY_MMAP;
IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs);
if (reqbufs.count < kNumInputBuffers) {
- PLOGF(ERROR) << "Could not allocate enough output buffers";
+ VLOGF(1) << "Could not allocate enough output buffers";
return false;
}
input_buffer_map_.resize(reqbufs.count);
@@ -727,7 +733,7 @@
MAP_SHARED,
buffer.m.planes[0].m.mem_offset);
if (address == MAP_FAILED) {
- PLOGF(ERROR) << "mmap() failed";
+ VLOGF(1) << "mmap() failed";
return false;
}
input_buffer_map_[i].address = address;
@@ -738,29 +744,29 @@
}
bool V4L2SliceVideoDecodeAccelerator::CreateOutputBuffers() {
- DVLOGF(3);
+ VLOGF(2);
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
DCHECK(!output_streamon_);
DCHECK(output_buffer_map_.empty());
DCHECK(surfaces_at_display_.empty());
DCHECK(surfaces_at_device_.empty());
- visible_size_ = decoder_->GetPicSize();
+ Size pic_size = decoder_->GetPicSize();
size_t num_pictures = decoder_->GetRequiredNumOfPictures();
DCHECK_GT(num_pictures, 0u);
- DCHECK(!visible_size_.IsEmpty());
+ DCHECK(!pic_size.IsEmpty());
struct v4l2_format format;
memset(&format, 0, sizeof(format));
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
format.fmt.pix_mp.pixelformat = output_format_fourcc_;
- format.fmt.pix_mp.width = visible_size_.width();
- format.fmt.pix_mp.height = visible_size_.height();
+ format.fmt.pix_mp.width = pic_size.width();
+ format.fmt.pix_mp.height = pic_size.height();
format.fmt.pix_mp.num_planes = input_planes_count_;
if (device_->Ioctl(VIDIOC_S_FMT, &format) != 0) {
- PLOGF(ERROR) << "Failed setting format to: " << output_format_fourcc_;
+ VPLOGF(1) << "Failed setting format to: " << output_format_fourcc_;
NOTIFY_ERROR(PLATFORM_FAILURE);
return false;
}
@@ -770,22 +776,17 @@
DCHECK_EQ(coded_size_.width() % 16, 0);
DCHECK_EQ(coded_size_.height() % 16, 0);
- if (!Rect(coded_size_).Contains(Rect(visible_size_))) {
- LOGF(ERROR) << "Got invalid adjusted coded size: "
- << coded_size_.ToString();
+ if (!Rect(coded_size_).Contains(Rect(pic_size))) {
+ VLOGF(1) << "Got invalid adjusted coded size: " << coded_size_.ToString();
return false;
}
DVLOGF(3) << "buffer_count=" << num_pictures
- << ", visible size=" << visible_size_.ToString()
+ << ", pic size=" << pic_size.ToString()
<< ", coded size=" << coded_size_.ToString();
- // With ALLOCATE mode the client can sample it as RGB and doesn't need to
- // know the precise format.
VideoPixelFormat pixel_format =
- (output_mode_ == Config::OutputMode::IMPORT)
- ? V4L2Device::V4L2PixFmtToVideoPixelFormat(output_format_fourcc_)
- : PIXEL_FORMAT_UNKNOWN;
+ V4L2Device::V4L2PixFmtToVideoPixelFormat(output_format_fourcc_);
child_task_runner_->PostTask(
FROM_HERE,
@@ -805,7 +806,7 @@
}
void V4L2SliceVideoDecodeAccelerator::DestroyInputBuffers() {
- DVLOGF(3);
+ VLOGF(2);
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread() ||
!decoder_thread_.IsRunning());
DCHECK(!input_streamon_);
@@ -836,7 +837,7 @@
DCHECK(child_task_runner_->BelongsToCurrentThread());
for (auto picture_buffer_id : picture_buffer_ids) {
- DVLOGF(1) << "dismissing PictureBuffer id=" << picture_buffer_id;
+ DVLOGF(4) << "dismissing PictureBuffer id=" << picture_buffer_id;
client_->DismissPictureBuffer(picture_buffer_id);
}
@@ -844,7 +845,7 @@
}
void V4L2SliceVideoDecodeAccelerator::DevicePollTask(bool poll_device) {
- DVLOGF(4);
+ DVLOGF(3);
DCHECK(device_poll_thread_.task_runner()->BelongsToCurrentThread());
bool event_pending;
@@ -874,7 +875,7 @@
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
if (!device_poll_thread_.IsRunning()) {
- DVLOGF(2) << "Device poll thread stopped, will not schedule poll";
+ DVLOGF(4) << "Device poll thread stopped, will not schedule poll";
return;
}
@@ -891,7 +892,7 @@
FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DevicePollTask,
base::Unretained(this), true));
- DVLOGF(2) << "buffer counts: "
+ DVLOGF(3) << "buffer counts: "
<< "INPUT[" << decoder_input_queue_.size() << "]"
<< " => DEVICE["
<< free_input_buffers_.size() << "+"
@@ -913,13 +914,13 @@
if (!EnqueueInputRecord(dec_surface->input_record(),
dec_surface->config_store())) {
- DVLOGF(1) << "Failed queueing an input buffer";
+ VLOGF(1) << "Failed queueing an input buffer";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
}
if (!EnqueueOutputRecord(dec_surface->output_record())) {
- DVLOGF(1) << "Failed queueing an output buffer";
+ VLOGF(1) << "Failed queueing an output buffer";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
}
@@ -935,7 +936,7 @@
}
void V4L2SliceVideoDecodeAccelerator::Dequeue() {
- DVLOGF(3);
+ DVLOGF(4);
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
struct v4l2_buffer dqbuf;
@@ -953,7 +954,7 @@
// EAGAIN if we're just out of buffers to dequeue.
break;
}
- PLOGF(ERROR) << "ioctl() failed: VIDIOC_DQBUF";
+ VPLOGF(1) << "ioctl() failed: VIDIOC_DQBUF";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
}
@@ -981,7 +982,7 @@
// EAGAIN if we're just out of buffers to dequeue.
break;
}
- PLOGF(ERROR) << "ioctl() failed: VIDIOC_DQBUF";
+ VPLOGF(1) << "ioctl() failed: VIDIOC_DQBUF";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
}
@@ -989,13 +990,13 @@
DCHECK(output_record.at_device);
output_record.at_device = false;
output_buffer_queued_count_--;
- DVLOGF(3) << "Dequeued output=" << dqbuf.index
- << " count " << output_buffer_queued_count_;
+ DVLOGF(4) << "Dequeued output=" << dqbuf.index << " count "
+ << output_buffer_queued_count_;
V4L2DecodeSurfaceByOutputId::iterator it =
surfaces_at_device_.find(dqbuf.index);
if (it == surfaces_at_device_.end()) {
- DLOGF(ERROR) << "Got invalid surface from device.";
+ VLOGF(1) << "Got invalid surface from device.";
NOTIFY_ERROR(PLATFORM_FAILURE);
}
@@ -1090,7 +1091,7 @@
bool V4L2SliceVideoDecodeAccelerator::EnqueueInputRecord(
int index,
uint32_t config_store) {
- DVLOGF(3);
+ DVLOGF(4);
DCHECK_LT(index, static_cast<int>(input_buffer_map_.size()));
DCHECK_GT(config_store, 0u);
@@ -1118,7 +1119,7 @@
}
bool V4L2SliceVideoDecodeAccelerator::EnqueueOutputRecord(int index) {
- DVLOGF(3);
+ DVLOGF(4);
DCHECK_LT(index, static_cast<int>(output_buffer_map_.size()));
// Enqueue an output (VIDEO_CAPTURE) buffer.
@@ -1161,7 +1162,7 @@
// Start up the device poll thread and schedule its first DevicePollTask().
if (!device_poll_thread_.Start()) {
- DLOGF(ERROR) << "Device thread failed to start";
+ VLOGF(1) << "Device thread failed to start";
NOTIFY_ERROR(PLATFORM_FAILURE);
return false;
}
@@ -1191,7 +1192,7 @@
// Signal the DevicePollTask() to stop, and stop the device poll thread.
if (!device_->SetDevicePollInterrupt()) {
- PLOGF(ERROR) << "SetDevicePollInterrupt(): failed";
+ VPLOGF(1) << "SetDevicePollInterrupt(): failed";
NOTIFY_ERROR(PLATFORM_FAILURE);
return false;
}
@@ -1253,12 +1254,12 @@
void V4L2SliceVideoDecodeAccelerator::Decode(
const BitstreamBuffer& bitstream_buffer) {
- DVLOGF(3) << "input_id=" << bitstream_buffer.id()
+ DVLOGF(4) << "input_id=" << bitstream_buffer.id()
<< ", size=" << bitstream_buffer.size();
DCHECK(decode_task_runner_->BelongsToCurrentThread());
if (bitstream_buffer.id() < 0) {
- LOGF(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id();
+ VLOGF(1) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id();
if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle()))
base::SharedMemory::CloseHandle(bitstream_buffer.handle());
NOTIFY_ERROR(INVALID_ARGUMENT);
@@ -1272,7 +1273,7 @@
void V4L2SliceVideoDecodeAccelerator::DecodeTask(
const BitstreamBuffer& bitstream_buffer) {
- DVLOGF(3) << "input_id=" << bitstream_buffer.id()
+ DVLOGF(4) << "input_id=" << bitstream_buffer.id()
<< " size=" << bitstream_buffer.size();
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
@@ -1285,11 +1286,11 @@
return;
if (!bitstream_record->shm->Map()) {
- LOGF(ERROR) << "Could not map bitstream_buffer";
+ VLOGF(1) << "Could not map bitstream_buffer";
NOTIFY_ERROR(UNREADABLE_INPUT);
return;
}
- DVLOGF(3) << "mapped at=" << bitstream_record->shm->memory();
+ DVLOGF(4) << "mapped at=" << bitstream_record->shm->memory();
decoder_input_queue_.push(
linked_ptr<BitstreamBufferRef>(bitstream_record.release()));
@@ -1333,7 +1334,7 @@
}
void V4L2SliceVideoDecodeAccelerator::DecodeBufferTask() {
- DVLOGF(3);
+ DVLOGF(4);
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
if (state_ != kDecoding) {
@@ -1346,7 +1347,7 @@
res = decoder_->Decode();
switch (res) {
case AcceleratedVideoDecoder::kAllocateNewSurfaces:
- DVLOGF(2) << "Decoder requesting a new set of surfaces";
+ VLOGF(2) << "Decoder requesting a new set of surfaces";
InitiateSurfaceSetChange();
return;
@@ -1367,7 +1368,7 @@
return;
case AcceleratedVideoDecoder::kDecodeError:
- DVLOGF(1) << "Error decoding stream";
+ VLOGF(1) << "Error decoding stream";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
}
@@ -1375,7 +1376,7 @@
}
void V4L2SliceVideoDecodeAccelerator::InitiateSurfaceSetChange() {
- DVLOGF(2);
+ VLOGF(2);
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
DCHECK_EQ(state_, kDecoding);
@@ -1385,7 +1386,7 @@
}
bool V4L2SliceVideoDecodeAccelerator::FinishSurfaceSetChange() {
- DVLOGF(2);
+ VLOGF(2);
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
if (!surface_set_change_pending_)
@@ -1408,6 +1409,12 @@
return false;
}
+ // Dequeued decoded surfaces may be pended in pending_picture_ready_ if they
+ // are waiting for some pictures to be cleared. We should post them right away
+ // because they are about to be dismissed and destroyed for surface set
+ // change.
+ SendPictureReady();
+
// This will return only once all buffers are dismissed and destroyed.
// This does not wait until they are displayed however, as display retains
// references to the buffers bound to textures and will release them
@@ -1423,12 +1430,12 @@
}
surface_set_change_pending_ = false;
- DVLOGF(3) << "Surface set change finished";
+ VLOGF(2) << "Surface set change finished";
return true;
}
bool V4L2SliceVideoDecodeAccelerator::DestroyOutputs(bool dismiss) {
- DVLOGF(3);
+ VLOGF(2);
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
std::vector<int32_t> picture_buffers_to_dismiss;
@@ -1441,7 +1448,7 @@
}
if (dismiss) {
- DVLOGF(2) << "Scheduling picture dismissal";
+ VLOGF(2) << "Scheduling picture dismissal";
base::WaitableEvent done(base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED);
child_task_runner_->PostTask(
@@ -1456,7 +1463,7 @@
}
bool V4L2SliceVideoDecodeAccelerator::DestroyOutputBuffers() {
- DVLOGF(3);
+ VLOGF(2);
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread() ||
!decoder_thread_.IsRunning());
DCHECK(!output_streamon_);
@@ -1498,7 +1505,7 @@
void V4L2SliceVideoDecodeAccelerator::AssignPictureBuffers(
const std::vector<PictureBuffer>& buffers) {
- DVLOGF(3);
+ VLOGF(2);
DCHECK(child_task_runner_->BelongsToCurrentThread());
decoder_thread_task_runner_->PostTask(
@@ -1509,16 +1516,16 @@
void V4L2SliceVideoDecodeAccelerator::AssignPictureBuffersTask(
const std::vector<PictureBuffer>& buffers) {
- DVLOGF(3);
+ VLOGF(2);
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
DCHECK_EQ(state_, kAwaitingPictureBuffers);
const uint32_t req_buffer_count = decoder_->GetRequiredNumOfPictures();
if (buffers.size() < req_buffer_count) {
- DLOG(ERROR) << "Failed to provide requested picture buffers. "
- << "(Got " << buffers.size()
- << ", requested " << req_buffer_count << ")";
+ VLOGF(1) << "Failed to provide requested picture buffers. "
+ << "(Got " << buffers.size() << ", requested " << req_buffer_count
+ << ")";
NOTIFY_ERROR(INVALID_ARGUMENT);
return;
}
@@ -1534,7 +1541,7 @@
IOCTL_OR_ERROR_RETURN(VIDIOC_REQBUFS, &reqbufs);
if (reqbufs.count != buffers.size()) {
- DLOGF(ERROR) << "Could not allocate enough output buffers";
+ VLOGF(1) << "Could not allocate enough output buffers";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
}
@@ -1587,6 +1594,7 @@
void V4L2SliceVideoDecodeAccelerator::ImportBufferForPicture(
int32_t picture_buffer_id,
+ VideoPixelFormat pixel_format,
const NativePixmapHandle& native_pixmap_handle) {
DVLOGF(3) << "picture_buffer_id=" << picture_buffer_id;
DCHECK(child_task_runner_->BelongsToCurrentThread());
@@ -1598,7 +1606,14 @@
}
if (output_mode_ != Config::OutputMode::IMPORT) {
- LOGF(ERROR) << "Cannot import in non-import mode";
+ VLOGF(1) << "Cannot import in non-import mode";
+ NOTIFY_ERROR(INVALID_ARGUMENT);
+ return;
+ }
+
+ if (pixel_format !=
+ V4L2Device::V4L2PixFmtToVideoPixelFormat(output_format_fourcc_)) {
+ VLOGF(1) << "Unsupported import format: " << pixel_format;
NOTIFY_ERROR(INVALID_ARGUMENT);
return;
}
@@ -1632,7 +1647,7 @@
}
if (!iter->at_client) {
- LOGF(ERROR) << "Cannot import buffer that not owned by client";
+ VLOGF(1) << "Cannot import buffer that not owned by client";
NOTIFY_ERROR(INVALID_ARGUMENT);
return;
}
@@ -1664,7 +1679,7 @@
void V4L2SliceVideoDecodeAccelerator::ReusePictureBufferTask(
int32_t picture_buffer_id) {
- DVLOGF(3) << "picture_buffer_id=" << picture_buffer_id;
+ DVLOGF(4) << "picture_buffer_id=" << picture_buffer_id;
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
V4L2DecodeSurfaceByPictureBufferId::iterator it =
@@ -1682,7 +1697,7 @@
OutputRecord& output_record = output_buffer_map_[it->second->output_record()];
if (output_record.at_device || !output_record.at_client) {
- DVLOGF(1) << "picture_buffer_id not reusable";
+ VLOGF(1) << "picture_buffer_id not reusable";
NOTIFY_ERROR(INVALID_ARGUMENT);
return;
}
@@ -1694,7 +1709,7 @@
}
void V4L2SliceVideoDecodeAccelerator::Flush() {
- DVLOGF(3);
+ VLOGF(2);
DCHECK(child_task_runner_->BelongsToCurrentThread());
decoder_thread_task_runner_->PostTask(
@@ -1703,7 +1718,7 @@
}
void V4L2SliceVideoDecodeAccelerator::FlushTask() {
- DVLOGF(3);
+ VLOGF(2);
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
// Queue an empty buffer which - when reached - will trigger flush sequence.
@@ -1715,7 +1730,7 @@
}
void V4L2SliceVideoDecodeAccelerator::InitiateFlush() {
- DVLOGF(3);
+ VLOGF(2);
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
// This will trigger output for all remaining surfaces in the decoder.
@@ -1736,7 +1751,7 @@
}
bool V4L2SliceVideoDecodeAccelerator::FinishFlush() {
- DVLOGF(3);
+ VLOGF(4);
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
if (!decoder_flushing_)
@@ -1762,7 +1777,7 @@
SendPictureReady();
decoder_flushing_ = false;
- DVLOGF(3) << "Flush finished";
+ VLOGF(2) << "Flush finished";
child_task_runner_->PostTask(FROM_HERE,
base::Bind(&Client::NotifyFlushDone, client_));
@@ -1771,7 +1786,7 @@
}
void V4L2SliceVideoDecodeAccelerator::Reset() {
- DVLOGF(3);
+ VLOGF(2);
DCHECK(child_task_runner_->BelongsToCurrentThread());
decoder_thread_task_runner_->PostTask(
@@ -1780,7 +1795,7 @@
}
void V4L2SliceVideoDecodeAccelerator::ResetTask() {
- DVLOGF(3);
+ VLOGF(2);
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
if (decoder_resetting_) {
@@ -1803,7 +1818,7 @@
}
bool V4L2SliceVideoDecodeAccelerator::FinishReset() {
- DVLOGF(3);
+ VLOGF(4);
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
if (!decoder_resetting_)
@@ -1834,7 +1849,7 @@
}
decoder_resetting_ = false;
- DVLOGF(3) << "Reset finished";
+ VLOGF(2) << "Reset finished";
child_task_runner_->PostTask(FROM_HERE,
base::Bind(&Client::NotifyResetDone, client_));
@@ -1898,7 +1913,7 @@
size_t i = 0;
for (const auto& pic : dpb) {
if (i >= arraysize(v4l2_decode_param_.dpb)) {
- DVLOGF(1) << "Invalid DPB size";
+ VLOGF(1) << "Invalid DPB size";
break;
}
@@ -2108,7 +2123,7 @@
const uint8_t* data,
size_t size) {
if (num_slices_ == kMaxSlices) {
- LOGF(ERROR) << "Over limit of supported slices per frame";
+ VLOGF(1) << "Over limit of supported slices per frame";
return false;
}
@@ -2228,7 +2243,7 @@
InputRecord& input_record = input_buffer_map_[index];
if (input_record.bytes_used + size > input_record.length) {
- DVLOGF(1) << "Input buffer too small";
+ VLOGF(1) << "Input buffer too small";
return false;
}
@@ -2306,6 +2321,7 @@
const scoped_refptr<H264Picture>& pic) {
scoped_refptr<V4L2DecodeSurface> dec_surface =
H264PictureToV4L2DecodeSurface(pic);
+ dec_surface->set_visible_rect(pic->visible_rect);
v4l2_dec_->SurfaceReady(dec_surface);
return true;
}
@@ -2537,7 +2553,7 @@
const scoped_refptr<VP8Picture>& pic) {
scoped_refptr<V4L2DecodeSurface> dec_surface =
VP8PictureToV4L2DecodeSurface(pic);
-
+ dec_surface->set_visible_rect(pic->visible_rect);
v4l2_dec_->SurfaceReady(dec_surface);
return true;
}
@@ -2840,7 +2856,7 @@
const scoped_refptr<VP9Picture>& pic) {
scoped_refptr<V4L2DecodeSurface> dec_surface =
VP9PictureToV4L2DecodeSurface(pic);
-
+ dec_surface->set_visible_rect(pic->visible_rect);
v4l2_dec_->SurfaceReady(dec_surface);
return true;
}
@@ -2920,13 +2936,13 @@
const scoped_refptr<V4L2DecodeSurface>& dec_surface) {
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
- DVLOGF(3) << "Submitting decode for surface: " << dec_surface->ToString();
+ DVLOGF(4) << "Submitting decode for surface: " << dec_surface->ToString();
Enqueue(dec_surface);
}
void V4L2SliceVideoDecodeAccelerator::SurfaceReady(
const scoped_refptr<V4L2DecodeSurface>& dec_surface) {
- DVLOGF(3);
+ DVLOGF(4);
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
decoder_display_queue_.push(dec_surface);
@@ -2964,14 +2980,12 @@
DCHECK_NE(output_record.picture_id, -1);
output_record.at_client = true;
- // TODO(posciak): Use visible size from decoder here instead
- // (crbug.com/402760). Passing (0, 0) results in the client using the
- // visible size extracted from the container instead.
Picture picture(output_record.picture_id, dec_surface->bitstream_id(),
- Rect(0, 0), false);
- DVLOGF(3) << dec_surface->ToString()
+ dec_surface->visible_rect(), true /* allow_overlay */);
+ DVLOGF(4) << dec_surface->ToString()
<< ", bitstream_id: " << picture.bitstream_buffer_id()
- << ", picture_id: " << picture.picture_buffer_id();
+ << ", picture_id: " << picture.picture_buffer_id()
+ << ", visible_rect: " << picture.visible_rect().ToString();
pending_picture_ready_.push(PictureRecord(output_record.cleared, picture));
SendPictureReady();
output_record.cleared = true;
@@ -3006,9 +3020,10 @@
}
void V4L2SliceVideoDecodeAccelerator::SendPictureReady() {
- DVLOGF(3);
+ DVLOGF(4);
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
- bool resetting_or_flushing = (decoder_resetting_ || decoder_flushing_);
+ bool send_now =
+ (decoder_resetting_ || decoder_flushing_ || surface_set_change_pending_);
while (!pending_picture_ready_.empty()) {
bool cleared = pending_picture_ready_.front().cleared;
const Picture& picture = pending_picture_ready_.front().picture;
@@ -3022,17 +3037,20 @@
FROM_HERE,
base::Bind(&Client::PictureReady, decode_client_, picture));
pending_picture_ready_.pop();
- } else if (!cleared || resetting_or_flushing) {
- DVLOGF(3) << "cleared=" << pending_picture_ready_.front().cleared
+ } else if (!cleared || send_now) {
+ DVLOGF(4) << "cleared=" << pending_picture_ready_.front().cleared
<< ", decoder_resetting_=" << decoder_resetting_
<< ", decoder_flushing_=" << decoder_flushing_
+ << ", surface_set_change_pending_="
+ << surface_set_change_pending_
<< ", picture_clearing_count_=" << picture_clearing_count_;
DVLOGF(4) << "Posting picture ready to GPU for: "
<< picture.picture_buffer_id();
// If the picture is not cleared, post it to the child thread because it
// has to be cleared in the child thread. A picture only needs to be
- // cleared once. If the decoder is resetting or flushing, send all
- // pictures to ensure PictureReady arrive before reset or flush done.
+ // cleared once. If the decoder is resetting or flushing or changing
+ // resolution, send all pictures to ensure PictureReady arrive before
+ // reset done, flush done, or picture dismissed.
child_task_runner_->PostTaskAndReply(
FROM_HERE, base::Bind(&Client::PictureReady, client_, picture),
// Unretained is safe. If Client::PictureReady gets to run, |this| is
@@ -3051,7 +3069,7 @@
}
void V4L2SliceVideoDecodeAccelerator::PictureCleared() {
- DVLOGF(3) << "clearing count=" << picture_clearing_count_;
+ DVLOGF(4) << "clearing count=" << picture_clearing_count_;
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
DCHECK_GT(picture_clearing_count_, 0);
picture_clearing_count_--;
diff --git a/vda/v4l2_slice_video_decode_accelerator.h b/vda/v4l2_slice_video_decode_accelerator.h
index 56d4374..8849625 100644
--- a/vda/v4l2_slice_video_decode_accelerator.h
+++ b/vda/v4l2_slice_video_decode_accelerator.h
@@ -1,6 +1,7 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 85fdf90
#ifndef V4L2_SLICE_VIDEO_DECODE_ACCELERATOR_H_
#define V4L2_SLICE_VIDEO_DECODE_ACCELERATOR_H_
@@ -47,6 +48,7 @@
void AssignPictureBuffers(const std::vector<PictureBuffer>& buffers) override;
void ImportBufferForPicture(
int32_t picture_buffer_id,
+ VideoPixelFormat pixel_format,
const NativePixmapHandle& native_pixmap_handle) override;
void ReusePictureBuffer(int32_t picture_buffer_id) override;
void Flush() override;
@@ -77,6 +79,7 @@
// Record for output buffers.
struct OutputRecord {
OutputRecord();
+ OutputRecord(OutputRecord&&) = default;
bool at_device;
bool at_client;
int32_t picture_id;
@@ -234,9 +237,9 @@
// file descriptors.
void ImportBufferForPictureTask(
int32_t picture_buffer_id,
- // TODO(posciak): (crbug.com/561749) we should normally be able to pass
- // the vector by itself via std::move, but it's not possible to do this
- // if this method is used as a callback.
+ // TODO(posciak): (https://crbug.com/561749) we should normally be able to
+ // pass the vector by itself via std::move, but it's not possible to do
+ // this if this method is used as a callback.
std::unique_ptr<std::vector<base::ScopedFD>> passed_dmabuf_fds);
// Performed on decoder_thread_ as a consequence of poll() on decoder_thread_
@@ -366,7 +369,6 @@
VideoCodecProfile video_profile_;
uint32_t input_format_fourcc_;
uint32_t output_format_fourcc_;
- Size visible_size_;
Size coded_size_;
struct BitstreamBufferRef;
@@ -417,6 +419,7 @@
bool cleared; // Whether the texture is cleared and safe to render from.
Picture picture; // The decoded picture.
};
+
// Pictures that are ready but not sent to PictureReady yet.
std::queue<PictureRecord> pending_picture_ready_;
diff --git a/vda/v4l2_video_decode_accelerator.cc b/vda/v4l2_video_decode_accelerator.cc
index 0003688..22a0912 100644
--- a/vda/v4l2_video_decode_accelerator.cc
+++ b/vda/v4l2_video_decode_accelerator.cc
@@ -1,6 +1,8 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 91175b1
+// Note: image processor is not ported.
#include "v4l2_video_decode_accelerator.h"
@@ -28,22 +30,20 @@
#include "shared_memory_region.h"
#include "videodev2.h"
-#define LOGF(level) LOG(level) << __func__ << "(): "
-#define DLOGF(level) DLOG(level) << __func__ << "(): "
#define DVLOGF(level) DVLOG(level) << __func__ << "(): "
#define VLOGF(level) VLOG(level) << __func__ << "(): "
-#define PLOGF(level) PLOG(level) << __func__ << "(): "
+#define VPLOGF(level) VPLOG(level) << __func__ << "(): "
-#define NOTIFY_ERROR(x) \
- do { \
- LOGF(ERROR) << "Setting error state:" << x; \
- SetErrorState(x); \
+#define NOTIFY_ERROR(x) \
+ do { \
+ VLOGF(1) << "Setting error state:" << x; \
+ SetErrorState(x); \
} while (0)
#define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value, type_str) \
do { \
if (device_->Ioctl(type, arg) != 0) { \
- PLOGF(ERROR) << "ioctl() failed: " << type_str; \
+ VPLOGF(1) << "ioctl() failed: " << type_str; \
NOTIFY_ERROR(PLATFORM_FAILURE); \
return value; \
} \
@@ -55,10 +55,10 @@
#define IOCTL_OR_ERROR_RETURN_FALSE(type, arg) \
IOCTL_OR_ERROR_RETURN_VALUE(type, arg, false, #type)
-#define IOCTL_OR_LOG_ERROR(type, arg) \
- do { \
- if (device_->Ioctl(type, arg) != 0) \
- PLOGF(ERROR) << "ioctl() failed: " << #type; \
+#define IOCTL_OR_LOG_ERROR(type, arg) \
+ do { \
+ if (device_->Ioctl(type, arg) != 0) \
+ VPLOGF(1) << "ioctl() failed: " << #type; \
} while (0)
namespace media {
@@ -153,6 +153,7 @@
V4L2VideoDecodeAccelerator::~V4L2VideoDecodeAccelerator() {
DCHECK(!decoder_thread_.IsRunning());
DCHECK(!device_poll_thread_.IsRunning());
+ DVLOGF(2);
// These maps have members that should be manually destroyed, e.g. file
// descriptors, mmap() segments, etc.
@@ -199,8 +200,8 @@
const __u32 kCapsRequired = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps);
if ((caps.capabilities & kCapsRequired) != kCapsRequired) {
- LOGF(ERROR) << "ioctl() failed: VIDIOC_QUERYCAP"
- << ", caps check failed: 0x" << std::hex << caps.capabilities;
+ VLOGF(1) << "ioctl() failed: VIDIOC_QUERYCAP"
+ << ", caps check failed: 0x" << std::hex << caps.capabilities;
return false;
}
@@ -212,7 +213,7 @@
}
if (!decoder_thread_.Start()) {
- LOGF(ERROR) << "decoder thread failed to start";
+ VLOGF(1) << "decoder thread failed to start";
return false;
}
@@ -256,7 +257,7 @@
DCHECK(decode_task_runner_->BelongsToCurrentThread());
if (bitstream_buffer.id() < 0) {
- LOGF(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id();
+ VLOGF(1) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id();
if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle()))
base::SharedMemory::CloseHandle(bitstream_buffer.handle());
NOTIFY_ERROR(INVALID_ARGUMENT);
@@ -289,8 +290,8 @@
uint32_t req_buffer_count = output_dpb_size_ + kDpbOutputBufferExtraCount;
if (buffers.size() < req_buffer_count) {
- LOGF(ERROR) << "Failed to provide requested picture buffers. (Got "
- << buffers.size() << ", requested " << req_buffer_count << ")";
+ VLOGF(1) << "Failed to provide requested picture buffers. (Got "
+ << buffers.size() << ", requested " << req_buffer_count << ")";
NOTIFY_ERROR(INVALID_ARGUMENT);
return;
}
@@ -304,7 +305,7 @@
IOCTL_OR_ERROR_RETURN(VIDIOC_REQBUFS, &reqbufs);
if (reqbufs.count != buffers.size()) {
- DLOGF(ERROR) << "Could not allocate enough output buffers";
+ VLOGF(1) << "Could not allocate enough output buffers";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
}
@@ -334,22 +335,31 @@
void V4L2VideoDecodeAccelerator::ImportBufferForPicture(
int32_t picture_buffer_id,
+ VideoPixelFormat pixel_format,
const NativePixmapHandle& native_pixmap_handle) {
DVLOGF(3) << "picture_buffer_id=" << picture_buffer_id;
DCHECK(child_task_runner_->BelongsToCurrentThread());
if (output_mode_ != Config::OutputMode::IMPORT) {
- LOGF(ERROR) << "Cannot import in non-import mode";
+ VLOGF(1) << "Cannot import in non-import mode";
NOTIFY_ERROR(INVALID_ARGUMENT);
return;
}
+
+ if (pixel_format !=
+ V4L2Device::V4L2PixFmtToVideoPixelFormat(output_format_fourcc_)) {
+ VLOGF(1) << "Unsupported import format: " << pixel_format;
+ NOTIFY_ERROR(INVALID_ARGUMENT);
+ return;
+ }
+
std::vector<base::ScopedFD> dmabuf_fds;
for (const auto& fd : native_pixmap_handle.fds) {
DCHECK_NE(fd.fd, -1);
dmabuf_fds.push_back(base::ScopedFD(fd.fd));
}
- decode_task_runner_->PostTask(
+ decoder_thread_.task_runner()->PostTask(
FROM_HERE,
base::Bind(&V4L2VideoDecodeAccelerator::ImportBufferForPictureTask,
base::Unretained(this), picture_buffer_id,
@@ -379,7 +389,7 @@
}
if (iter->state != kAtClient) {
- LOGF(ERROR) << "Cannot import buffer not owned by client";
+ VLOGF(1) << "Cannot import buffer not owned by client";
NOTIFY_ERROR(INVALID_ARGUMENT);
return;
}
@@ -448,6 +458,7 @@
}
delete this;
+ VLOGF(2) << "Destroyed.";
}
bool V4L2VideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread(
@@ -489,7 +500,7 @@
return;
if (!bitstream_record->shm->Map()) {
- LOGF(ERROR) << "could not map bitstream_buffer";
+ VLOGF(1) << "could not map bitstream_buffer";
NOTIFY_ERROR(UNREADABLE_INPUT);
return;
}
@@ -523,7 +534,7 @@
decoder_decode_buffer_tasks_scheduled_--;
if (decoder_state_ != kInitialized && decoder_state_ != kDecoding) {
- VLOGF(2) << "early out: state=" << decoder_state_;
+ DVLOGF(3) << "early out: state=" << decoder_state_;
return;
}
@@ -729,7 +740,7 @@
bool V4L2VideoDecodeAccelerator::DecodeBufferInitial(const void* data,
size_t size,
size_t* endpos) {
- DVLOGF(4) << "data=" << data << ", size=" << size;
+ DVLOGF(3) << "data=" << data << ", size=" << size;
DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
DCHECK_EQ(decoder_state_, kInitialized);
// Initial decode. We haven't been able to get output stream format info yet.
@@ -749,32 +760,21 @@
// Recycle buffers.
Dequeue();
- // Check and see if we have format info yet.
- struct v4l2_format format;
- Size visible_size;
- bool again = false;
- if (!GetFormatInfo(&format, &visible_size, &again))
- return false;
-
*endpos = size;
- if (again) {
+ // If an initial resolution change event is not done yet, a driver probably
+ // needs more stream to decode format.
+ // Return true and schedule next buffer without changing status to kDecoding.
+ // If the initial resolution change is done and coded size is known, we may
+ // still have to wait for AssignPictureBuffers() and output buffers to be
+ // allocated.
+ if (coded_size_.IsEmpty() || output_buffer_map_.empty()) {
// Need more stream to decode format, return true and schedule next buffer.
return true;
}
- // Run this initialization only on first startup.
- if (output_buffer_map_.empty()) {
- DVLOGF(4) << "running initialization";
- // Success! Setup our parameters.
- if (!CreateBuffersForFormat(format, visible_size))
- return false;
- // We are waiting for AssignPictureBuffers. Do not set the state to
- // kDecoding.
- } else {
- decoder_state_ = kDecoding;
- ScheduleDecodeBufferTaskIfNeeded();
- }
+ decoder_state_ = kDecoding;
+ ScheduleDecodeBufferTaskIfNeeded();
return true;
}
@@ -818,7 +818,7 @@
Dequeue();
if (free_input_buffers_.empty()) {
// Nope!
- DVLOGF(3) << "stalled for input buffers";
+ DVLOGF(4) << "stalled for input buffers";
return false;
}
}
@@ -843,7 +843,7 @@
// Copy in to the buffer.
InputRecord& input_record = input_buffer_map_[decoder_current_input_buffer_];
if (size > input_record.length - input_record.bytes_used) {
- LOGF(ERROR) << "over-size frame, erroring";
+ VLOGF(1) << "over-size frame, erroring";
NOTIFY_ERROR(UNREADABLE_INPUT);
return false;
}
@@ -892,7 +892,7 @@
}
void V4L2VideoDecodeAccelerator::ServiceDeviceTask(bool event_pending) {
- DVLOGF(3);
+ DVLOGF(4);
DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
DCHECK_NE(decoder_state_, kUninitialized);
TRACE_EVENT0("Video Decoder", "V4L2VDA::ServiceDeviceTask");
@@ -911,6 +911,25 @@
bool resolution_change_pending = false;
if (event_pending)
resolution_change_pending = DequeueResolutionChangeEvent();
+
+ if (!resolution_change_pending && coded_size_.IsEmpty()) {
+ // Some platforms do not send an initial resolution change event.
+ // To work around this, we need to keep checking if the initial resolution
+ // is known already by explicitly querying the format after each decode,
+ // regardless of whether we received an event.
+ // This needs to be done on initial resolution change,
+ // i.e. when coded_size_.IsEmpty().
+
+ // Try GetFormatInfo to check if an initial resolution change can be done.
+ struct v4l2_format format;
+ Size visible_size;
+ bool again;
+ if (GetFormatInfo(&format, &visible_size, &again) && !again) {
+ resolution_change_pending = true;
+ DequeueResolutionChangeEvent();
+ }
+ }
+
Dequeue();
Enqueue();
@@ -938,16 +957,16 @@
FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::DevicePollTask,
base::Unretained(this), poll_device));
- DVLOG(3) << "ServiceDeviceTask(): buffer counts: DEC["
- << decoder_input_queue_.size() << "->"
- << input_ready_queue_.size() << "] => DEVICE["
- << free_input_buffers_.size() << "+"
- << input_buffer_queued_count_ << "/"
- << input_buffer_map_.size() << "->"
- << free_output_buffers_.size() << "+"
- << output_buffer_queued_count_ << "/"
- << output_buffer_map_.size() << "] => CLIENT["
- << decoder_frames_at_client_ << "]";
+ DVLOGF(3) << "ServiceDeviceTask(): buffer counts: DEC["
+ << decoder_input_queue_.size() << "->"
+ << input_ready_queue_.size() << "] => DEVICE["
+ << free_input_buffers_.size() << "+"
+ << input_buffer_queued_count_ << "/"
+ << input_buffer_map_.size() << "->"
+ << free_output_buffers_.size() << "+"
+ << output_buffer_queued_count_ << "/"
+ << output_buffer_map_.size() << "] => CLIENT["
+ << decoder_frames_at_client_ << "]";
ScheduleDecodeBufferTaskIfNeeded();
if (resolution_change_pending)
@@ -992,7 +1011,7 @@
// We just started up a previously empty queue.
// Queue state changed; signal interrupt.
if (!device_->SetDevicePollInterrupt()) {
- PLOGF(ERROR) << "SetDevicePollInterrupt failed";
+ VPLOGF(1) << "SetDevicePollInterrupt failed";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
}
@@ -1014,7 +1033,7 @@
// We just started up a previously empty queue.
// Queue state changed; signal interrupt.
if (!device_->SetDevicePollInterrupt()) {
- PLOGF(ERROR) << "SetDevicePollInterrupt(): failed";
+ VPLOGF(1) << "SetDevicePollInterrupt(): failed";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
}
@@ -1042,8 +1061,7 @@
return true;
}
} else {
- LOGF(ERROR) << "got an event (" << ev.type
- << ") we haven't subscribed to.";
+ VLOGF(1) << "got an event (" << ev.type << ") we haven't subscribed to.";
}
}
return false;
@@ -1086,7 +1104,7 @@
// EAGAIN if we're just out of buffers to dequeue.
return false;
}
- PLOGF(ERROR) << "ioctl() failed: VIDIOC_DQBUF";
+ VPLOGF(1) << "ioctl() failed: VIDIOC_DQBUF";
NOTIFY_ERROR(PLATFORM_FAILURE);
return false;
}
@@ -1125,7 +1143,7 @@
DVLOGF(3) << "Got EPIPE. Last output buffer was already dequeued.";
return false;
}
- PLOGF(ERROR) << "ioctl() failed: VIDIOC_DQBUF";
+ VPLOGF(1) << "ioctl() failed: VIDIOC_DQBUF";
NOTIFY_ERROR(PLATFORM_FAILURE);
return false;
}
@@ -1248,14 +1266,14 @@
// posted to us by the client. In that case just ignore this (we've already
// dismissed it and accounted for that) and let the sync object get
// destroyed.
- DVLOGF(4) << "got picture id= " << picture_buffer_id
+ DVLOGF(3) << "got picture id= " << picture_buffer_id
<< " not in use (anymore?).";
return;
}
OutputRecord& output_record = output_buffer_map_[index];
if (output_record.state != kAtClient) {
- LOGF(ERROR) << "picture_buffer_id not reusable";
+ VLOGF(1) << "picture_buffer_id not reusable";
NOTIFY_ERROR(INVALID_ARGUMENT);
return;
}
@@ -1272,14 +1290,7 @@
DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
TRACE_EVENT0("Video Decoder", "V4L2VDA::FlushTask");
- // Flush outstanding buffers.
- if (decoder_state_ == kInitialized) {
- // There's nothing in the pipe, so return done immediately.
- VLOGF(2) << "returning flush";
- child_task_runner_->PostTask(FROM_HERE,
- base::Bind(&Client::NotifyFlushDone, client_));
- return;
- } else if (decoder_state_ == kError) {
+ if (decoder_state_ == kError) {
VLOGF(2) << "early out: kError state";
return;
}
@@ -1328,10 +1339,10 @@
return;
}
- // TODO(posciak): crbug.com/270039. Exynos requires a streamoff-streamon
- // sequence after flush to continue, even if we are not resetting. This would
- // make sense, because we don't really want to resume from a non-resume point
- // (e.g. not from an IDR) if we are flushed.
+ // TODO(posciak): https://crbug.com/270039. Exynos requires a
+ // streamoff-streamon sequence after flush to continue, even if we are not
+ // resetting. This would make sense, because we don't really want to resume
+ // from a non-resume point (e.g. not from an IDR) if we are flushed.
// MSE player however triggers a Flush() on chunk end, but never Reset(). One
// could argue either way, or even say that Flush() is not needed/harmful when
// transitioning to next chunk.
@@ -1361,7 +1372,7 @@
memset(&cmd, 0, sizeof(cmd));
cmd.cmd = V4L2_DEC_CMD_STOP;
if (device_->Ioctl(VIDIOC_TRY_DECODER_CMD, &cmd) != 0) {
- DVLOGF(3) "V4L2_DEC_CMD_STOP is not supported.";
+ VLOGF(2) << "V4L2_DEC_CMD_STOP is not supported.";
return false;
}
@@ -1512,7 +1523,7 @@
// Start up the device poll thread and schedule its first DevicePollTask().
if (!device_poll_thread_.Start()) {
- LOGF(ERROR) << "Device thread failed to start";
+ VLOGF(1) << "Device thread failed to start";
NOTIFY_ERROR(PLATFORM_FAILURE);
return false;
}
@@ -1534,7 +1545,7 @@
// Signal the DevicePollTask() to stop, and stop the device poll thread.
if (!device_->SetDevicePollInterrupt()) {
- PLOGF(ERROR) << "SetDevicePollInterrupt(): failed";
+ VPLOGF(1) << "SetDevicePollInterrupt(): failed";
NOTIFY_ERROR(PLATFORM_FAILURE);
return false;
}
@@ -1612,7 +1623,7 @@
SendPictureReady(); // Send all pending PictureReady.
if (!DestroyOutputBuffers()) {
- LOGF(ERROR) << "Failed destroying output buffers.";
+ VLOGF(1) << "Failed destroying output buffers.";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
}
@@ -1635,13 +1646,13 @@
Size visible_size;
bool ret = GetFormatInfo(&format, &visible_size, &again);
if (!ret || again) {
- LOGF(ERROR) << "Couldn't get format information after resolution change";
+ VLOGF(1) << "Couldn't get format information after resolution change";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
}
if (!CreateBuffersForFormat(format, visible_size)) {
- LOGF(ERROR) << "Couldn't reallocate buffers after resolution change";
+ VLOGF(1) << "Couldn't reallocate buffers after resolution change";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
}
@@ -1670,7 +1681,7 @@
}
void V4L2VideoDecodeAccelerator::NotifyError(Error error) {
- VLOGF(2);
+ VLOGF(1);
if (!child_task_runner_->BelongsToCurrentThread()) {
child_task_runner_->PostTask(
@@ -1718,7 +1729,7 @@
*again = true;
return true;
} else {
- PLOGF(ERROR) << "ioctl() failed: VIDIOC_G_FMT";
+ VPLOGF(1) << "ioctl() failed: VIDIOC_G_FMT";
NOTIFY_ERROR(PLATFORM_FAILURE);
return false;
}
@@ -1726,7 +1737,7 @@
// Make sure we are still getting the format we set on initialization.
if (format->fmt.pix_mp.pixelformat != output_format_fourcc_) {
- LOGF(ERROR) << "Unexpected format from G_FMT on output";
+ VLOGF(1) << "Unexpected format from G_FMT on output";
return false;
}
@@ -1763,16 +1774,16 @@
selection_arg.target = V4L2_SEL_TGT_COMPOSE;
if (device_->Ioctl(VIDIOC_G_SELECTION, &selection_arg) == 0) {
- DVLOGF(2) << "VIDIOC_G_SELECTION is supported";
+ VLOGF(2) << "VIDIOC_G_SELECTION is supported";
visible_rect = &selection_arg.r;
} else {
- DVLOGF(2) << "Fallback to VIDIOC_G_CROP";
+ VLOGF(2) << "Fallback to VIDIOC_G_CROP";
struct v4l2_crop crop_arg;
memset(&crop_arg, 0, sizeof(crop_arg));
crop_arg.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
if (device_->Ioctl(VIDIOC_G_CROP, &crop_arg) != 0) {
- PLOGF(ERROR) << "ioctl() VIDIOC_G_CROP failed";
+ VPLOGF(1) << "ioctl() VIDIOC_G_CROP failed";
return coded_size;
}
visible_rect = &crop_arg.c;
@@ -1782,19 +1793,19 @@
visible_rect->height);
VLOGF(2) << "visible rectangle is " << rect.ToString();
if (!Rect(coded_size).Contains(rect)) {
- DLOGF(ERROR) << "visible rectangle " << rect.ToString()
- << " is not inside coded size " << coded_size.ToString();
+ DVLOGF(3) << "visible rectangle " << rect.ToString()
+ << " is not inside coded size " << coded_size.ToString();
return coded_size;
}
if (rect.IsEmpty()) {
- DLOGF(ERROR) << "visible size is empty";
+ VLOGF(1) << "visible size is empty";
return coded_size;
}
// Chrome assume picture frame is coded at (0, 0).
if (rect.x() != 0 || rect.y() != 0) {
- DLOGF(ERROR) << "Unexpected visible rectangle " << rect.ToString()
- << ", top-left is not origin";
+ VLOGF(1) << "Unexpected visible rectangle " << rect.ToString()
+ << ", top-left is not origin";
return coded_size;
}
@@ -1836,7 +1847,7 @@
MAP_SHARED,
buffer.m.planes[0].m.mem_offset);
if (address == MAP_FAILED) {
- PLOGF(ERROR) << "mmap() failed";
+ VPLOGF(1) << "mmap() failed";
return false;
}
input_buffer_map_[i].address = address;
@@ -1913,7 +1924,7 @@
}
if (output_format_fourcc_ == 0) {
- VLOGF(1) << "Image processor not available";
+ VLOGF(2) << "Image processor not available";
return false;
}
VLOGF(2) << "Output format=" << output_format_fourcc_;
@@ -2020,7 +2031,7 @@
reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
reqbufs.memory = V4L2_MEMORY_MMAP;
if (device_->Ioctl(VIDIOC_REQBUFS, &reqbufs) != 0) {
- PLOGF(ERROR) << "ioctl() failed: VIDIOC_REQBUFS";
+ VPLOGF(1) << "ioctl() failed: VIDIOC_REQBUFS";
NOTIFY_ERROR(PLATFORM_FAILURE);
success = false;
}
diff --git a/vda/v4l2_video_decode_accelerator.h b/vda/v4l2_video_decode_accelerator.h
index 9377043..e18cab4 100644
--- a/vda/v4l2_video_decode_accelerator.h
+++ b/vda/v4l2_video_decode_accelerator.h
@@ -5,6 +5,8 @@
// This file contains an implementation of VideoDecodeAccelerator
// that utilizes hardware video decoders, which expose Video4Linux 2 API
// (http://linuxtv.org/downloads/v4l-dvb-apis/).
+// Note: ported from Chromium commit head: 85fdf90
+// Note: image processor is not ported.
#ifndef MEDIA_GPU_V4L2_VIDEO_DECODE_ACCELERATOR_H_
#define MEDIA_GPU_V4L2_VIDEO_DECODE_ACCELERATOR_H_
@@ -93,6 +95,7 @@
void AssignPictureBuffers(const std::vector<PictureBuffer>& buffers) override;
void ImportBufferForPicture(
int32_t picture_buffer_id,
+ VideoPixelFormat pixel_format,
const NativePixmapHandle& native_pixmap_handle) override;
void ReusePictureBuffer(int32_t picture_buffer_id) override;
void Flush() override;
diff --git a/vda/video_codecs.cc b/vda/video_codecs.cc
index 995ee38..61d0708 100644
--- a/vda/video_codecs.cc
+++ b/vda/video_codecs.cc
@@ -1,6 +1,8 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: b03fc92
+// Note: only necessary functions are ported.
#include "video_codecs.h"
diff --git a/vda/video_codecs.h b/vda/video_codecs.h
index 30df7ec..2c88d50 100644
--- a/vda/video_codecs.h
+++ b/vda/video_codecs.h
@@ -1,6 +1,8 @@
// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: b03fc92
+// Note: only necessary functions are ported.
#ifndef VIDEO_CODECS_H_
#define VIDEO_CODECS_H_
diff --git a/vda/video_decode_accelerator.cc b/vda/video_decode_accelerator.cc
index cee4dcc..e74d1ec 100644
--- a/vda/video_decode_accelerator.cc
+++ b/vda/video_decode_accelerator.cc
@@ -1,6 +1,7 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 85fdf90
#include "base/logging.h"
@@ -27,7 +28,7 @@
NOTREACHED() << "By default deferred initialization is not supported.";
}
-VideoDecodeAccelerator::~VideoDecodeAccelerator() {}
+VideoDecodeAccelerator::~VideoDecodeAccelerator() = default;
bool VideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread(
const base::WeakPtr<Client>& decode_client,
@@ -39,6 +40,7 @@
void VideoDecodeAccelerator::ImportBufferForPicture(
int32_t picture_buffer_id,
+ VideoPixelFormat pixel_format,
const NativePixmapHandle& native_pixmap_handle) {
NOTREACHED() << "Buffer import not supported.";
}
@@ -46,14 +48,14 @@
VideoDecodeAccelerator::SupportedProfile::SupportedProfile()
: profile(VIDEO_CODEC_PROFILE_UNKNOWN), encrypted_only(false) {}
-VideoDecodeAccelerator::SupportedProfile::~SupportedProfile() {}
+VideoDecodeAccelerator::SupportedProfile::~SupportedProfile() = default;
VideoDecodeAccelerator::Capabilities::Capabilities() : flags(NO_FLAGS) {}
VideoDecodeAccelerator::Capabilities::Capabilities(const Capabilities& other) =
default;
-VideoDecodeAccelerator::Capabilities::~Capabilities() {}
+VideoDecodeAccelerator::Capabilities::~Capabilities() = default;
std::string VideoDecodeAccelerator::Capabilities::AsHumanReadableString()
const {
diff --git a/vda/video_decode_accelerator.h b/vda/video_decode_accelerator.h
index 6834570..10601be 100644
--- a/vda/video_decode_accelerator.h
+++ b/vda/video_decode_accelerator.h
@@ -1,6 +1,7 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 85fdf90
#ifndef VIDEO_DECODE_ACCELERATOR_H_
#define VIDEO_DECODE_ACCELERATOR_H_
@@ -245,15 +246,20 @@
virtual void AssignPictureBuffers(
const std::vector<PictureBuffer>& buffers) = 0;
- // Imports |native_pixmap_handle| as backing memory for picture buffer
- // associated with |picture_buffer_id|. This can only be be used if the VDA
- // has been Initialize()d with config.output_mode = IMPORT, and should be
- // preceded by a call to AssignPictureBuffers() to set up the number of
- // PictureBuffers and their details.
+ // Imports |gpu_memory_buffer_handle|, pointing to a buffer in |pixel_format|,
+ // as backing memory for picture buffer associated with |picture_buffer_id|.
+ // This can only be be used if the VDA has been Initialize()d with
+ // config.output_mode = IMPORT, and should be preceded by a call to
+ // AssignPictureBuffers() to set up the number of PictureBuffers and their
+ // details.
+ // The |pixel_format| used here may be different from the |pixel_format|
+ // required in ProvidePictureBuffers(). If the buffer cannot be imported an
+ // error should be notified via NotifyError().
// After this call, the VDA becomes the owner of those file descriptors,
// and is responsible for closing it after use, also on import failure.
virtual void ImportBufferForPicture(
int32_t picture_buffer_id,
+ VideoPixelFormat pixel_format,
const NativePixmapHandle& native_pixmap_handle);
// Sends picture buffers to be reused by the decoder. This needs to be called
diff --git a/vda/video_pixel_format.h b/vda/video_pixel_format.h
index d593dad..7f75cc4 100644
--- a/vda/video_pixel_format.h
+++ b/vda/video_pixel_format.h
@@ -1,6 +1,8 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 006301b
+// Note: only necessary functions are ported from video_types.h
#ifndef VIDEO_PIXEL_FORMAT_H_
#define VIDEO_PIXEL_FORMAT_H_
@@ -15,10 +17,14 @@
PIXEL_FORMAT_UNKNOWN = 0, // Unknown or unspecified format value.
PIXEL_FORMAT_I420 =
1, // 12bpp YUV planar 1x1 Y, 2x2 UV samples, a.k.a. YU12.
- PIXEL_FORMAT_YV12 = 2, // 12bpp YVU planar 1x1 Y, 2x2 VU samples.
- PIXEL_FORMAT_YV16 = 3, // 16bpp YVU planar 1x1 Y, 2x1 VU samples.
- PIXEL_FORMAT_YV12A = 4, // 20bpp YUVA planar 1x1 Y, 2x2 VU, 1x1 A samples.
- PIXEL_FORMAT_YV24 = 5, // 24bpp YUV planar, no subsampling.
+
+ // Note: Chrome does not actually support YVU compositing, so you probably
+ // don't actually want to use this. See http://crbug.com/784627.
+ PIXEL_FORMAT_YV12 = 2, // 12bpp YVU planar 1x1 Y, 2x2 VU samples.
+
+ PIXEL_FORMAT_I422 = 3, // 16bpp YUV planar 1x1 Y, 2x1 UV samples.
+ PIXEL_FORMAT_I420A = 4, // 20bpp YUVA planar 1x1 Y, 2x2 UV, 1x1 A samples.
+ PIXEL_FORMAT_I444 = 5, // 24bpp YUV planar, no subsampling.
PIXEL_FORMAT_NV12 =
6, // 12bpp with Y plane followed by a 2x2 interleaved UV plane.
PIXEL_FORMAT_NV21 =
@@ -42,6 +48,8 @@
// Plane size = Row pitch * (((height+31)/32)*32)
PIXEL_FORMAT_MT21 = 15,
+ // The P* in the formats below designates the number of bits per pixel. I.e.
+ // P9 is 9-bits per pixel, P10 is 10-bits per pixel, etc.
PIXEL_FORMAT_YUV420P9 = 16,
PIXEL_FORMAT_YUV420P10 = 17,
PIXEL_FORMAT_YUV422P9 = 18,
@@ -53,15 +61,12 @@
PIXEL_FORMAT_YUV422P12 = 23,
PIXEL_FORMAT_YUV444P12 = 24,
- PIXEL_FORMAT_Y8 = 25, // single 8bpp plane.
+ /* PIXEL_FORMAT_Y8 = 25, Deprecated */
PIXEL_FORMAT_Y16 = 26, // single 16bpp plane.
- PIXEL_FORMAT_I422 =
- 27, // 16bpp YUV planar 1x1 Y, 2x1 UV samples, a.k.a. YU16.
-
// Please update UMA histogram enumeration when adding new formats here.
PIXEL_FORMAT_MAX =
- PIXEL_FORMAT_I422, // Must always be equal to largest entry logged.
+ PIXEL_FORMAT_Y16, // Must always be equal to largest entry logged.
};
} // namespace media
diff --git a/vda/vp8_bool_decoder.cc b/vda/vp8_bool_decoder.cc
index 1d74ced..68f06d0 100644
--- a/vda/vp8_bool_decoder.cc
+++ b/vda/vp8_bool_decoder.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
+// Note: ported from Chromium commit head: 9b6f429
/*
* Copyright (c) 2010, The WebM Project authors. All rights reserved.
diff --git a/vda/vp8_bool_decoder.h b/vda/vp8_bool_decoder.h
index 445fd68..4b8e3a5 100644
--- a/vda/vp8_bool_decoder.h
+++ b/vda/vp8_bool_decoder.h
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
+// Note: ported from Chromium commit head: 1323b9c
/*
* Copyright (c) 2010, The WebM Project authors. All rights reserved.
diff --git a/vda/vp8_decoder.cc b/vda/vp8_decoder.cc
index d9ee6e4..cd2d58b 100644
--- a/vda/vp8_decoder.cc
+++ b/vda/vp8_decoder.cc
@@ -1,6 +1,7 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 7441087
#include "vp8_decoder.h"
@@ -93,6 +94,7 @@
if (!curr_pic_)
return kRanOutOfSurfaces;
+ curr_pic_->visible_rect = Rect(pic_size_);
if (!DecodeAndOutputCurrentFrame())
return kDecodeError;
diff --git a/vda/vp8_decoder.h b/vda/vp8_decoder.h
index 653da40..58211f6 100644
--- a/vda/vp8_decoder.h
+++ b/vda/vp8_decoder.h
@@ -1,6 +1,7 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 60f9667
#ifndef VP8_DECODER_H_
#define VP8_DECODER_H_
diff --git a/vda/vp8_parser.cc b/vda/vp8_parser.cc
index 46eb669..5367545 100644
--- a/vda/vp8_parser.cc
+++ b/vda/vp8_parser.cc
@@ -4,6 +4,8 @@
//
// This file contains an implementation of a VP8 raw stream parser,
// as defined in RFC 6386.
+// Note: ported from Chromium commit head: 2de6929
+
#include "base/logging.h"
#include "vp8_parser.h"
@@ -51,8 +53,7 @@
Vp8Parser::Vp8Parser() : stream_(nullptr), bytes_left_(0) {
}
-Vp8Parser::~Vp8Parser() {
-}
+Vp8Parser::~Vp8Parser() = default;
bool Vp8Parser::ParseFrame(const uint8_t* ptr,
size_t frame_size,
diff --git a/vda/vp8_parser.h b/vda/vp8_parser.h
index ef9326c..c75e6cc 100644
--- a/vda/vp8_parser.h
+++ b/vda/vp8_parser.h
@@ -4,6 +4,7 @@
//
// This file contains an implementation of a VP8 raw stream parser,
// as defined in RFC 6386.
+// Note: ported from Chromium commit head: 1323b9c
#ifndef VP8_PARSER_H_
#define VP8_PARSER_H_
diff --git a/vda/vp8_picture.cc b/vda/vp8_picture.cc
index 59938aa..b9030ce 100644
--- a/vda/vp8_picture.cc
+++ b/vda/vp8_picture.cc
@@ -1,6 +1,7 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 6e70beb
#include "vp8_picture.h"
diff --git a/vda/vp8_picture.h b/vda/vp8_picture.h
index eb253a4..bd04ec7 100644
--- a/vda/vp8_picture.h
+++ b/vda/vp8_picture.h
@@ -1,25 +1,30 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 70340ce
#ifndef VP8_PICTURE_H_
#define VP8_PICTURE_H_
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "rect.h"
namespace media {
class V4L2VP8Picture;
-class VP8Picture : public base::RefCounted<VP8Picture> {
+class VP8Picture : public base::RefCountedThreadSafe<VP8Picture> {
public:
VP8Picture();
virtual V4L2VP8Picture* AsV4L2VP8Picture();
+ // The visible size of picture.
+ Rect visible_rect;
+
protected:
- friend class base::RefCounted<VP8Picture>;
+ friend class base::RefCountedThreadSafe<VP8Picture>;
virtual ~VP8Picture();
DISALLOW_COPY_AND_ASSIGN(VP8Picture);
diff --git a/vda/vp9_bool_decoder.cc b/vda/vp9_bool_decoder.cc
index bf227b2..1d2b6f4 100644
--- a/vda/vp9_bool_decoder.cc
+++ b/vda/vp9_bool_decoder.cc
@@ -1,6 +1,7 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 1323b9c
#include "vp9_bool_decoder.h"
@@ -35,9 +36,9 @@
};
} // namespace
-Vp9BoolDecoder::Vp9BoolDecoder() {}
+Vp9BoolDecoder::Vp9BoolDecoder() = default;
-Vp9BoolDecoder::~Vp9BoolDecoder() {}
+Vp9BoolDecoder::~Vp9BoolDecoder() = default;
// 9.2.1 Initialization process for Boolean decoder
bool Vp9BoolDecoder::Initialize(const uint8_t* data, size_t size) {
diff --git a/vda/vp9_bool_decoder.h b/vda/vp9_bool_decoder.h
index 3862e51..50c386f 100644
--- a/vda/vp9_bool_decoder.h
+++ b/vda/vp9_bool_decoder.h
@@ -1,6 +1,7 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: e5a9a62
#ifndef VP9_BOOL_DECODER_H_
#define VP9_BOOL_DECODER_H_
diff --git a/vda/vp9_compressed_header_parser.cc b/vda/vp9_compressed_header_parser.cc
index d5ee772..524472f 100644
--- a/vda/vp9_compressed_header_parser.cc
+++ b/vda/vp9_compressed_header_parser.cc
@@ -1,6 +1,7 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 2de6929
#include "vp9_compressed_header_parser.h"
@@ -59,7 +60,7 @@
} // namespace
-Vp9CompressedHeaderParser::Vp9CompressedHeaderParser() {}
+Vp9CompressedHeaderParser::Vp9CompressedHeaderParser() = default;
// 6.3.1 Tx mode syntax
void Vp9CompressedHeaderParser::ReadTxMode(Vp9FrameHeader* fhdr) {
diff --git a/vda/vp9_compressed_header_parser.h b/vda/vp9_compressed_header_parser.h
index 032a880..5f5ff56 100644
--- a/vda/vp9_compressed_header_parser.h
+++ b/vda/vp9_compressed_header_parser.h
@@ -1,6 +1,7 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: e5a9a62
#ifndef VP9_COMPRESSED_HEADER_PARSER_H_
#define VP9_COMPRESSED_HEADER_PARSER_H_
diff --git a/vda/vp9_decoder.cc b/vda/vp9_decoder.cc
index 2ea6d16..d8af03d 100644
--- a/vda/vp9_decoder.cc
+++ b/vda/vp9_decoder.cc
@@ -1,7 +1,9 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 7441087
+#include "rect.h"
#include "vp9_decoder.h"
#include <memory>
@@ -136,6 +138,18 @@
if (!pic)
return kRanOutOfSurfaces;
+ Rect new_render_rect(curr_frame_hdr_->render_width,
+ curr_frame_hdr_->render_height);
+ // For safety, check the validity of render size or leave it as (0, 0).
+ if (!Rect(pic_size_).Contains(new_render_rect)) {
+ DVLOG(1) << "Render size exceeds picture size. render size: "
+ << new_render_rect.ToString()
+ << ", picture size: " << pic_size_.ToString();
+ new_render_rect = Rect();
+ }
+ DVLOG(2) << "Render resolution: " << new_render_rect.ToString();
+
+ pic->visible_rect = new_render_rect;
pic->frame_hdr.reset(curr_frame_hdr_.release());
if (!DecodeAndOutputPicture(pic)) {
diff --git a/vda/vp9_decoder.h b/vda/vp9_decoder.h
index 77a8d88..cdbcd69 100644
--- a/vda/vp9_decoder.h
+++ b/vda/vp9_decoder.h
@@ -1,6 +1,7 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 77118c9
#ifndef VP9_DECODER_H_
#define VP9_DECODER_H_
diff --git a/vda/vp9_parser.cc b/vda/vp9_parser.cc
index de51c7b..bbd90b9 100644
--- a/vda/vp9_parser.cc
+++ b/vda/vp9_parser.cc
@@ -8,6 +8,7 @@
// 1 something wrong in bitstream
// 2 parsing steps
// 3 parsed values (selected)
+// Note: ported from Chromium commit head: 2de6929
#include "vp9_parser.h"
@@ -22,6 +23,133 @@
namespace media {
+namespace {
+
+// Coefficients extracted verbatim from "VP9 Bitstream & Decoding Process
+// Specification" Version 0.6, Sec 8.6.1 Dequantization functions, see:
+// https://www.webmproject.org/vp9/#draft-vp9-bitstream-and-decoding-process-specification
+constexpr size_t kQIndexRange = 256;
+// clang-format off
+// libva is the only user of high bit depth VP9 formats and only supports
+// 10 bits per component, see https://github.com/01org/libva/issues/137.
+// TODO(mcasas): Add the 12 bit versions of these tables.
+const int16_t kDcQLookup[][kQIndexRange] = {
+ {
+ 4, 8, 8, 9, 10, 11, 12, 12, 13, 14, 15, 16,
+ 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26, 26,
+ 27, 28, 29, 30, 31, 32, 32, 33, 34, 35, 36, 37,
+ 38, 38, 39, 40, 41, 42, 43, 43, 44, 45, 46, 47,
+ 48, 48, 49, 50, 51, 52, 53, 53, 54, 55, 56, 57,
+ 57, 58, 59, 60, 61, 62, 62, 63, 64, 65, 66, 66,
+ 67, 68, 69, 70, 70, 71, 72, 73, 74, 74, 75, 76,
+ 77, 78, 78, 79, 80, 81, 81, 82, 83, 84, 85, 85,
+ 87, 88, 90, 92, 93, 95, 96, 98, 99, 101, 102, 104,
+ 105, 107, 108, 110, 111, 113, 114, 116, 117, 118, 120, 121,
+ 123, 125, 127, 129, 131, 134, 136, 138, 140, 142, 144, 146,
+ 148, 150, 152, 154, 156, 158, 161, 164, 166, 169, 172, 174,
+ 177, 180, 182, 185, 187, 190, 192, 195, 199, 202, 205, 208,
+ 211, 214, 217, 220, 223, 226, 230, 233, 237, 240, 243, 247,
+ 250, 253, 257, 261, 265, 269, 272, 276, 280, 284, 288, 292,
+ 296, 300, 304, 309, 313, 317, 322, 326, 330, 335, 340, 344,
+ 349, 354, 359, 364, 369, 374, 379, 384, 389, 395, 400, 406,
+ 411, 417, 423, 429, 435, 441, 447, 454, 461, 467, 475, 482,
+ 489, 497, 505, 513, 522, 530, 539, 549, 559, 569, 579, 590,
+ 602, 614, 626, 640, 654, 668, 684, 700, 717, 736, 755, 775,
+ 796, 819, 843, 869, 896, 925, 955, 988, 1022, 1058, 1098, 1139,
+ 1184, 1232, 1282, 1336,
+ },
+ {
+ 4, 9, 10, 13, 15, 17, 20, 22, 25, 28, 31, 34,
+ 37, 40, 43, 47, 50, 53, 57, 60, 64, 68, 71, 75,
+ 78, 82, 86, 90, 93, 97, 101, 105, 109, 113, 116, 120,
+ 124, 128, 132, 136, 140, 143, 147, 151, 155, 159, 163, 166,
+ 170, 174, 178, 182, 185, 189, 193, 197, 200, 204, 208, 212,
+ 215, 219, 223, 226, 230, 233, 237, 241, 244, 248, 251, 255,
+ 259, 262, 266, 269, 273, 276, 280, 283, 287, 290, 293, 297,
+ 300, 304, 307, 310, 314, 317, 321, 324, 327, 331, 334, 337,
+ 343, 350, 356, 362, 369, 375, 381, 387, 394, 400, 406, 412,
+ 418, 424, 430, 436, 442, 448, 454, 460, 466, 472, 478, 484,
+ 490, 499, 507, 516, 525, 533, 542, 550, 559, 567, 576, 584,
+ 592, 601, 609, 617, 625, 634, 644, 655, 666, 676, 687, 698,
+ 708, 718, 729, 739, 749, 759, 770, 782, 795, 807, 819, 831,
+ 844, 856, 868, 880, 891, 906, 920, 933, 947, 961, 975, 988,
+ 1001, 1015, 1030, 1045, 1061, 1076, 1090, 1105, 1120, 1137, 1153, 1170,
+ 1186, 1202, 1218, 1236, 1253, 1271, 1288, 1306, 1323, 1342, 1361, 1379,
+ 1398, 1416, 1436, 1456, 1476, 1496, 1516, 1537, 1559, 1580, 1601, 1624,
+ 1647, 1670, 1692, 1717, 1741, 1766, 1791, 1817, 1844, 1871, 1900, 1929,
+ 1958, 1990, 2021, 2054, 2088, 2123, 2159, 2197, 2236, 2276, 2319, 2363,
+ 2410, 2458, 2508, 2561, 2616, 2675, 2737, 2802, 2871, 2944, 3020, 3102,
+ 3188, 3280, 3375, 3478, 3586, 3702, 3823, 3953, 4089, 4236, 4394, 4559,
+ 4737, 4929, 5130, 5347
+ }
+};
+
+const int16_t kAcQLookup[][kQIndexRange] = {
+ {
+ 4, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
+ 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
+ 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126,
+ 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150,
+ 152, 155, 158, 161, 164, 167, 170, 173, 176, 179, 182, 185,
+ 188, 191, 194, 197, 200, 203, 207, 211, 215, 219, 223, 227,
+ 231, 235, 239, 243, 247, 251, 255, 260, 265, 270, 275, 280,
+ 285, 290, 295, 300, 305, 311, 317, 323, 329, 335, 341, 347,
+ 353, 359, 366, 373, 380, 387, 394, 401, 408, 416, 424, 432,
+ 440, 448, 456, 465, 474, 483, 492, 501, 510, 520, 530, 540,
+ 550, 560, 571, 582, 593, 604, 615, 627, 639, 651, 663, 676,
+ 689, 702, 715, 729, 743, 757, 771, 786, 801, 816, 832, 848,
+ 864, 881, 898, 915, 933, 951, 969, 988, 1007, 1026, 1046, 1066,
+ 1087, 1108, 1129, 1151, 1173, 1196, 1219, 1243, 1267, 1292, 1317, 1343,
+ 1369, 1396, 1423, 1451, 1479, 1508, 1537, 1567, 1597, 1628, 1660, 1692,
+ 1725, 1759, 1793, 1828,
+ },
+ {
+ 4, 9, 11, 13, 16, 18, 21, 24, 27, 30, 33, 37,
+ 40, 44, 48, 51, 55, 59, 63, 67, 71, 75, 79, 83,
+ 88, 92, 96, 100, 105, 109, 114, 118, 122, 127, 131, 136,
+ 140, 145, 149, 154, 158, 163, 168, 172, 177, 181, 186, 190,
+ 195, 199, 204, 208, 213, 217, 222, 226, 231, 235, 240, 244,
+ 249, 253, 258, 262, 267, 271, 275, 280, 284, 289, 293, 297,
+ 302, 306, 311, 315, 319, 324, 328, 332, 337, 341, 345, 349,
+ 354, 358, 362, 367, 371, 375, 379, 384, 388, 392, 396, 401,
+ 409, 417, 425, 433, 441, 449, 458, 466, 474, 482, 490, 498,
+ 506, 514, 523, 531, 539, 547, 555, 563, 571, 579, 588, 596,
+ 604, 616, 628, 640, 652, 664, 676, 688, 700, 713, 725, 737,
+ 749, 761, 773, 785, 797, 809, 825, 841, 857, 873, 889, 905,
+ 922, 938, 954, 970, 986, 1002, 1018, 1038, 1058, 1078, 1098, 1118,
+ 1138, 1158, 1178, 1198, 1218, 1242, 1266, 1290, 1314, 1338, 1362, 1386,
+ 1411, 1435, 1463, 1491, 1519, 1547, 1575, 1603, 1631, 1663, 1695, 1727,
+ 1759, 1791, 1823, 1859, 1895, 1931, 1967, 2003, 2039, 2079, 2119, 2159,
+ 2199, 2239, 2283, 2327, 2371, 2415, 2459, 2507, 2555, 2603, 2651, 2703,
+ 2755, 2807, 2859, 2915, 2971, 3027, 3083, 3143, 3203, 3263, 3327, 3391,
+ 3455, 3523, 3591, 3659, 3731, 3803, 3876, 3952, 4028, 4104, 4184, 4264,
+ 4348, 4432, 4516, 4604, 4692, 4784, 4876, 4972, 5068, 5168, 5268, 5372,
+ 5476, 5584, 5692, 5804, 5916, 6032, 6148, 6268, 6388, 6512, 6640, 6768,
+ 6900, 7036, 7172, 7312
+ }
+};
+// clang-format on
+
+static_assert(arraysize(kDcQLookup[0]) == arraysize(kAcQLookup[0]),
+ "quantizer lookup arrays of incorrect size");
+
+size_t ClampQ(size_t q) {
+ return std::min(q, kQIndexRange - 1);
+}
+
+int ClampLf(int lf) {
+ const int kMaxLoopFilterLevel = 63;
+ return std::min(std::max(0, lf), kMaxLoopFilterLevel);
+}
+
+} // namespace
+
bool Vp9FrameHeader::IsKeyframe() const {
// When show_existing_frame is true, the frame header does not precede an
// actual frame to be decoded, so frame_type does not apply (and is not read
@@ -107,7 +235,7 @@
Vp9Parser::Context::Vp9FrameContextManager::Vp9FrameContextManager()
: weak_ptr_factory_(this) {}
-Vp9Parser::Context::Vp9FrameContextManager::~Vp9FrameContextManager() {}
+Vp9Parser::Context::Vp9FrameContextManager::~Vp9FrameContextManager() = default;
const Vp9FrameContext&
Vp9Parser::Context::Vp9FrameContextManager::frame_context() const {
@@ -205,7 +333,7 @@
Reset();
}
-Vp9Parser::~Vp9Parser() {}
+Vp9Parser::~Vp9Parser() = default;
void Vp9Parser::SetStream(const uint8_t* stream, off_t stream_size) {
DCHECK(stream);
@@ -223,14 +351,106 @@
context_.Reset();
}
+bool Vp9Parser::ParseUncompressedHeader(const FrameInfo& frame_info,
+ Vp9FrameHeader* fhdr,
+ Result* result) {
+ memset(&curr_frame_header_, 0, sizeof(curr_frame_header_));
+ *result = kInvalidStream;
+
+ Vp9UncompressedHeaderParser uncompressed_parser(&context_);
+ if (!uncompressed_parser.Parse(frame_info.ptr, frame_info.size,
+ &curr_frame_header_)) {
+ *result = kInvalidStream;
+ return true;
+ }
+
+ if (curr_frame_header_.header_size_in_bytes == 0) {
+ // Verify padding bits are zero.
+ for (off_t i = curr_frame_header_.uncompressed_header_size;
+ i < frame_info.size; i++) {
+ if (frame_info.ptr[i] != 0) {
+ DVLOG(1) << "Padding bits are not zeros.";
+ *result = kInvalidStream;
+ return true;
+ }
+ }
+ *fhdr = curr_frame_header_;
+ *result = kOk;
+ return true;
+ }
+ if (curr_frame_header_.uncompressed_header_size +
+ curr_frame_header_.header_size_in_bytes >
+ base::checked_cast<size_t>(frame_info.size)) {
+ DVLOG(1) << "header_size_in_bytes="
+ << curr_frame_header_.header_size_in_bytes
+ << " is larger than bytes left in buffer: "
+ << frame_info.size - curr_frame_header_.uncompressed_header_size;
+ *result = kInvalidStream;
+ return true;
+ }
+
+ return false;
+}
+
+bool Vp9Parser::ParseCompressedHeader(const FrameInfo& frame_info,
+ Result* result) {
+ *result = kInvalidStream;
+ size_t frame_context_idx = curr_frame_header_.frame_context_idx;
+ const Context::Vp9FrameContextManager& context_to_load =
+ context_.frame_context_managers_[frame_context_idx];
+ if (!context_to_load.initialized()) {
+ // 8.2 Frame order constraints
+ // must load an initialized set of probabilities.
+ DVLOG(1) << "loading uninitialized frame context, index="
+ << frame_context_idx;
+ *result = kInvalidStream;
+ return true;
+ }
+ if (context_to_load.needs_client_update()) {
+ DVLOG(3) << "waiting frame_context_idx=" << frame_context_idx
+ << " to update";
+ curr_frame_info_ = frame_info;
+ *result = kAwaitingRefresh;
+ return true;
+ }
+ curr_frame_header_.initial_frame_context = curr_frame_header_.frame_context =
+ context_to_load.frame_context();
+
+ Vp9CompressedHeaderParser compressed_parser;
+ if (!compressed_parser.Parse(
+ frame_info.ptr + curr_frame_header_.uncompressed_header_size,
+ curr_frame_header_.header_size_in_bytes, &curr_frame_header_)) {
+ *result = kInvalidStream;
+ return true;
+ }
+
+ if (curr_frame_header_.refresh_frame_context) {
+ // In frame parallel mode, we can refresh the context without decoding
+ // tile data.
+ if (curr_frame_header_.frame_parallel_decoding_mode) {
+ context_.UpdateFrameContext(frame_context_idx,
+ curr_frame_header_.frame_context);
+ } else {
+ context_.MarkFrameContextForUpdate(frame_context_idx);
+ }
+ }
+ return false;
+}
+
Vp9Parser::Result Vp9Parser::ParseNextFrame(Vp9FrameHeader* fhdr) {
DCHECK(fhdr);
DVLOG(2) << "ParseNextFrame";
+ FrameInfo frame_info;
+ Result result;
// If |curr_frame_info_| is valid, uncompressed header was parsed into
// |curr_frame_header_| and we are awaiting context update to proceed with
// compressed header parsing.
- if (!curr_frame_info_.IsValid()) {
+ if (curr_frame_info_.IsValid()) {
+ DCHECK(parsing_compressed_header_);
+ frame_info = curr_frame_info_;
+ curr_frame_info_.Reset();
+ } else {
if (frames_.empty()) {
// No frames to be decoded, if there is no more stream, request more.
if (!stream_)
@@ -244,85 +464,26 @@
}
}
- curr_frame_info_ = frames_.front();
+ frame_info = frames_.front();
frames_.pop_front();
- memset(&curr_frame_header_, 0, sizeof(curr_frame_header_));
-
- Vp9UncompressedHeaderParser uncompressed_parser(&context_);
- if (!uncompressed_parser.Parse(curr_frame_info_.ptr, curr_frame_info_.size,
- &curr_frame_header_))
- return kInvalidStream;
-
- if (curr_frame_header_.header_size_in_bytes == 0) {
- // Verify padding bits are zero.
- for (off_t i = curr_frame_header_.uncompressed_header_size;
- i < curr_frame_info_.size; i++) {
- if (curr_frame_info_.ptr[i] != 0) {
- DVLOG(1) << "Padding bits are not zeros.";
- return kInvalidStream;
- }
- }
- *fhdr = curr_frame_header_;
- curr_frame_info_.Reset();
- return kOk;
- }
- if (curr_frame_header_.uncompressed_header_size +
- curr_frame_header_.header_size_in_bytes >
- base::checked_cast<size_t>(curr_frame_info_.size)) {
- DVLOG(1) << "header_size_in_bytes="
- << curr_frame_header_.header_size_in_bytes
- << " is larger than bytes left in buffer: "
- << curr_frame_info_.size -
- curr_frame_header_.uncompressed_header_size;
- return kInvalidStream;
- }
+ if (ParseUncompressedHeader(frame_info, fhdr, &result))
+ return result;
}
if (parsing_compressed_header_) {
- size_t frame_context_idx = curr_frame_header_.frame_context_idx;
- const Context::Vp9FrameContextManager& context_to_load =
- context_.frame_context_managers_[frame_context_idx];
- if (!context_to_load.initialized()) {
- // 8.2 Frame order constraints
- // must load an initialized set of probabilities.
- DVLOG(1) << "loading uninitialized frame context, index="
- << frame_context_idx;
- return kInvalidStream;
- }
- if (context_to_load.needs_client_update()) {
- DVLOG(3) << "waiting frame_context_idx=" << frame_context_idx
- << " to update";
- return kAwaitingRefresh;
- }
- curr_frame_header_.initial_frame_context =
- curr_frame_header_.frame_context = context_to_load.frame_context();
-
- Vp9CompressedHeaderParser compressed_parser;
- if (!compressed_parser.Parse(
- curr_frame_info_.ptr + curr_frame_header_.uncompressed_header_size,
- curr_frame_header_.header_size_in_bytes, &curr_frame_header_)) {
- return kInvalidStream;
- }
-
- if (curr_frame_header_.refresh_frame_context) {
- // In frame parallel mode, we can refresh the context without decoding
- // tile data.
- if (curr_frame_header_.frame_parallel_decoding_mode) {
- context_.UpdateFrameContext(frame_context_idx,
- curr_frame_header_.frame_context);
- } else {
- context_.MarkFrameContextForUpdate(frame_context_idx);
- }
+ if (ParseCompressedHeader(frame_info, &result)) {
+ DCHECK(result != kAwaitingRefresh || curr_frame_info_.IsValid());
+ return result;
}
}
- SetupSegmentationDequant();
+ if (!SetupSegmentationDequant())
+ return kInvalidStream;
SetupLoopFilter();
UpdateSlots();
*fhdr = curr_frame_header_;
- curr_frame_info_.Reset();
return kOk;
}
@@ -398,86 +559,6 @@
return frames;
}
-// 8.6.1
-const size_t QINDEX_RANGE = 256;
-const int16_t kDcQLookup[QINDEX_RANGE] = {
- 4, 8, 8, 9, 10, 11, 12, 12,
- 13, 14, 15, 16, 17, 18, 19, 19,
- 20, 21, 22, 23, 24, 25, 26, 26,
- 27, 28, 29, 30, 31, 32, 32, 33,
- 34, 35, 36, 37, 38, 38, 39, 40,
- 41, 42, 43, 43, 44, 45, 46, 47,
- 48, 48, 49, 50, 51, 52, 53, 53,
- 54, 55, 56, 57, 57, 58, 59, 60,
- 61, 62, 62, 63, 64, 65, 66, 66,
- 67, 68, 69, 70, 70, 71, 72, 73,
- 74, 74, 75, 76, 77, 78, 78, 79,
- 80, 81, 81, 82, 83, 84, 85, 85,
- 87, 88, 90, 92, 93, 95, 96, 98,
- 99, 101, 102, 104, 105, 107, 108, 110,
- 111, 113, 114, 116, 117, 118, 120, 121,
- 123, 125, 127, 129, 131, 134, 136, 138,
- 140, 142, 144, 146, 148, 150, 152, 154,
- 156, 158, 161, 164, 166, 169, 172, 174,
- 177, 180, 182, 185, 187, 190, 192, 195,
- 199, 202, 205, 208, 211, 214, 217, 220,
- 223, 226, 230, 233, 237, 240, 243, 247,
- 250, 253, 257, 261, 265, 269, 272, 276,
- 280, 284, 288, 292, 296, 300, 304, 309,
- 313, 317, 322, 326, 330, 335, 340, 344,
- 349, 354, 359, 364, 369, 374, 379, 384,
- 389, 395, 400, 406, 411, 417, 423, 429,
- 435, 441, 447, 454, 461, 467, 475, 482,
- 489, 497, 505, 513, 522, 530, 539, 549,
- 559, 569, 579, 590, 602, 614, 626, 640,
- 654, 668, 684, 700, 717, 736, 755, 775,
- 796, 819, 843, 869, 896, 925, 955, 988,
- 1022, 1058, 1098, 1139, 1184, 1232, 1282, 1336,
-};
-
-const int16_t kAcQLookup[QINDEX_RANGE] = {
- 4, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22,
- 23, 24, 25, 26, 27, 28, 29, 30,
- 31, 32, 33, 34, 35, 36, 37, 38,
- 39, 40, 41, 42, 43, 44, 45, 46,
- 47, 48, 49, 50, 51, 52, 53, 54,
- 55, 56, 57, 58, 59, 60, 61, 62,
- 63, 64, 65, 66, 67, 68, 69, 70,
- 71, 72, 73, 74, 75, 76, 77, 78,
- 79, 80, 81, 82, 83, 84, 85, 86,
- 87, 88, 89, 90, 91, 92, 93, 94,
- 95, 96, 97, 98, 99, 100, 101, 102,
- 104, 106, 108, 110, 112, 114, 116, 118,
- 120, 122, 124, 126, 128, 130, 132, 134,
- 136, 138, 140, 142, 144, 146, 148, 150,
- 152, 155, 158, 161, 164, 167, 170, 173,
- 176, 179, 182, 185, 188, 191, 194, 197,
- 200, 203, 207, 211, 215, 219, 223, 227,
- 231, 235, 239, 243, 247, 251, 255, 260,
- 265, 270, 275, 280, 285, 290, 295, 300,
- 305, 311, 317, 323, 329, 335, 341, 347,
- 353, 359, 366, 373, 380, 387, 394, 401,
- 408, 416, 424, 432, 440, 448, 456, 465,
- 474, 483, 492, 501, 510, 520, 530, 540,
- 550, 560, 571, 582, 593, 604, 615, 627,
- 639, 651, 663, 676, 689, 702, 715, 729,
- 743, 757, 771, 786, 801, 816, 832, 848,
- 864, 881, 898, 915, 933, 951, 969, 988,
- 1007, 1026, 1046, 1066, 1087, 1108, 1129, 1151,
- 1173, 1196, 1219, 1243, 1267, 1292, 1317, 1343,
- 1369, 1396, 1423, 1451, 1479, 1508, 1537, 1567,
- 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828,
-};
-
-static_assert(arraysize(kDcQLookup) == arraysize(kAcQLookup),
- "quantizer lookup arrays of incorrect size");
-
-static size_t ClampQ(size_t q) {
- return std::min(std::max(static_cast<size_t>(0), q),
- arraysize(kDcQLookup) - 1);
-}
-
// 8.6.1 Dequantization functions
size_t Vp9Parser::GetQIndex(const Vp9QuantizationParams& quant,
size_t segid) const {
@@ -497,40 +578,40 @@
}
// 8.6.1 Dequantization functions
-void Vp9Parser::SetupSegmentationDequant() {
+bool Vp9Parser::SetupSegmentationDequant() {
const Vp9QuantizationParams& quant = curr_frame_header_.quant_params;
Vp9SegmentationParams& segmentation = context_.segmentation_;
- DLOG_IF(ERROR, curr_frame_header_.bit_depth > 8)
- << "bit_depth > 8 is not supported "
- "yet, kDcQLookup and kAcQLookup "
- "need extended";
+ if (curr_frame_header_.bit_depth > 10) {
+ DLOG(ERROR) << "bit_depth > 10 is not supported yet, kDcQLookup and "
+ "kAcQLookup need to be extended";
+ return false;
+ }
+ const size_t bit_depth_index = (curr_frame_header_.bit_depth == 8) ? 0 : 1;
+
if (segmentation.enabled) {
for (size_t i = 0; i < Vp9SegmentationParams::kNumSegments; ++i) {
const size_t q_index = GetQIndex(quant, i);
segmentation.y_dequant[i][0] =
- kDcQLookup[ClampQ(q_index + quant.delta_q_y_dc)];
- segmentation.y_dequant[i][1] = kAcQLookup[ClampQ(q_index)];
+ kDcQLookup[bit_depth_index][ClampQ(q_index + quant.delta_q_y_dc)];
+ segmentation.y_dequant[i][1] =
+ kAcQLookup[bit_depth_index][ClampQ(q_index)];
segmentation.uv_dequant[i][0] =
- kDcQLookup[ClampQ(q_index + quant.delta_q_uv_dc)];
+ kDcQLookup[bit_depth_index][ClampQ(q_index + quant.delta_q_uv_dc)];
segmentation.uv_dequant[i][1] =
- kAcQLookup[ClampQ(q_index + quant.delta_q_uv_ac)];
+ kAcQLookup[bit_depth_index][ClampQ(q_index + quant.delta_q_uv_ac)];
}
} else {
const size_t q_index = quant.base_q_idx;
segmentation.y_dequant[0][0] =
- kDcQLookup[ClampQ(q_index + quant.delta_q_y_dc)];
- segmentation.y_dequant[0][1] = kAcQLookup[ClampQ(q_index)];
+ kDcQLookup[bit_depth_index][ClampQ(q_index + quant.delta_q_y_dc)];
+ segmentation.y_dequant[0][1] = kAcQLookup[bit_depth_index][ClampQ(q_index)];
segmentation.uv_dequant[0][0] =
- kDcQLookup[ClampQ(q_index + quant.delta_q_uv_dc)];
+ kDcQLookup[bit_depth_index][ClampQ(q_index + quant.delta_q_uv_dc)];
segmentation.uv_dequant[0][1] =
- kAcQLookup[ClampQ(q_index + quant.delta_q_uv_ac)];
+ kAcQLookup[bit_depth_index][ClampQ(q_index + quant.delta_q_uv_ac)];
}
-}
-
-static int ClampLf(int lf) {
- const int kMaxLoopFilterLevel = 63;
- return std::min(std::max(0, lf), kMaxLoopFilterLevel);
+ return true;
}
// 8.8.1 Loop filter frame init process
diff --git a/vda/vp9_parser.h b/vda/vp9_parser.h
index c6e1d9f..ab1fa57 100644
--- a/vda/vp9_parser.h
+++ b/vda/vp9_parser.h
@@ -9,6 +9,7 @@
//
// See media::VP9Decoder for example usage.
//
+// Note: ported from Chromium commit head: ec6c6e0
#ifndef VP9_PARSER_H_
#define VP9_PARSER_H_
@@ -404,8 +405,22 @@
std::deque<FrameInfo> ParseSuperframe();
+ // Returns true and populates |result| with the parsing result if parsing of
+ // current frame is finished (possibly unsuccessfully). |fhdr| will only be
+ // populated and valid if |result| is kOk. Otherwise return false, indicating
+ // that the compressed header must be parsed next.
+ bool ParseUncompressedHeader(const FrameInfo& frame_info,
+ Vp9FrameHeader* fhdr,
+ Result* result);
+
+ // Returns true if parsing of current frame is finished and |result| will be
+ // populated with value of parsing result. Otherwise, needs to continue setup
+ // current frame.
+ bool ParseCompressedHeader(const FrameInfo& frame_info, Result* result);
+
size_t GetQIndex(const Vp9QuantizationParams& quant, size_t segid) const;
- void SetupSegmentationDequant();
+ // Returns true if the setup succeeded.
+ bool SetupSegmentationDequant();
void SetupLoopFilter();
void UpdateSlots();
@@ -415,7 +430,7 @@
// Remaining bytes in stream_.
off_t bytes_left_;
- bool parsing_compressed_header_;
+ const bool parsing_compressed_header_;
// FrameInfo for the remaining frames in the current superframe to be parsed.
std::deque<FrameInfo> frames_;
diff --git a/vda/vp9_picture.cc b/vda/vp9_picture.cc
index a99427f..df2c3b0 100644
--- a/vda/vp9_picture.cc
+++ b/vda/vp9_picture.cc
@@ -1,6 +1,7 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 6e70beb
#include "vp9_picture.h"
diff --git a/vda/vp9_picture.h b/vda/vp9_picture.h
index 23e299b..efff37b 100644
--- a/vda/vp9_picture.h
+++ b/vda/vp9_picture.h
@@ -1,6 +1,7 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 70340ce
#ifndef VP9_PICTURE_H_
#define VP9_PICTURE_H_
@@ -9,13 +10,14 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "rect.h"
#include "vp9_parser.h"
namespace media {
class V4L2VP9Picture;
-class VP9Picture : public base::RefCounted<VP9Picture> {
+class VP9Picture : public base::RefCountedThreadSafe<VP9Picture> {
public:
VP9Picture();
@@ -23,8 +25,13 @@
std::unique_ptr<Vp9FrameHeader> frame_hdr;
+ // The visible size of picture. This could be either parsed from frame
+ // header, or set to Rect(0, 0) for indicating invalid values or
+ // not available.
+ Rect visible_rect;
+
protected:
- friend class base::RefCounted<VP9Picture>;
+ friend class base::RefCountedThreadSafe<VP9Picture>;
virtual ~VP9Picture();
DISALLOW_COPY_AND_ASSIGN(VP9Picture);
diff --git a/vda/vp9_raw_bits_reader.cc b/vda/vp9_raw_bits_reader.cc
index 7cad4d9..dea06e0 100644
--- a/vda/vp9_raw_bits_reader.cc
+++ b/vda/vp9_raw_bits_reader.cc
@@ -1,6 +1,7 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: 2de6929
#include "vp9_raw_bits_reader.h"
@@ -13,7 +14,7 @@
Vp9RawBitsReader::Vp9RawBitsReader() : valid_(true) {}
-Vp9RawBitsReader::~Vp9RawBitsReader() {}
+Vp9RawBitsReader::~Vp9RawBitsReader() = default;
void Vp9RawBitsReader::Initialize(const uint8_t* data, size_t size) {
DCHECK(data);
diff --git a/vda/vp9_raw_bits_reader.h b/vda/vp9_raw_bits_reader.h
index 9f112b8..04ad413 100644
--- a/vda/vp9_raw_bits_reader.h
+++ b/vda/vp9_raw_bits_reader.h
@@ -1,6 +1,7 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: e5a9a62
#ifndef VP9_RAW_BITS_READER_H_
#define VP9_RAW_BITS_READER_H_
diff --git a/vda/vp9_uncompressed_header_parser.cc b/vda/vp9_uncompressed_header_parser.cc
index 067b40c..f6dc2eb 100644
--- a/vda/vp9_uncompressed_header_parser.cc
+++ b/vda/vp9_uncompressed_header_parser.cc
@@ -1,6 +1,7 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: f06caa0
#include "vp9_uncompressed_header_parser.h"
@@ -789,7 +790,7 @@
for (size_t i = 0; i < Vp9LoopFilterParams::kNumModeDeltas; i++) {
loop_filter.update_mode_deltas[i] = reader_.ReadBool();
if (loop_filter.update_mode_deltas[i])
- loop_filter.mode_deltas[i] = reader_.ReadLiteral(6);
+ loop_filter.mode_deltas[i] = reader_.ReadSignedLiteral(6);
}
}
}
diff --git a/vda/vp9_uncompressed_header_parser.h b/vda/vp9_uncompressed_header_parser.h
index 655ba38..6780d38 100644
--- a/vda/vp9_uncompressed_header_parser.h
+++ b/vda/vp9_uncompressed_header_parser.h
@@ -1,6 +1,7 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: ported from Chromium commit head: e5a9a62
#ifndef VP9_UNCOMPRESSED_HEADER_PARSER_H_
#define VP9_UNCOMPRESSED_HEADER_PARSER_H_
diff --git a/vndk/C2VDAStore.cpp b/vndk/C2VDAStore.cpp
index 8c57e88..42ce6df 100644
--- a/vndk/C2VDAStore.cpp
+++ b/vndk/C2VDAStore.cpp
@@ -94,7 +94,9 @@
#ifdef ANDROID_VERSION_NYC
allocator = std::make_shared<C2AllocatorCrosGralloc>();
#else
- allocator = std::make_shared<C2AllocatorGralloc>();
+ // TODO is this supposed to be the platform's gralloc allocator?
+ // perhaps extend C2PlatformAllocatorStore
+ allocator = std::make_shared<C2AllocatorGralloc>(C2AllocatorStore::VENDOR_START);
#endif
mCrosGrallocAllocator = allocator;
}