1
+
/******************************************************************************
2
+
QtAV: Media play library based on Qt and FFmpeg
3
+
Copyright (C) 2013 Wang Bin <wbsecg1@gmail.com>
4
+
5
+
* This file is part of QtAV
6
+
7
+
This library is free software; you can redistribute it and/or
8
+
modify it under the terms of the GNU Lesser General Public
9
+
License as published by the Free Software Foundation; either
10
+
version 2.1 of the License, or (at your option) any later version.
11
+
12
+
This library is distributed in the hope that it will be useful,
13
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+
Lesser General Public License for more details.
16
+
17
+
You should have received a copy of the GNU Lesser General Public
18
+
License along with this library; if not, write to the Free Software
19
+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
+
******************************************************************************/
21
+
22
+
#include "QtAV/VideoDecoderFFmpeg.h"
23
+
#include "private/VideoDecoderFFmpeg_p.h"
24
+
#include <QtAV/Packet.h>
25
+
#include <QtAV/QtAV_Compat.h>
26
+
#include "prepost.h"
27
+
28
+
#include <QDebug>
29
+
30
+
#include <libavcodec/avcodec.h>
31
+
extern "C"
32
+
{
33
+
#include <libcedarv/libcedarv.h>
34
+
}
35
+
36
+
static void map32x32_to_yuv_Y(unsigned char* srcY, unsigned char* tarY, unsigned int coded_width, unsigned int coded_height)
37
+
{
38
+
unsigned int i,j,l,m,n;
39
+
unsigned int mb_width,mb_height,twomb_line,recon_width;
40
+
unsigned long offset;
41
+
unsigned char *ptr;
42
+
43
+
ptr = srcY;
44
+
mb_width = (coded_width+15)>>4;
45
+
mb_height = (coded_height+15)>>4;
46
+
twomb_line = (mb_height+1)>>1;
47
+
recon_width = (mb_width+1)&0xfffffffe;
48
+
49
+
for(i=0;i<twomb_line;i++)
50
+
{
51
+
for(j=0;j<recon_width;j+=2)
52
+
{
53
+
for(l=0;l<32;l++)
54
+
{
55
+
//first mb
56
+
m=i*32 + l;
57
+
n= j*16;
58
+
if(m<coded_height && n<coded_width)
59
+
{
60
+
offset = m*coded_width + n;
61
+
memcpy(tarY+offset,ptr,16);
62
+
ptr += 16;
63
+
}
64
+
else
65
+
ptr += 16;
66
+
67
+
//second mb
68
+
n= j*16+16;
69
+
if(m<coded_height && n<coded_width)
70
+
{
71
+
offset = m*coded_width + n;
72
+
memcpy(tarY+offset,ptr,16);
73
+
ptr += 16;
74
+
}
75
+
else
76
+
ptr += 16;
77
+
}
78
+
}
79
+
}
80
+
}
81
+
82
+
static void map32x32_to_yuv_C(unsigned char* srcC,unsigned char* tarCb,unsigned char* tarCr,unsigned int coded_width,unsigned int coded_height)
83
+
{
84
+
/*
85
+
unsigned int i,j,k;
86
+
87
+
for (i = 0; i < coded_width; ++i) {
88
+
k = i * coded_width;
89
+
for (j = 0; j < coded_height; ++j) {
90
+
*(tarCb + k) = srcC[2*k];
91
+
*(tarCr + k) = srcC[2*k+1];
92
+
k++;
93
+
}
94
+
}
95
+
*/
96
+
unsigned int i,j,l,m,n,k;
97
+
unsigned int mb_width,mb_height,fourmb_line,recon_width;
98
+
unsigned char line[16];
99
+
unsigned long offset;
100
+
unsigned char *ptr;
101
+
102
+
ptr = srcC;
103
+
mb_width = (coded_width+7)>>3;
104
+
mb_height = (coded_height+7)>>3;
105
+
fourmb_line = (mb_height+3)>>2;
106
+
recon_width = (mb_width+1)&0xfffffffe;
107
+
108
+
for(i=0;i<fourmb_line;i++)
109
+
{
110
+
for(j=0;j<recon_width;j+=2)
111
+
{
112
+
for(l=0;l<32;l++)
113
+
{
114
+
//first mb
115
+
m=i*32 + l;
116
+
n= j*8;
117
+
if(m<coded_height && n<coded_width)
118
+
{
119
+
offset = m*coded_width + n;
120
+
memcpy(line,ptr,16);
121
+
for(k=0;k<8;k++)
122
+
{
123
+
*(tarCb + offset + k) = line[2*k];
124
+
*(tarCr + offset + k) = line[2*k+1];
125
+
}
126
+
ptr += 16;
127
+
}
128
+
else
129
+
ptr += 16;
130
+
131
+
//second mb
132
+
n= j*8+8;
133
+
if(m<coded_height && n<coded_width)
134
+
{
135
+
offset = m*coded_width + n;
136
+
memcpy(line,ptr,16);
137
+
for(k=0;k<8;k++)
138
+
{
139
+
*(tarCb + offset + k) = line[2*k];
140
+
*(tarCr + offset + k) = line[2*k+1];
141
+
}
142
+
ptr += 16;
143
+
}
144
+
else
145
+
ptr += 16;
146
+
}
147
+
}
148
+
}
149
+
}
150
+
151
+
namespace QtAV {
152
+
153
+
class VideoDecoderCedarvPrivate;
154
+
class VideoDecoderCedarv : public VideoDecoderFFmpeg
155
+
{
156
+
DPTR_DECLARE_PRIVATE(VideoDecoderCedarv)
157
+
public:
158
+
VideoDecoderCedarv();
159
+
bool prepare();
160
+
bool decode(const QByteArray &encoded);
161
+
VideoFrame frame();
162
+
};
163
+
164
+
extern VideoDecoderId VideoDecoderId_Cedarv;
165
+
FACTORY_REGISTER_ID_AUTO(VideoDecoder, Cedarv, "Cedarv")
166
+
167
+
void RegisterVideoDecoderCedarv_Man()
168
+
{
169
+
FACTORY_REGISTER_ID_MAN(VideoDecoder, Cedarv, "Cedarv")
170
+
}
171
+
172
+
class VideoDecoderCedarvPrivate : public VideoDecoderFFmpegPrivate
173
+
{
174
+
public:
175
+
VideoDecoderCedarvPrivate() {
176
+
cedarv = 0;
177
+
}
178
+
179
+
~VideoDecoderCedarvPrivate() {
180
+
//TODO:
181
+
}
182
+
183
+
CEDARV_DECODER *cedarv;
184
+
cedarv_picture_t cedarPicture;
185
+
QByteArray y;
186
+
QByteArray u;
187
+
QByteArray v;
188
+
};
189
+
190
+
VideoDecoderCedarv::VideoDecoderCedarv()
191
+
: VideoDecoderFFmpeg(*new VideoDecoderCedarvPrivate())
192
+
{
193
+
}
194
+
195
+
196
+
bool VideoDecoderCedarv::prepare()
197
+
{
198
+
DPTR_D(VideoDecoderCedarv);
199
+
if (!d.cedarv) {
200
+
int ret;
201
+
d.cedarv = libcedarv_init(&ret);
202
+
if (ret < 0 || d.cedarv == NULL)
203
+
return false;
204
+
}
205
+
206
+
d.codec_ctx->opaque = &d; //is it ok?
207
+
208
+
cedarv_stream_info_t cedarStreamInfo;
209
+
memset(&cedarStreamInfo, 0, sizeof cedarStreamInfo);
210
+
211
+
switch (d.codec_ctx->codec_id) {
212
+
case AV_CODEC_ID_H264:
213
+
cedarStreamInfo.format = CEDARV_STREAM_FORMAT_H264;
214
+
break;
215
+
case AV_CODEC_ID_VP8:
216
+
cedarStreamInfo.format = CEDARV_STREAM_FORMAT_VP8;
217
+
break;
218
+
case AV_CODEC_ID_VC1:
219
+
cedarStreamInfo.format = CEDARV_STREAM_FORMAT_VC1;
220
+
break;
221
+
case AV_CODEC_ID_MPEG4:
222
+
cedarStreamInfo.format = CEDARV_STREAM_FORMAT_MPEG4;
223
+
cedarStreamInfo.sub_format = CEDARV_MPEG4_SUB_FORMAT_XVID;
224
+
break;
225
+
case AV_CODEC_ID_MPEG2VIDEO:
226
+
cedarStreamInfo.format = CEDARV_STREAM_FORMAT_MPEG2;
227
+
break;
228
+
case AV_CODEC_ID_RV40:
229
+
cedarStreamInfo.format = CEDARV_STREAM_FORMAT_REALVIDEO;
230
+
break;
231
+
default:
232
+
return false;
233
+
}
234
+
cedarStreamInfo.video_width = d.codec_ctx->width;
235
+
cedarStreamInfo.video_height = d.codec_ctx->height;
236
+
if (d.codec_ctx->extradata_size) {
237
+
cedarStreamInfo.init_data = d.codec_ctx->extradata;
238
+
cedarStreamInfo.init_data_len = d.codec_ctx->extradata_size;
239
+
}
240
+
241
+
int cedarvRet;
242
+
cedarvRet = d.cedarv->set_vstream_info(d.cedarv, &cedarStreamInfo);
243
+
if (cedarvRet < 0)
244
+
return false;
245
+
cedarvRet = d.cedarv->open(d.cedarv);
246
+
if (cedarvRet < 0)
247
+
return false;
248
+
249
+
d.cedarv->ioctrl(d.cedarv, CEDARV_COMMAND_PLAY, 0);
250
+
251
+
return true;
252
+
}
253
+
254
+
bool VideoDecoderCedarv::decode(const QByteArray &encoded)
255
+
{
256
+
DPTR_D(VideoDecoderCedarv);
257
+
258
+
//d.cedarv->ioctrl(d.cedarv, CEDARV_COMMAND_JUMP, 0);
259
+
260
+
AVPacket packet;
261
+
av_new_packet(&packet, encoded.size());
262
+
memcpy(packet.data, encoded.data(), encoded.size());
263
+
264
+
if (packet.size == 0) {
265
+
return true;
266
+
}
267
+
268
+
u32 bufsize0, bufsize1;
269
+
u8 *buf0, *buf1;
270
+
271
+
if (d.cedarv->request_write(d.cedarv, packet.size, &buf0, &bufsize0, &buf1, &bufsize1) >= 0) {
272
+
memcpy(buf0, packet.data, bufsize0);
273
+
if ((u32)packet.size > bufsize0) {
274
+
memcpy(buf1, packet.data + bufsize0, bufsize1);
275
+
}
276
+
cedarv_stream_data_info_t stream_data_info;
277
+
stream_data_info.type = 0;
278
+
stream_data_info.lengh = packet.size;
279
+
stream_data_info.pts = packet.pts;
280
+
stream_data_info.flags = CEDARV_FLAG_FIRST_PART | CEDARV_FLAG_LAST_PART | CEDARV_FLAG_PTS_VALID;
281
+
d.cedarv->update_data(d.cedarv, &stream_data_info);
282
+
if (d.cedarv->decode(d.cedarv) >= 0 && !d.cedarv->display_request(d.cedarv, &d.cedarPicture)) {
283
+
}
284
+
else {
285
+
if (d.cedarPicture.id) {
286
+
d.cedarv->display_release(d.cedarv, d.cedarPicture.id);
287
+
d.cedarPicture.id = 0;
288
+
}
289
+
}
290
+
}
291
+
return true;
292
+
}
293
+
294
+
295
+
VideoFrame VideoDecoderCedarv::frame()
296
+
{
297
+
DPTR_D(VideoDecoderCedarv);
298
+
if (!d.cedarPicture.id) {
299
+
return VideoFrame();
300
+
}
301
+
VideoFrame frame = VideoFrame(d.cedarPicture.width, d.cedarPicture.height, VideoFormat(VideoFormat::Format_YUV420P));
302
+
if ((unsigned int)d.y.size() != d.cedarPicture.size_y) {
303
+
d.y.resize(d.cedarPicture.size_y);
304
+
}
305
+
if ((unsigned int)d.u.size() != d.cedarPicture.size_u / 2) {
306
+
d.u.resize(d.cedarPicture.size_u / 2);
307
+
}
308
+
if ((unsigned int)d.v.size() != d.cedarPicture.size_u / 2) {
309
+
d.v.resize(d.cedarPicture.size_u / 2);
310
+
}
311
+
int bitsPerLine_Y = d.cedarPicture.size_y / d.cedarPicture.height;
312
+
int bitsPerRow_Y = d.cedarPicture.size_y / bitsPerLine_Y;
313
+
map32x32_to_yuv_Y(d.cedarPicture.y, (uchar *)d.y.data(), bitsPerLine_Y, bitsPerRow_Y);
314
+
map32x32_to_yuv_C(d.cedarPicture.u, (uchar *)d.u.data(), (uchar *)d.v.data(), bitsPerLine_Y / 2, bitsPerRow_Y / 2);
315
+
frame.setBits((uchar *)d.y.data(), 0);
316
+
frame.setBytesPerLine(d.cedarPicture.size_y / d.cedarPicture.height, 0);
317
+
frame.setBits((uchar *)d.u.data(), 1);
318
+
frame.setBytesPerLine(bitsPerLine_Y / 2, 1);
319
+
frame.setBits((uchar *)d.v.data(), 2);
320
+
frame.setBytesPerLine(bitsPerLine_Y / 2, 2);
321
+
322
+
d.cedarv->display_release(d.cedarv, d.cedarPicture.id);
323
+
d.cedarPicture.id = 0;
324
+
return frame;
325
+
}
326
+
327
+
328
+
} // namespace QtAV
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4