Skip to content

Commit

Permalink
Added cedarx decoder.
Browse files Browse the repository at this point in the history
  • Loading branch information
mireq committed Dec 16, 2013
1 parent 7231c61 commit d7b428c
Show file tree
Hide file tree
Showing 8 changed files with 370 additions and 1 deletion.
2 changes: 1 addition & 1 deletion QtAV.pro
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ win32 {
OptionalDepends += dxva
}
unix {
OptionalDepends += xv vaapi
OptionalDepends += xv vaapi libcedarv
}

include(root.pri)
Expand Down
5 changes: 5 additions & 0 deletions config.tests/libcedarv/libcedardrv.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
CONFIG -= qt
CONFIG += console
SOURCES += main.cpp

LIBS += -lvecore -lcedarv
26 changes: 26 additions & 0 deletions config.tests/libcedarv/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/******************************************************************************
QtAV: Media play library based on Qt and FFmpeg
Copyright (C) 2013 Wang Bin <wbsecg1@gmail.com>
* This file is part of QtAV
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
#include <libcedarv/libcedarv.h>

int main()
{
return 0;
}
3 changes: 3 additions & 0 deletions src/AVPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ AVPlayer::AVPlayer(QObject *parent) :
#if QTAV_HAVE(VAAPI)
<< VideoDecoderId_VAAPI
#endif //QTAV_HAVE(VAAPI)
#if QTAV_HAVE(CEDARV)
<< VideoDecoderId_Cedarv
#endif //QTAV_HAVE(CEDARV)
<< VideoDecoderId_FFmpeg;
}

Expand Down
1 change: 1 addition & 0 deletions src/QtAV/VideoDecoderTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ extern Q_AV_EXPORT VideoDecoderId VideoDecoderId_FFmpeg;
extern Q_AV_EXPORT VideoDecoderId VideoDecoderId_CUDA;
extern Q_AV_EXPORT VideoDecoderId VideoDecoderId_DXVA;
extern Q_AV_EXPORT VideoDecoderId VideoDecoderId_VAAPI;
extern Q_AV_EXPORT VideoDecoderId VideoDecoderId_Cedarv;
extern Q_AV_EXPORT VideoDecoderId VideoDecoderId_FFmpeg_VDPAU;
extern Q_AV_EXPORT VideoDecoderId VideoDecoderId_FFmpeg_VDA;

Expand Down
328 changes: 328 additions & 0 deletions src/VideoDecoderCedarv.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,328 @@
/******************************************************************************
QtAV: Media play library based on Qt and FFmpeg
Copyright (C) 2013 Wang Bin <wbsecg1@gmail.com>
* This file is part of QtAV
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/

#include "QtAV/VideoDecoderFFmpeg.h"
#include "private/VideoDecoderFFmpeg_p.h"
#include <QtAV/Packet.h>
#include <QtAV/QtAV_Compat.h>
#include "prepost.h"

#include <QDebug>

#include <libavcodec/avcodec.h>
extern "C"
{
#include <libcedarv/libcedarv.h>
}

static void map32x32_to_yuv_Y(unsigned char* srcY, unsigned char* tarY, unsigned int coded_width, unsigned int coded_height)
{
unsigned int i,j,l,m,n;
unsigned int mb_width,mb_height,twomb_line,recon_width;
unsigned long offset;
unsigned char *ptr;

ptr = srcY;
mb_width = (coded_width+15)>>4;
mb_height = (coded_height+15)>>4;
twomb_line = (mb_height+1)>>1;
recon_width = (mb_width+1)&0xfffffffe;

for(i=0;i<twomb_line;i++)
{
for(j=0;j<recon_width;j+=2)
{
for(l=0;l<32;l++)
{
//first mb
m=i*32 + l;
n= j*16;
if(m<coded_height && n<coded_width)
{
offset = m*coded_width + n;
memcpy(tarY+offset,ptr,16);
ptr += 16;
}
else
ptr += 16;

//second mb
n= j*16+16;
if(m<coded_height && n<coded_width)
{
offset = m*coded_width + n;
memcpy(tarY+offset,ptr,16);
ptr += 16;
}
else
ptr += 16;
}
}
}
}

static void map32x32_to_yuv_C(unsigned char* srcC,unsigned char* tarCb,unsigned char* tarCr,unsigned int coded_width,unsigned int coded_height)
{
/*
unsigned int i,j,k;
for (i = 0; i < coded_width; ++i) {
k = i * coded_width;
for (j = 0; j < coded_height; ++j) {
*(tarCb + k) = srcC[2*k];
*(tarCr + k) = srcC[2*k+1];
k++;
}
}
*/
unsigned int i,j,l,m,n,k;
unsigned int mb_width,mb_height,fourmb_line,recon_width;
unsigned char line[16];
unsigned long offset;
unsigned char *ptr;

