OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 * | |
10 */ | |
11 | |
12 // TODO(hbos): This is essentially a copy of an decoder class in WebRTC that as | |
13 // of this statement has not yet landed, but that I want to have accessible in | |
14 // Chromium before that CL lands. This is because I use it in order to validate | |
15 // the build files for OpenH264 and the WebRTC encoder/decoder CL cannot land | |
16 // until I can build OpenH264 from source. Once the build files are stable I | |
17 // will land both CLs and remove this copy of the decoder. | |
hbos_chromium
2015/10/29 14:28:26
You can skip reviewing this file...
| |
18 | |
19 #include "openh264/testing/h264_decoder_impl.h" | |
20 | |
21 #include <bitset> | |
22 | |
23 // OpenH264 | |
24 #include "openh264/src/codec/api/svc/codec_api.h" | |
25 #include "openh264/src/codec/api/svc/codec_app_def.h" | |
26 #include "openh264/src/codec/api/svc/codec_def.h" | |
27 | |
28 #include "webrtc/base/checks.h" | |
29 #include "webrtc/base/logging.h" | |
30 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" | |
31 | |
32 using webrtc::VideoCodecType; | |
33 | |
34 namespace openh264 { | |
35 | |
36 namespace { | |
37 const bool kOpenH264DecoderDetailedLogging = false; | |
38 } // namespace | |
39 | |
40 H264DecoderImpl::H264DecoderImpl() | |
41 : openh264_decoder_(nullptr), | |
42 decoded_image_(), | |
43 decoded_image_callback_(nullptr) { | |
44 } | |
45 | |
46 H264DecoderImpl::~H264DecoderImpl() { | |
47 Release(); | |
48 } | |
49 | |
50 int32_t H264DecoderImpl::InitDecode(const VideoCodec* codec_settings, | |
51 int32_t /*number_of_cores*/) { | |
52 if (codec_settings && | |
53 codec_settings->codecType != VideoCodecType::kVideoCodecH264) { | |
54 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | |
55 } | |
56 | |
57 int release_ret = Release(); | |
58 if (release_ret != WEBRTC_VIDEO_CODEC_OK) | |
59 return release_ret; | |
60 RTC_DCHECK(!openh264_decoder_); | |
61 | |
62 // Create decoder. | |
63 if (WelsCreateDecoder(&openh264_decoder_) != 0) { | |
64 // LOG(LS_ERROR) << "Failed to create OpenH264 decoder"; | |
65 RTC_DCHECK(!openh264_decoder_); | |
66 return WEBRTC_VIDEO_CODEC_ERROR; | |
67 } | |
68 RTC_DCHECK(openh264_decoder_); | |
69 if (kOpenH264DecoderDetailedLogging) { | |
70 int trace_level = WELS_LOG_DETAIL; | |
71 openh264_decoder_->SetOption(DECODER_OPTION_TRACE_LEVEL, | |
72 &trace_level); | |
73 } | |
74 // else WELS_LOG_DEFAULT is used by default. | |
75 | |
76 // Initialization parameters. | |
77 SDecodingParam init_params; | |
78 memset(&init_params, 0, sizeof(SDecodingParam)); | |
79 init_params.eOutputColorFormat = EVideoFormatType::videoFormatI420; | |
80 init_params.uiCpuLoad = 0; | |
81 init_params.uiTargetDqLayer = 0xFF; | |
82 init_params.eEcActiveIdc = ERROR_CON_IDC::ERROR_CON_DISABLE; | |
83 init_params.bParseOnly = false; | |
84 init_params.sVideoProperty.eVideoBsType = | |
85 VIDEO_BITSTREAM_TYPE::VIDEO_BITSTREAM_DEFAULT; | |
86 | |
87 // Initialize. | |
88 if (openh264_decoder_->Initialize(&init_params) != 0) { | |
89 // LOG(LS_ERROR) << "Failed to initialize OpenH264 decoder"; | |
90 Release(); | |
91 return WEBRTC_VIDEO_CODEC_ERROR; | |
92 } | |
93 | |
94 return WEBRTC_VIDEO_CODEC_OK; | |
95 } | |
96 | |
97 int32_t H264DecoderImpl::Release() { | |
98 if (openh264_decoder_) { | |
99 int64_t uninit_ret = openh264_decoder_->Uninitialize(); | |
100 if (uninit_ret != 0) { | |
101 // LOG(LS_WARNING) << "OpenH264 decoder's Uninitialize() returned " | |
102 // << "unsuccessful: " << uninit_ret; | |
103 } | |
104 WelsDestroyDecoder(openh264_decoder_); | |
105 openh264_decoder_ = nullptr; | |
106 } | |
107 return WEBRTC_VIDEO_CODEC_OK; | |
108 } | |
109 | |
110 int32_t H264DecoderImpl::Reset() { | |
111 if (!IsInitialized()) | |
112 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | |
113 InitDecode(nullptr, 1); | |
114 return WEBRTC_VIDEO_CODEC_OK; | |
115 } | |
116 | |
117 int32_t H264DecoderImpl::RegisterDecodeCompleteCallback( | |
118 DecodedImageCallback* callback) { | |
119 decoded_image_callback_ = callback; | |
120 return WEBRTC_VIDEO_CODEC_OK; | |
121 } | |
122 | |
123 int32_t H264DecoderImpl::Decode(const EncodedImage& input_image, | |
124 bool /*missing_frames*/, | |
125 const RTPFragmentationHeader* /*fragmentation*/, | |
126 const CodecSpecificInfo* codec_specific_info, | |
127 int64_t /*render_time_ms*/) { | |
128 if (!IsInitialized()) { | |
129 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | |
130 } | |
131 if (!decoded_image_callback_) { | |
132 // LOG(LS_WARNING) << "InitDecode() has been called, but a callback function " | |
133 // << "has not been set with RegisterDecodeCompleteCallback() "; | |
134 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | |
135 } | |
136 if (!input_image._buffer || !input_image._length) | |
137 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | |
138 if (codec_specific_info && | |
139 codec_specific_info->codecType != VideoCodecType::kVideoCodecH264) { | |
140 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | |
141 } | |
142 | |
143 // DecodeFrameNoDelay output. | |
144 uint8_t* data[3] = { 0, 0, 0 }; | |
145 SBufferInfo buffer_info; | |
146 memset(&buffer_info, 0, sizeof(SBufferInfo)); | |
147 | |
148 // Decode! | |
149 DECODING_STATE decode_ret = openh264_decoder_->DecodeFrameNoDelay( | |
150 input_image._buffer, static_cast<int>(input_image._length), data, | |
151 &buffer_info); | |
152 if (decode_ret != 0) { | |
153 // LOG(LS_ERROR) << "H264 decode failed, returned error bitmask: " | |
154 // << std::bitset<8>(decode_ret).to_string() << " = " | |
155 // << decode_ret; | |
156 // if (decode_ret & dsFramePending) | |
157 // LOG(LS_ERROR) << " dsFramePending"; | |
158 // if (decode_ret & dsRefLost) | |
159 // LOG(LS_ERROR) << " dsRefLost"; | |
160 // if (decode_ret & dsBitstreamError) | |
161 // LOG(LS_ERROR) << " dsBitstreamError"; | |
162 // if (decode_ret & dsDepLayerLost) | |
163 // LOG(LS_ERROR) << " dsDepLayerLost"; | |
164 // if (decode_ret & dsNoParamSets) | |
165 // LOG(LS_ERROR) << " dsNoParamSets"; | |
166 // if (decode_ret & dsDataErrorConcealed) | |
167 // LOG(LS_ERROR) << " dsDataErrorConcealed"; | |
168 return WEBRTC_VIDEO_CODEC_ERROR; | |
169 } | |
170 RTC_DCHECK_EQ(decode_ret, 0); | |
171 | |
172 // Frame data ready? | |
173 if (buffer_info.iBufferStatus == 1) { | |
174 // Copy decoded data into |decoded_image_|. Must copy because the internal | |
175 // VideoFrameBuffer is reference counted. | |
176 decoded_image_.CreateFrame(data[0], data[1], data[2], | |
177 buffer_info.UsrData.sSystemBuffer.iWidth, | |
178 buffer_info.UsrData.sSystemBuffer.iHeight, | |
179 buffer_info.UsrData.sSystemBuffer.iStride[0], | |
180 buffer_info.UsrData.sSystemBuffer.iStride[1], | |
181 buffer_info.UsrData.sSystemBuffer.iStride[1]); | |
182 decoded_image_.set_timestamp(input_image._timeStamp); | |
183 decoded_image_.set_ntp_time_ms(input_image.ntp_time_ms_); | |
184 | |
185 // Deliver decoded image. | |
186 decoded_image_callback_->Decoded(decoded_image_); | |
187 } | |
188 return WEBRTC_VIDEO_CODEC_OK; | |
189 } | |
190 | |
191 bool H264DecoderImpl::IsInitialized() { | |
192 return openh264_decoder_ != nullptr; | |
193 } | |
194 | |
195 } // namespace openh264 | |
OLD | NEW |