Permalink
Browse files

Added cedarx decoder.

  • Loading branch information...
1 parent 7231c61 commit d7b428c1dae66b2a85b7a6bfa7b253980b5b963c @mireq committed Dec 16, 2013
View
@@ -30,7 +30,7 @@ win32 {
OptionalDepends += dxva
}
unix {
- OptionalDepends += xv vaapi
+ OptionalDepends += xv vaapi libcedarv
}
include(root.pri)
@@ -0,0 +1,5 @@
+CONFIG -= qt
+CONFIG += console
+SOURCES += main.cpp
+
+LIBS += -lvecore -lcedarv
@@ -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;
+}
View
@@ -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;
}
@@ -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;
View
@@ -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());
@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);
@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
@@ -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()
{
Oops, something went wrong.

0 comments on commit d7b428c

Please sign in to comment.