1
2
3
4
5
6
7
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
103
104
105
106
107
108
109
110
111
|
// Copyright (c) 2010 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.
#include "remoting/base/decoder_vp8.h"
#include "base/logging.h"
#include "media/base/media.h"
#include "media/base/yuv_convert.h"
#include "remoting/base/util.h"
extern "C" {
#define VPX_CODEC_DISABLE_COMPAT 1
#include "third_party/libvpx/include/vpx/vpx_codec.h"
#include "third_party/libvpx/include/vpx/vpx_decoder.h"
#include "third_party/libvpx/include/vpx/vp8dx.h"
}
namespace remoting {
DecoderVp8::DecoderVp8()
: state_(kUninitialized),
codec_(NULL) {
}
DecoderVp8::~DecoderVp8() {
if (codec_) {
vpx_codec_err_t ret = vpx_codec_destroy(codec_);
CHECK(ret == VPX_CODEC_OK) << "Failed to destroy codec";
}
delete codec_;
}
void DecoderVp8::Initialize(scoped_refptr<media::VideoFrame> frame) {
DCHECK_EQ(kUninitialized, state_);
if (frame->format() != media::VideoFrame::RGB32) {
LOG(INFO) << "DecoderVp8 only supports RGB32 as output";
state_ = kError;
return;
}
frame_ = frame;
state_ = kReady;
}
Decoder::DecodeResult DecoderVp8::DecodePacket(const VideoPacket* packet) {
DCHECK_EQ(kReady, state_);
// Initialize the codec as needed.
if (!codec_) {
codec_ = new vpx_codec_ctx_t();
vpx_codec_err_t ret =
vpx_codec_dec_init(
codec_,
(const vpx_codec_iface_t*)media::GetVp8DxAlgoAddress(), NULL, 0);
if (ret != VPX_CODEC_OK) {
LOG(INFO) << "Cannot initialize codec.";
delete codec_;
codec_ = NULL;
state_ = kError;
return DECODE_ERROR;
}
}
// Do the actual decoding.
vpx_codec_err_t ret = vpx_codec_decode(
codec_, reinterpret_cast<const uint8*>(packet->data().data()),
packet->data().size(), NULL, 0);
if (ret != VPX_CODEC_OK) {
LOG(INFO) << "Decoding failed:" << vpx_codec_err_to_string(ret) << "\n"
<< "Details: " << vpx_codec_error(codec_) << "\n"
<< vpx_codec_error_detail(codec_);
return DECODE_ERROR;
}
// Gets the decoded data.
vpx_codec_iter_t iter = NULL;
vpx_image_t* image = vpx_codec_get_frame(codec_, &iter);
if (!image) {
LOG(INFO) << "No video frame decoded";
return DECODE_ERROR;
}
// Perform YUV conversion.
media::ConvertYUVToRGB32(image->planes[0], image->planes[1], image->planes[2],
frame_->data(media::VideoFrame::kRGBPlane),
frame_->width(), frame_->height(),
image->stride[0], image->stride[1],
frame_->stride(media::VideoFrame::kRGBPlane),
media::YV12);
return DECODE_DONE;
}
void DecoderVp8::GetUpdatedRects(UpdatedRects* rects) {
}
void DecoderVp8::Reset() {
frame_ = NULL;
state_ = kUninitialized;
}
bool DecoderVp8::IsReadyForData() {
return state_ == kReady;
}
VideoPacketFormat::Encoding DecoderVp8::Encoding() {
return VideoPacketFormat::ENCODING_VP8;
}
} // namespace remoting
|