vpx_video_decoder.cc 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "media/filters/vpx_video_decoder.h"
  5. #include <stddef.h>
  6. #include <stdint.h>
  7. #include <algorithm>
  8. #include <string>
  9. #include <vector>
  10. #include "base/bind.h"
  11. #include "base/callback_helpers.h"
  12. #include "base/feature_list.h"
  13. #include "base/location.h"
  14. #include "base/logging.h"
  15. #include "base/metrics/histogram_macros.h"
  16. #include "base/sys_byteorder.h"
  17. #include "base/trace_event/trace_event.h"
  18. #include "media/base/bind_to_current_loop.h"
  19. #include "media/base/decoder_buffer.h"
  20. #include "media/base/limits.h"
  21. #include "media/base/media_switches.h"
  22. #include "media/base/video_aspect_ratio.h"
  23. #include "media/filters/frame_buffer_pool.h"
  24. #include "third_party/libvpx/source/libvpx/vpx/vp8dx.h"
  25. #include "third_party/libvpx/source/libvpx/vpx/vpx_decoder.h"
  26. #include "third_party/libvpx/source/libvpx/vpx/vpx_frame_buffer.h"
  27. #include "third_party/libyuv/include/libyuv/convert.h"
  28. #include "third_party/libyuv/include/libyuv/planar_functions.h"
  29. namespace media {
  30. // Returns the number of threads.
  31. static int GetVpxVideoDecoderThreadCount(const VideoDecoderConfig& config) {
  32. // vp8a doesn't really need more threads.
  33. int desired_threads = limits::kMinVideoDecodeThreads;
  34. // For VP9 decoding increase the number of decode threads to equal the
  35. // maximum number of tiles possible for higher resolution streams.
  36. if (config.codec() == VideoCodec::kVP9) {
  37. const int width = config.coded_size().width();
  38. if (width >= 3840)
  39. desired_threads = 16;
  40. else if (width >= 2560)
  41. desired_threads = 8;
  42. else if (width >= 1280)
  43. desired_threads = 4;
  44. }
  45. return VideoDecoder::GetRecommendedThreadCount(desired_threads);
  46. }
  47. static std::unique_ptr<vpx_codec_ctx> InitializeVpxContext(
  48. const VideoDecoderConfig& config) {
  49. auto context = std::make_unique<vpx_codec_ctx>();
  50. vpx_codec_dec_cfg_t vpx_config = {0};
  51. vpx_config.w = config.coded_size().width();
  52. vpx_config.h = config.coded_size().height();
  53. vpx_config.threads = GetVpxVideoDecoderThreadCount(config);
  54. vpx_codec_err_t status = vpx_codec_dec_init(context.get(),
  55. config.codec() == VideoCodec::kVP9
  56. ? vpx_codec_vp9_dx()
  57. : vpx_codec_vp8_dx(),
  58. &vpx_config, 0 /* flags */);
  59. if (status == VPX_CODEC_OK)
  60. return context;
  61. DLOG(ERROR) << "vpx_codec_dec_init() failed: "
  62. << vpx_codec_error(context.get());
  63. return nullptr;
  64. }
  65. static int32_t GetVP9FrameBuffer(void* user_priv,
  66. size_t min_size,
  67. vpx_codec_frame_buffer* fb) {
  68. DCHECK(user_priv);
  69. DCHECK(fb);
  70. FrameBufferPool* pool = static_cast<FrameBufferPool*>(user_priv);
  71. fb->data = pool->GetFrameBuffer(min_size, &fb->priv);
  72. fb->size = min_size;
  73. return fb->data ? 0 : VPX_CODEC_MEM_ERROR;
  74. }
  75. static int32_t ReleaseVP9FrameBuffer(void* user_priv,
  76. vpx_codec_frame_buffer* fb) {
  77. DCHECK(user_priv);
  78. DCHECK(fb);
  79. if (!fb->priv)
  80. return -1;
  81. FrameBufferPool* pool = static_cast<FrameBufferPool*>(user_priv);
  82. pool->ReleaseFrameBuffer(fb->priv);
  83. return 0;
  84. }
  85. // static
  86. SupportedVideoDecoderConfigs VpxVideoDecoder::SupportedConfigs() {
  87. SupportedVideoDecoderConfigs supported_configs;
  88. supported_configs.emplace_back(/*profile_min=*/VP8PROFILE_ANY,
  89. /*profile_max=*/VP8PROFILE_ANY,
  90. /*coded_size_min=*/kDefaultSwDecodeSizeMin,
  91. /*coded_size_max=*/kDefaultSwDecodeSizeMax,
  92. /*allow_encrypted=*/false,
  93. /*require_encrypted=*/false);
  94. supported_configs.emplace_back(/*profile_min=*/VP9PROFILE_PROFILE0,
  95. /*profile_max=*/VP9PROFILE_PROFILE2,
  96. /*coded_size_min=*/kDefaultSwDecodeSizeMin,
  97. /*coded_size_max=*/kDefaultSwDecodeSizeMax,
  98. /*allow_encrypted=*/false,
  99. /*require_encrypted=*/false);
  100. return supported_configs;
  101. }
  102. VpxVideoDecoder::VpxVideoDecoder(OffloadState offload_state)
  103. : bind_callbacks_(offload_state == OffloadState::kNormal) {
  104. DETACH_FROM_SEQUENCE(sequence_checker_);
  105. }
  106. VpxVideoDecoder::~VpxVideoDecoder() {
  107. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  108. CloseDecoder();
  109. }
  110. VideoDecoderType VpxVideoDecoder::GetDecoderType() const {
  111. return VideoDecoderType::kVpx;
  112. }
  113. void VpxVideoDecoder::Initialize(const VideoDecoderConfig& config,
  114. bool /* low_delay */,
  115. CdmContext* /* cdm_context */,
  116. InitCB init_cb,
  117. const OutputCB& output_cb,
  118. const WaitingCB& /* waiting_cb */) {
  119. DVLOG(1) << __func__ << ": " << config.AsHumanReadableString();
  120. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  121. DCHECK(config.IsValidConfig());
  122. CloseDecoder();
  123. InitCB bound_init_cb = bind_callbacks_ ? BindToCurrentLoop(std::move(init_cb))
  124. : std::move(init_cb);
  125. if (config.is_encrypted()) {
  126. std::move(bound_init_cb)
  127. .Run(DecoderStatus::Codes::kUnsupportedEncryptionMode);
  128. return;
  129. }
  130. if (!ConfigureDecoder(config)) {
  131. std::move(bound_init_cb).Run(DecoderStatus::Codes::kUnsupportedConfig);
  132. return;
  133. }
  134. // Success!
  135. config_ = config;
  136. state_ = DecoderState::kNormal;
  137. output_cb_ = output_cb;
  138. std::move(bound_init_cb).Run(DecoderStatus::Codes::kOk);
  139. }
  140. void VpxVideoDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
  141. DecodeCB decode_cb) {
  142. DVLOG(3) << __func__ << ": " << buffer->AsHumanReadableString();
  143. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  144. DCHECK(buffer);
  145. DCHECK(decode_cb);
  146. DCHECK_NE(state_, DecoderState::kUninitialized)
  147. << "Called Decode() before successful Initialize()";
  148. DecodeCB bound_decode_cb = bind_callbacks_
  149. ? BindToCurrentLoop(std::move(decode_cb))
  150. : std::move(decode_cb);
  151. if (state_ == DecoderState::kError) {
  152. std::move(bound_decode_cb).Run(DecoderStatus::Codes::kFailed);
  153. return;
  154. }
  155. if (state_ == DecoderState::kDecodeFinished) {
  156. std::move(bound_decode_cb).Run(DecoderStatus::Codes::kOk);
  157. return;
  158. }
  159. if (state_ == DecoderState::kNormal && buffer->end_of_stream()) {
  160. state_ = DecoderState::kDecodeFinished;
  161. std::move(bound_decode_cb).Run(DecoderStatus::Codes::kOk);
  162. return;
  163. }
  164. scoped_refptr<VideoFrame> video_frame;
  165. if (!VpxDecode(buffer.get(), &video_frame)) {
  166. state_ = DecoderState::kError;
  167. std::move(bound_decode_cb).Run(DecoderStatus::Codes::kFailed);
  168. return;
  169. }
  170. // We might get a successful VpxDecode but not a frame if only a partial
  171. // decode happened.
  172. if (video_frame) {
  173. video_frame->metadata().power_efficient = false;
  174. output_cb_.Run(video_frame);
  175. }
  176. // VideoDecoderShim expects |decode_cb| call after |output_cb_|.
  177. std::move(bound_decode_cb).Run(DecoderStatus::Codes::kOk);
  178. }
  179. void VpxVideoDecoder::Reset(base::OnceClosure reset_cb) {
  180. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  181. state_ = DecoderState::kNormal;
  182. if (bind_callbacks_)
  183. BindToCurrentLoop(std::move(reset_cb)).Run();
  184. else
  185. std::move(reset_cb).Run();
  186. // Allow Initialize() to be called on another thread now.
  187. DETACH_FROM_SEQUENCE(sequence_checker_);
  188. }
  189. bool VpxVideoDecoder::ConfigureDecoder(const VideoDecoderConfig& config) {
  190. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  191. if (config.codec() != VideoCodec::kVP8 && config.codec() != VideoCodec::kVP9)
  192. return false;
  193. #if BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
  194. // When enabled, ffmpeg handles VP8 that doesn't have alpha, and
  195. // VpxVideoDecoder will handle VP8 with alpha. FFvp8 is being deprecated.
  196. // See http://crbug.com/992235.
  197. if (base::FeatureList::IsEnabled(kFFmpegDecodeOpaqueVP8) &&
  198. config.codec() == VideoCodec::kVP8 &&
  199. config.alpha_mode() == VideoDecoderConfig::AlphaMode::kIsOpaque) {
  200. return false;
  201. }
  202. #endif
  203. DCHECK(!vpx_codec_);
  204. vpx_codec_ = InitializeVpxContext(config);
  205. if (!vpx_codec_)
  206. return false;
  207. // Configure VP9 to decode on our buffers to skip a data copy on
  208. // decoding. For YV12A-VP9, we use our buffers for the Y, U and V planes and
  209. // copy the A plane.
  210. if (config.codec() == VideoCodec::kVP9) {
  211. DCHECK(vpx_codec_get_caps(vpx_codec_->iface) &
  212. VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER);
  213. DCHECK(!memory_pool_);
  214. memory_pool_ = new FrameBufferPool();
  215. if (vpx_codec_set_frame_buffer_functions(
  216. vpx_codec_.get(), &GetVP9FrameBuffer, &ReleaseVP9FrameBuffer,
  217. memory_pool_.get())) {
  218. DLOG(ERROR) << "Failed to configure external buffers. "
  219. << vpx_codec_error(vpx_codec_.get());
  220. return false;
  221. }
  222. vpx_codec_err_t status =
  223. vpx_codec_control(vpx_codec_.get(), VP9D_SET_LOOP_FILTER_OPT, 1);
  224. if (status != VPX_CODEC_OK) {
  225. DLOG(ERROR) << "Failed to enable VP9D_SET_LOOP_FILTER_OPT. "
  226. << vpx_codec_error(vpx_codec_.get());
  227. return false;
  228. }
  229. }
  230. if (config.alpha_mode() == VideoDecoderConfig::AlphaMode::kIsOpaque)
  231. return true;
  232. DCHECK(!vpx_codec_alpha_);
  233. vpx_codec_alpha_ = InitializeVpxContext(config);
  234. return !!vpx_codec_alpha_;
  235. }
  236. void VpxVideoDecoder::CloseDecoder() {
  237. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  238. // Note: The vpx_codec_destroy() calls below don't release the memory
  239. // allocated for vpx_codec_ctx, they just release internal allocations, so we
  240. // still need std::unique_ptr to release the structure memory.
  241. if (vpx_codec_)
  242. vpx_codec_destroy(vpx_codec_.get());
  243. if (vpx_codec_alpha_)
  244. vpx_codec_destroy(vpx_codec_alpha_.get());
  245. vpx_codec_.reset();
  246. vpx_codec_alpha_.reset();
  247. if (memory_pool_) {
  248. memory_pool_->Shutdown();
  249. memory_pool_ = nullptr;
  250. }
  251. }
  252. void VpxVideoDecoder::Detach() {
  253. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  254. DCHECK(!bind_callbacks_);
  255. CloseDecoder();
  256. DETACH_FROM_SEQUENCE(sequence_checker_);
  257. }
  258. bool VpxVideoDecoder::VpxDecode(const DecoderBuffer* buffer,
  259. scoped_refptr<VideoFrame>* video_frame) {
  260. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  261. DCHECK(video_frame);
  262. DCHECK(!buffer->end_of_stream());
  263. {
  264. TRACE_EVENT1("media", "vpx_codec_decode", "buffer",
  265. buffer->AsHumanReadableString());
  266. vpx_codec_err_t status =
  267. vpx_codec_decode(vpx_codec_.get(), buffer->data(), buffer->data_size(),
  268. nullptr /* user_priv */, 0 /* deadline */);
  269. if (status != VPX_CODEC_OK) {
  270. DLOG(ERROR) << "vpx_codec_decode() error: "
  271. << vpx_codec_err_to_string(status);
  272. return false;
  273. }
  274. }
  275. // Gets pointer to decoded data.
  276. vpx_codec_iter_t iter = NULL;
  277. const vpx_image_t* vpx_image = vpx_codec_get_frame(vpx_codec_.get(), &iter);
  278. if (!vpx_image) {
  279. *video_frame = nullptr;
  280. return true;
  281. }
  282. const vpx_image_t* vpx_image_alpha = nullptr;
  283. const auto alpha_decode_status =
  284. DecodeAlphaPlane(vpx_image, &vpx_image_alpha, buffer);
  285. if (alpha_decode_status == kAlphaPlaneError) {
  286. return false;
  287. } else if (alpha_decode_status == kNoAlphaPlaneData) {
  288. *video_frame = nullptr;
  289. return true;
  290. }
  291. if (!CopyVpxImageToVideoFrame(vpx_image, vpx_image_alpha, video_frame))
  292. return false;
  293. if (vpx_image_alpha && config_.codec() == VideoCodec::kVP8) {
  294. libyuv::CopyPlane(vpx_image_alpha->planes[VPX_PLANE_Y],
  295. vpx_image_alpha->stride[VPX_PLANE_Y],
  296. (*video_frame)->visible_data(VideoFrame::kAPlane),
  297. (*video_frame)->stride(VideoFrame::kAPlane),
  298. (*video_frame)->visible_rect().width(),
  299. (*video_frame)->visible_rect().height());
  300. }
  301. (*video_frame)->set_timestamp(buffer->timestamp());
  302. (*video_frame)->set_hdr_metadata(config_.hdr_metadata());
  303. // Prefer the color space from the config if available. It generally comes
  304. // from the color tag which is more expressive than the vp8 and vp9 bitstream.
  305. if (config_.color_space_info().IsSpecified()) {
  306. (*video_frame)
  307. ->set_color_space(config_.color_space_info().ToGfxColorSpace());
  308. return true;
  309. }
  310. auto primaries = gfx::ColorSpace::PrimaryID::INVALID;
  311. auto transfer = gfx::ColorSpace::TransferID::INVALID;
  312. auto matrix = gfx::ColorSpace::MatrixID::INVALID;
  313. auto range = vpx_image->range == VPX_CR_FULL_RANGE
  314. ? gfx::ColorSpace::RangeID::FULL
  315. : gfx::ColorSpace::RangeID::LIMITED;
  316. switch (vpx_image->cs) {
  317. case VPX_CS_BT_601:
  318. case VPX_CS_SMPTE_170:
  319. primaries = gfx::ColorSpace::PrimaryID::SMPTE170M;
  320. transfer = gfx::ColorSpace::TransferID::SMPTE170M;
  321. matrix = gfx::ColorSpace::MatrixID::SMPTE170M;
  322. break;
  323. case VPX_CS_SMPTE_240:
  324. primaries = gfx::ColorSpace::PrimaryID::SMPTE240M;
  325. transfer = gfx::ColorSpace::TransferID::SMPTE240M;
  326. matrix = gfx::ColorSpace::MatrixID::SMPTE240M;
  327. break;
  328. case VPX_CS_BT_709:
  329. primaries = gfx::ColorSpace::PrimaryID::BT709;
  330. transfer = gfx::ColorSpace::TransferID::BT709;
  331. matrix = gfx::ColorSpace::MatrixID::BT709;
  332. break;
  333. case VPX_CS_BT_2020:
  334. primaries = gfx::ColorSpace::PrimaryID::BT2020;
  335. if (vpx_image->bit_depth >= 12)
  336. transfer = gfx::ColorSpace::TransferID::BT2020_12;
  337. else if (vpx_image->bit_depth >= 10)
  338. transfer = gfx::ColorSpace::TransferID::BT2020_10;
  339. else
  340. transfer = gfx::ColorSpace::TransferID::BT709;
  341. matrix = gfx::ColorSpace::MatrixID::BT2020_NCL; // is this right?
  342. break;
  343. case VPX_CS_SRGB:
  344. primaries = gfx::ColorSpace::PrimaryID::BT709;
  345. transfer = gfx::ColorSpace::TransferID::SRGB;
  346. matrix = gfx::ColorSpace::MatrixID::GBR;
  347. break;
  348. default:
  349. break;
  350. }
  351. // TODO(ccameron): Set a color space even for unspecified values.
  352. if (primaries != gfx::ColorSpace::PrimaryID::INVALID) {
  353. (*video_frame)
  354. ->set_color_space(gfx::ColorSpace(primaries, transfer, matrix, range));
  355. }
  356. return true;
  357. }
  358. VpxVideoDecoder::AlphaDecodeStatus VpxVideoDecoder::DecodeAlphaPlane(
  359. const struct vpx_image* vpx_image,
  360. const struct vpx_image** vpx_image_alpha,
  361. const DecoderBuffer* buffer) {
  362. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  363. if (!vpx_codec_alpha_ || buffer->side_data_size() < 8) {
  364. return kAlphaPlaneProcessed;
  365. }
  366. // First 8 bytes of side data is |side_data_id| in big endian.
  367. const uint64_t side_data_id = base::NetToHost64(
  368. *(reinterpret_cast<const uint64_t*>(buffer->side_data())));
  369. if (side_data_id != 1) {
  370. return kAlphaPlaneProcessed;
  371. }
  372. // Try and decode buffer->side_data() minus the first 8 bytes as a full
  373. // frame.
  374. {
  375. TRACE_EVENT1("media", "vpx_codec_decode_alpha", "buffer",
  376. buffer->AsHumanReadableString());
  377. vpx_codec_err_t status =
  378. vpx_codec_decode(vpx_codec_alpha_.get(), buffer->side_data() + 8,
  379. buffer->side_data_size() - 8, nullptr /* user_priv */,
  380. 0 /* deadline */);
  381. if (status != VPX_CODEC_OK) {
  382. DLOG(ERROR) << "vpx_codec_decode() failed for the alpha: "
  383. << vpx_codec_error(vpx_codec_.get());
  384. return kAlphaPlaneError;
  385. }
  386. }
  387. vpx_codec_iter_t iter_alpha = NULL;
  388. *vpx_image_alpha = vpx_codec_get_frame(vpx_codec_alpha_.get(), &iter_alpha);
  389. if (!(*vpx_image_alpha)) {
  390. return kNoAlphaPlaneData;
  391. }
  392. if ((*vpx_image_alpha)->d_h != vpx_image->d_h ||
  393. (*vpx_image_alpha)->d_w != vpx_image->d_w) {
  394. DLOG(ERROR) << "The alpha plane dimensions are not the same as the "
  395. "image dimensions.";
  396. return kAlphaPlaneError;
  397. }
  398. return kAlphaPlaneProcessed;
  399. }
  400. bool VpxVideoDecoder::CopyVpxImageToVideoFrame(
  401. const struct vpx_image* vpx_image,
  402. const struct vpx_image* vpx_image_alpha,
  403. scoped_refptr<VideoFrame>* video_frame) {
  404. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  405. DCHECK(vpx_image);
  406. VideoPixelFormat codec_format;
  407. switch (vpx_image->fmt) {
  408. case VPX_IMG_FMT_I420:
  409. codec_format = vpx_image_alpha ? PIXEL_FORMAT_I420A : PIXEL_FORMAT_I420;
  410. break;
  411. case VPX_IMG_FMT_I422:
  412. codec_format = PIXEL_FORMAT_I422;
  413. break;
  414. case VPX_IMG_FMT_I444:
  415. codec_format = PIXEL_FORMAT_I444;
  416. break;
  417. case VPX_IMG_FMT_I42016:
  418. switch (vpx_image->bit_depth) {
  419. case 10:
  420. codec_format = PIXEL_FORMAT_YUV420P10;
  421. break;
  422. case 12:
  423. codec_format = PIXEL_FORMAT_YUV420P12;
  424. break;
  425. default:
  426. DLOG(ERROR) << "Unsupported bit depth: " << vpx_image->bit_depth;
  427. return false;
  428. }
  429. break;
  430. case VPX_IMG_FMT_I42216:
  431. switch (vpx_image->bit_depth) {
  432. case 10:
  433. codec_format = PIXEL_FORMAT_YUV422P10;
  434. break;
  435. case 12:
  436. codec_format = PIXEL_FORMAT_YUV422P12;
  437. break;
  438. default:
  439. DLOG(ERROR) << "Unsupported bit depth: " << vpx_image->bit_depth;
  440. return false;
  441. }
  442. break;
  443. case VPX_IMG_FMT_I44416:
  444. switch (vpx_image->bit_depth) {
  445. case 10:
  446. codec_format = PIXEL_FORMAT_YUV444P10;
  447. break;
  448. case 12:
  449. codec_format = PIXEL_FORMAT_YUV444P12;
  450. break;
  451. default:
  452. DLOG(ERROR) << "Unsupported bit depth: " << vpx_image->bit_depth;
  453. return false;
  454. }
  455. break;
  456. default:
  457. DLOG(ERROR) << "Unsupported pixel format: " << vpx_image->fmt;
  458. return false;
  459. }
  460. // The mixed |w|/|d_h| in |coded_size| is intentional. Setting the correct
  461. // coded width is necessary to allow coalesced memory access, which may avoid
  462. // frame copies. Setting the correct coded height however does not have any
  463. // benefit, and only risk copying too much data.
  464. const gfx::Size coded_size(vpx_image->w, vpx_image->d_h);
  465. const gfx::Size visible_size(vpx_image->d_w, vpx_image->d_h);
  466. // Compute natural size by scaling visible size by *pixel* aspect ratio. Note
  467. // that we could instead use vpx_image r_w and r_h, but doing so would allow
  468. // pixel aspect ratio to change on a per-frame basis which would make
  469. // vpx_video_decoder inconsistent with decoders where changes to
  470. // pixel aspect ratio are not surfaced (e.g. Android MediaCodec).
  471. const gfx::Size natural_size =
  472. config_.aspect_ratio().GetNaturalSize(gfx::Rect(visible_size));
  473. if (memory_pool_) {
  474. DCHECK_EQ(VideoCodec::kVP9, config_.codec());
  475. if (vpx_image_alpha) {
  476. size_t alpha_plane_size =
  477. vpx_image_alpha->stride[VPX_PLANE_Y] * vpx_image_alpha->d_h;
  478. uint8_t* alpha_plane = memory_pool_->AllocateAlphaPlaneForFrameBuffer(
  479. alpha_plane_size, vpx_image->fb_priv);
  480. if (!alpha_plane) // In case of OOM, abort copy.
  481. return false;
  482. libyuv::CopyPlane(vpx_image_alpha->planes[VPX_PLANE_Y],
  483. vpx_image_alpha->stride[VPX_PLANE_Y], alpha_plane,
  484. vpx_image_alpha->stride[VPX_PLANE_Y],
  485. vpx_image_alpha->d_w, vpx_image_alpha->d_h);
  486. *video_frame = VideoFrame::WrapExternalYuvaData(
  487. codec_format, coded_size, gfx::Rect(visible_size), natural_size,
  488. vpx_image->stride[VPX_PLANE_Y], vpx_image->stride[VPX_PLANE_U],
  489. vpx_image->stride[VPX_PLANE_V], vpx_image_alpha->stride[VPX_PLANE_Y],
  490. vpx_image->planes[VPX_PLANE_Y], vpx_image->planes[VPX_PLANE_U],
  491. vpx_image->planes[VPX_PLANE_V], alpha_plane, kNoTimestamp);
  492. } else {
  493. *video_frame = VideoFrame::WrapExternalYuvData(
  494. codec_format, coded_size, gfx::Rect(visible_size), natural_size,
  495. vpx_image->stride[VPX_PLANE_Y], vpx_image->stride[VPX_PLANE_U],
  496. vpx_image->stride[VPX_PLANE_V], vpx_image->planes[VPX_PLANE_Y],
  497. vpx_image->planes[VPX_PLANE_U], vpx_image->planes[VPX_PLANE_V],
  498. kNoTimestamp);
  499. }
  500. if (!(*video_frame))
  501. return false;
  502. video_frame->get()->AddDestructionObserver(
  503. memory_pool_->CreateFrameCallback(vpx_image->fb_priv));
  504. return true;
  505. }
  506. *video_frame = frame_pool_.CreateFrame(codec_format, visible_size,
  507. gfx::Rect(visible_size), natural_size,
  508. kNoTimestamp);
  509. if (!(*video_frame))
  510. return false;
  511. for (int plane = 0; plane < 3; plane++) {
  512. libyuv::CopyPlane(
  513. vpx_image->planes[plane], vpx_image->stride[plane],
  514. (*video_frame)->visible_data(plane), (*video_frame)->stride(plane),
  515. (*video_frame)->row_bytes(plane), (*video_frame)->rows(plane));
  516. }
  517. return true;
  518. }
  519. } // namespace media