Add support for VDPAU video out, including hardware decoding.
[mplayer/glamo.git] / libmpcodecs / ve_nuv.c
blob0b670179cd08e0a964e02a9de8dcb3f55530a4f1
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
5 #include "config.h"
6 #include "mp_msg.h"
8 #include "m_option.h"
10 #include "codec-cfg.h"
11 #include "stream/stream.h"
12 #include "libmpdemux/demuxer.h"
13 #include "libmpdemux/stheader.h"
15 #include "stream/stream.h"
16 #include "libmpdemux/muxer.h"
18 #include "img_format.h"
19 #include "mp_image.h"
20 #include "vf.h"
22 #include "libmpdemux/nuppelvideo.h"
23 #include <lzo/lzo1x.h>
24 #include "native/rtjpegn.h"
26 #define LZO_AL(size) (((size) + (sizeof(long) - 1)) / sizeof(long))
27 #define LZO_IN_LEN (1024*1024L)
28 #define LZO_OUT_LEN (LZO_IN_LEN + LZO_IN_LEN / 64 + 16 + 3)
30 //===========================================================================//
32 struct vf_priv_s {
33 int raw; // Do not use RTjpeg
34 int lzo; // Use lzo
35 unsigned int l,c,q; // Mjpeg param
36 muxer_stream_t* mux;
37 uint8_t* buffer;
39 int buf_size;
40 int tbl_wrote;
41 lzo_byte *zbuffer;
42 long __LZO_MMODEL *zmem;
44 #define mux_v (vf->priv->mux)
46 struct vf_priv_s nuv_priv_dflt = {
47 0, // raw
48 1, // lzo
49 1,1, // l,c
50 255, // q
51 NULL,
52 NULL,
53 0,0,
54 NULL,NULL
57 m_option_t nuvopts_conf[]={
58 {"raw", &nuv_priv_dflt.raw, CONF_TYPE_FLAG, 0, 0, 1, NULL},
59 {"rtjpeg", &nuv_priv_dflt.raw, CONF_TYPE_FLAG, 0, 1, 0, NULL},
60 {"lzo", &nuv_priv_dflt.lzo, CONF_TYPE_FLAG, 0, 0, 1, NULL},
61 {"nolzo", &nuv_priv_dflt.lzo, CONF_TYPE_FLAG, 0, 1, 0, NULL},
62 {"q", &nuv_priv_dflt.q, CONF_TYPE_INT, M_OPT_RANGE,3,255, NULL},
63 {"l", &nuv_priv_dflt.l, CONF_TYPE_INT, M_OPT_RANGE,0,20, NULL},
64 {"c", &nuv_priv_dflt.c, CONF_TYPE_INT, M_OPT_RANGE,0,20, NULL},
65 {NULL, NULL, 0, 0, 0, 0, NULL}
66 };
68 //===========================================================================//
71 static int config(struct vf_instance_s* vf,
72 int width, int height, int d_width, int d_height,
73 unsigned int flags, unsigned int outfmt){
75 // We need a buffer wich can holda header and a whole YV12 picture
76 // or a RTJpeg table
77 vf->priv->buf_size = width*height*3/2+FRAMEHEADERSIZE;
78 if(vf->priv->buf_size < (int)(128*sizeof(long int) + FRAMEHEADERSIZE))
79 vf->priv->buf_size = 128*sizeof(long int) + FRAMEHEADERSIZE;
81 mux_v->bih->biWidth=width;
82 mux_v->bih->biHeight=height;
83 mux_v->bih->biSizeImage=mux_v->bih->biWidth*mux_v->bih->biHeight*(mux_v->bih->biBitCount/8);
84 mux_v->aspect = (float)d_width/d_height;
85 vf->priv->buffer = realloc(vf->priv->buffer,vf->priv->buf_size);
86 vf->priv->tbl_wrote = 0;
88 return 1;
91 static int control(struct vf_instance_s* vf, int request, void* data){
93 return CONTROL_UNKNOWN;
96 static int query_format(struct vf_instance_s* vf, unsigned int fmt){
97 if(fmt==IMGFMT_I420) return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW;
98 return 0;
101 static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts){
102 struct rtframeheader* ench = (struct rtframeheader*)vf->priv->buffer;
103 uint8_t* data = vf->priv->buffer + FRAMEHEADERSIZE;
104 uint8_t* zdata = vf->priv->zbuffer + FRAMEHEADERSIZE;
105 int len = 0, zlen = 0,r;
107 memset(vf->priv->buffer,0,FRAMEHEADERSIZE); // Reset the header
108 if(vf->priv->lzo)
109 memset(vf->priv->zbuffer,0,FRAMEHEADERSIZE);
111 // This has to be don here otherwise tv with sound doesn't work
112 if(!vf->priv->tbl_wrote) {
113 RTjpeg_init_compress((long int*)data,mpi->width,mpi->height,vf->priv->q);
114 RTjpeg_init_mcompress();
116 ench->frametype = 'D'; // compressor data
117 ench->comptype = 'R'; // compressor data for RTjpeg
118 ench->packetlength = 128*sizeof(long int);
120 le2me_rtframeheader(ench);
121 mux_v->buffer=vf->priv->buffer;
122 muxer_write_chunk(mux_v,FRAMEHEADERSIZE + 128*sizeof(long int), 0x10, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
123 vf->priv->tbl_wrote = 1;
124 memset(ench,0,FRAMEHEADERSIZE); // Reset the header
127 // Raw picture
128 if(vf->priv->raw) {
129 len = mpi->width*mpi->height*3/2;
130 // Try lzo ???
131 if(vf->priv->lzo) {
132 r = lzo1x_1_compress(mpi->planes[0],mpi->width*mpi->height*3/2,
133 zdata,&zlen,vf->priv->zmem);
134 if(r != LZO_E_OK) {
135 mp_msg(MSGT_VFILTER,MSGL_ERR,"LZO compress error\n");
136 zlen = 0;
140 if(zlen <= 0 || zlen > len) {
141 memcpy(data,mpi->planes[0],len);
142 ench->comptype = '0';
143 } else { // Use lzo only if it's littler
144 ench = (struct rtframeheader*)vf->priv->zbuffer;
145 ench->comptype = '3';
146 len = zlen;
149 } else { // RTjpeg compression
150 len = RTjpeg_mcompressYUV420(data,mpi->planes[0],vf->priv->l,
151 vf->priv->c);
152 if(len <= 0) {
153 mp_msg(MSGT_VFILTER,MSGL_ERR,"RTjpeg_mcompressYUV420 error (%d)\n",len);
154 return 0;
157 if(vf->priv->lzo) {
158 r = lzo1x_1_compress(data,len,zdata,&zlen,vf->priv->zmem);
159 if(r != LZO_E_OK) {
160 mp_msg(MSGT_VFILTER,MSGL_ERR,"LZO compress error\n");
161 zlen = 0;
165 if(zlen <= 0 || zlen > len)
166 ench->comptype = '1';
167 else {
168 ench = (struct rtframeheader*)vf->priv->zbuffer;
169 ench->comptype = '2';
170 len = zlen;
175 ench->frametype = 'V'; // video frame
176 ench->packetlength = len;
177 le2me_rtframeheader(ench);
178 mux_v->buffer=(void*)ench;
179 muxer_write_chunk(mux_v, len + FRAMEHEADERSIZE, 0x10, pts, pts);
180 return 1;
183 static void uninit(struct vf_instance_s* vf) {
185 if(vf->priv->buffer)
186 free(vf->priv->buffer);
187 if(vf->priv->zbuffer)
188 free(vf->priv->zbuffer);
189 if(vf->priv->zmem)
190 free(vf->priv->zmem);
194 //===========================================================================//
196 static int vf_open(vf_instance_t *vf, char* args){
197 vf->config=config;
198 vf->default_caps=VFCAP_CONSTANT;
199 vf->control=control;
200 vf->query_format=query_format;
201 vf->put_image=put_image;
202 vf->uninit = uninit;
203 vf->priv=malloc(sizeof(struct vf_priv_s));
204 memcpy(vf->priv, &nuv_priv_dflt,sizeof(struct vf_priv_s));
205 vf->priv->mux=(muxer_stream_t*)args;
207 mux_v->bih=calloc(1, sizeof(BITMAPINFOHEADER));
208 mux_v->bih->biSize=sizeof(BITMAPINFOHEADER);
209 mux_v->bih->biWidth=0;
210 mux_v->bih->biHeight=0;
211 mux_v->bih->biPlanes=1;
212 mux_v->bih->biBitCount=12;
213 mux_v->bih->biCompression = mmioFOURCC('N','U','V','1');
215 if(vf->priv->lzo) {
216 if(lzo_init() != LZO_E_OK) {
217 mp_msg(MSGT_VFILTER,MSGL_WARN,"LZO init failed: no lzo compression\n");
218 vf->priv->lzo = 0;
220 vf->priv->zbuffer = (lzo_bytep)malloc(FRAMEHEADERSIZE + LZO_OUT_LEN);
221 vf->priv->zmem = malloc(sizeof(long)*LZO_AL(LZO1X_1_MEM_COMPRESS));
224 return 1;
227 vf_info_t ve_info_nuv = {
228 "nuv encoder",
229 "nuv",
230 "Albeu",
231 "for internal use by mencoder",
232 vf_open
235 //===========================================================================//