ptr = srcC;
mb_width = (coded_width+7)>>3;
mb_height = (coded_height+7)>>3;
fourmb_line = (mb_height+3)>>2;
recon_width = (mb_width+1)&0xfffffffe;

for(i=0;i<fourmb_line;i++)
{
for(j=0;j<recon_width;j+=2)
{
for(l=0;l<32;l++)
{
//first mb
m=i*32 + l;
n= j*8;
if(m<coded_height && n<coded_width)
{
offset = m*coded_width + n;
memcpy(line,ptr,16);
for(k=0;k<8;k++)
{
*(tarCb + offset + k) = line[2*k];
*(tarCr + offset + k) = line[2*k+1];
}
ptr += 16;
}
else
ptr += 16;

//second mb
n= j*8+8;
if(m<coded_height && n<coded_width)
{
offset = m*coded_width + n;
memcpy(line,ptr,16);
for(k=0;k<8;k++)
{
*(tarCb + offset + k) = line[2*k];
*(tarCr + offset + k) = line[2*k+1];
}
ptr += 16;
}
else
ptr += 16;
}
}
}
}

namespace QtAV {

class VideoDecoderCedarvPrivate;
class VideoDecoderCedarv : public VideoDecoderFFmpeg
{
DPTR_DECLARE_PRIVATE(VideoDecoderCedarv)
public:
VideoDecoderCedarv();
bool prepare();
bool decode(const QByteArray &encoded);
VideoFrame frame();
};

extern VideoDecoderId VideoDecoderId_Cedarv;
FACTORY_REGISTER_ID_AUTO(VideoDecoder, Cedarv, "Cedarv")

void RegisterVideoDecoderCedarv_Man()
{
FACTORY_REGISTER_ID_MAN(VideoDecoder, Cedarv, "Cedarv")
}

class VideoDecoderCedarvPrivate : public VideoDecoderFFmpegPrivate
{
public:
VideoDecoderCedarvPrivate() {
cedarv = 0;
}

~VideoDecoderCedarvPrivate() {
//TODO:
}

CEDARV_DECODER *cedarv;
cedarv_picture_t cedarPicture;
QByteArray y;
QByteArray u;
QByteArray v;
};

VideoDecoderCedarv::VideoDecoderCedarv()
: VideoDecoderFFmpeg(*new VideoDecoderCedarvPrivate())
{
}


bool VideoDecoderCedarv::prepare()
{
DPTR_D(VideoDecoderCedarv);
if (!d.cedarv) {
int ret;
d.cedarv = libcedarv_init(&ret);
if (ret < 0 || d.cedarv == NULL)
return false;
}

d.codec_ctx->opaque = &d; //is it ok?

cedarv_stream_info_t cedarStreamInfo;
memset(&cedarStreamInfo, 0, sizeof cedarStreamInfo);

switch (d.codec_ctx->codec_id) {
case AV_CODEC_ID_H264:
cedarStreamInfo.format = CEDARV_STREAM_FORMAT_H264;
break;
case AV_CODEC_ID_VP8:
cedarStreamInfo.format = CEDARV_STREAM_FORMAT_VP8;
break;
case AV_CODEC_ID_VC1:
cedarStreamInfo.format = CEDARV_STREAM_FORMAT_VC1;
break;
case AV_CODEC_ID_MPEG4:
cedarStreamInfo.format = CEDARV_STREAM_FORMAT_MPEG4;
cedarStreamInfo.sub_format = CEDARV_MPEG4_SUB_FORMAT_XVID;
break;
case AV_CODEC_ID_MPEG2VIDEO:
cedarStreamInfo.format = CEDARV_STREAM_FORMAT_MPEG2;
break;
case AV_CODEC_ID_RV40:
cedarStreamInfo.format = CEDARV_STREAM_FORMAT_REALVIDEO;
break;
default:
return false;
}
cedarStreamInfo.video_width = d.codec_ctx->width;
cedarStreamInfo.video_height = d.codec_ctx->height;
if (d.codec_ctx->extradata_size) {
cedarStreamInfo.init_data = d.codec_ctx->extradata;
cedarStreamInfo.init_data_len = d.codec_ctx->extradata_size;
}

int cedarvRet;
cedarvRet = d.cedarv->set_vstream_info(d.cedarv, &cedarStreamInfo);
if (cedarvRet < 0)
return false;
cedarvRet = d.cedarv->open(d.cedarv);
if (cedarvRet < 0)
return false;

d.cedarv->ioctrl(d.cedarv, CEDARV_COMMAND_PLAY, 0);

return true;
}

bool VideoDecoderCedarv::decode(const QByteArray &encoded)
{
DPTR_D(VideoDecoderCedarv);

//d.cedarv->ioctrl(d.cedarv, CEDARV_COMMAND_JUMP, 0);

AVPacket packet;
av_new_packet(&packet, encoded.size());
memcpy(packet.data, encoded.data(), encoded.size());

This comment has been minimized.

Copy link
@wang-bin

wang-bin Mar 7, 2014

encoded.constData(). data() may result in a deep copy in QByteArray


if (packet.size == 0) {
return true;
}

u32 bufsize0, bufsize1;
u8 *buf0, *buf1;

if (d.cedarv->request_write(d.cedarv, packet.size, &buf0, &bufsize0, &buf1, &bufsize1) >= 0) {
memcpy(buf0, packet.data, bufsize0);
if ((u32)packet.size > bufsize0) {
memcpy(buf1, packet.data + bufsize0, bufsize1);
}
cedarv_stream_data_info_t stream_data_info;
stream_data_info.type = 0;
stream_data_info.lengh = packet.size;
stream_data_info.pts = packet.pts;
stream_data_info.flags = CEDARV_FLAG_FIRST_PART | CEDARV_FLAG_LAST_PART | CEDARV_FLAG_PTS_VALID;
d.cedarv->update_data(d.cedarv, &stream_data_info);
if (d.cedarv->decode(d.cedarv) >= 0 && !d.cedarv->display_request(d.cedarv, &d.cedarPicture)) {
}
else {
if (d.cedarPicture.id) {
d.cedarv->display_release(d.cedarv, d.cedarPicture.id);
d.cedarPicture.id = 0;
}
}
}
return true;
}


VideoFrame VideoDecoderCedarv::frame()
{
DPTR_D(VideoDecoderCedarv);
if (!d.cedarPicture.id) {
return VideoFrame();
}
VideoFrame frame = VideoFrame(d.cedarPicture.width, d.cedarPicture.height, VideoFormat(VideoFormat::Format_YUV420P));
if ((unsigned int)d.y.size() != d.cedarPicture.size_y) {
d.y.resize(d.cedarPicture.size_y);
}
if ((unsigned int)d.u.size() != d.cedarPicture.size_u / 2) {
d.u.resize(d.cedarPicture.size_u / 2);
}
if ((unsigned int)d.v.size() != d.cedarPicture.size_u / 2) {
d.v.resize(d.cedarPicture.size_u / 2);
}
int bitsPerLine_Y = d.cedarPicture.size_y / d.cedarPicture.height;
int bitsPerRow_Y = d.cedarPicture.size_y / bitsPerLine_Y;
map32x32_to_yuv_Y(d.cedarPicture.y, (uchar *)d.y.data(), bitsPerLine_Y, bitsPerRow_Y);
map32x32_to_yuv_C(d.cedarPicture.u, (uchar *)d.u.data(), (uchar *)d.v.data(), bitsPerLine_Y / 2, bitsPerRow_Y / 2);
frame.setBits((uchar *)d.y.data(), 0);

This comment has been minimized.

Copy link
@wang-bin

wang-bin Mar 7, 2014

store QByteArray y, u, v in VideoDecoderCedarvPrivate is not a good idea. frame.setBits() only set the address, no data copying. So the content of the address points to may be invalid when the frame is to be displayed.
A better solution is like this:

QByteArray buf(y_size+u_size+v_size, 0);
uchar* dst = buf.data();
map32x32_to_yuv_Y(d.cedarPicture.y, dst, bitsPerLine_Y, bitsPerRow_Y);
map32x32_to_yuv_C(d.cedarPicture.u, dst+y_size, dst+y_size+u_size, .....);
VideFrame frame(buf, d.cedarPicture.width, d.cedarPicture.height, VideoFormat::Format_YUV420P);
frame.setBits(dst, 0);
frame.setBits(dst+y_size,1);
frame.setBits(dst+y_size+u_size,2);
...
frame.setBytesPerLine(d.cedarPicture.size_y / d.cedarPicture.height, 0);
frame.setBits((uchar *)d.u.data(), 1);
frame.setBytesPerLine(bitsPerLine_Y / 2, 1);
frame.setBits((uchar *)d.v.data(), 2);
frame.setBytesPerLine(bitsPerLine_Y / 2, 2);

d.cedarv->display_release(d.cedarv, d.cedarPicture.id);
d.cedarPicture.id = 0;
return frame;
}


} // namespace QtAV
1 change: 1 addition & 0 deletions src/VideoDecoderTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ VideoDecoderId VideoDecoderId_FFmpeg = 1;
VideoDecoderId VideoDecoderId_CUDA = 2;
VideoDecoderId VideoDecoderId_DXVA = 3;
VideoDecoderId VideoDecoderId_VAAPI = 4;
VideoDecoderId VideoDecoderId_Cedarv = 5;

QVector<VideoDecoderId> GetRegistedVideoDecoderIds()
{
Expand Down
Loading

0 comments on commit d7b428c

Please sign in to comment.