Mercurial > mplayer.hg
annotate libvo/vo_mpegpes.c @ 2575:37da7219ebaf
c optimizations
author | michael |
---|---|
date | Tue, 30 Oct 2001 22:03:25 +0000 |
parents | b2ce5d6d7d4f |
children | 3066369adb32 |
rev | line source |
---|---|
1939 | 1 #undef HAVE_DVB |
1876 | 2 #define PES_MAX_SIZE 2048 |
3 /* | |
4 * Based on: | |
5 * | |
6 * test_av.c - Test program for new API | |
7 * | |
8 * Copyright (C) 2000 Ralph Metzler <ralph@convergence.de> | |
9 * & Marcus Metzler <marcus@convergence.de> | |
10 * for convergence integrated media GmbH | |
11 * | |
12 * libav - MPEG-PS multiplexer, part of ffmpeg | |
13 * Copyright Gerard Lantau (see http://ffmpeg.sf.net) | |
14 * | |
15 */ | |
1871 | 16 |
17 #include <stdio.h> | |
18 #include <stdlib.h> | |
19 #include <string.h> | |
20 | |
1876 | 21 #include <sys/types.h> |
22 #include <sys/stat.h> | |
23 #include <fcntl.h> | |
24 | |
25 #ifdef HAVE_DVB | |
26 | |
2066
2b14cad013b7
using poll() only for DVB card - not required for file write
arpi
parents:
1986
diff
changeset
|
27 #include <sys/poll.h> |
2b14cad013b7
using poll() only for DVB card - not required for file write
arpi
parents:
1986
diff
changeset
|
28 |
1876 | 29 #include <sys/ioctl.h> |
30 #include <stdio.h> | |
31 #include <time.h> | |
32 #include <unistd.h> | |
33 | |
34 #include <ost/dmx.h> | |
35 #include <ost/frontend.h> | |
36 #include <ost/sec.h> | |
37 #include <ost/video.h> | |
38 #include <ost/audio.h> | |
39 | |
40 #endif | |
41 | |
1871 | 42 #include "config.h" |
43 #include "video_out.h" | |
44 #include "video_out_internal.h" | |
45 | |
46 LIBVO_EXTERN (mpegpes) | |
47 | |
1872 | 48 int vo_mpegpes_fd=-1; |
1876 | 49 int vo_mpegpes_fd2=-1; |
1872 | 50 |
1935 | 51 #ifdef USE_LIBAVCODEC |
52 | |
2496 | 53 #ifdef USE_LIBAVCODEC_SO |
54 #include <libffmpeg/avcodec.h> | |
55 #else | |
1935 | 56 #include "../libavcodec/avcodec.h" |
2496 | 57 #endif |
1935 | 58 static unsigned char *picture_buf=NULL; |
59 static unsigned char *outbuf=NULL; | |
60 static int outbuf_size = 100000; | |
61 | |
62 static int s_pos_x,s_pos_y; | |
63 static int d_pos_x,d_pos_y; | |
64 | |
1943 | 65 static int osd_w,osd_h; |
66 | |
1935 | 67 static AVPicture picture; |
68 static AVCodec *codec=NULL; | |
69 static AVCodecContext codec_context; | |
70 extern int avcodec_inited; | |
71 | |
72 #endif | |
73 | |
1871 | 74 static vo_info_t vo_info = |
75 { | |
1876 | 76 #ifdef HAVE_DVB |
77 "Mpeg-PES to DVB card", | |
78 #else | |
1871 | 79 "Mpeg-PES file", |
1876 | 80 #endif |
81 "mpegpes", | |
1871 | 82 "A'rpi", |
83 "" | |
84 }; | |
85 | |
86 static uint32_t | |
1935 | 87 init(uint32_t s_width, uint32_t s_height, uint32_t width, uint32_t height, uint32_t fullscreen, char *title, uint32_t format) |
1871 | 88 { |
1876 | 89 #ifdef HAVE_DVB |
90 //|O_NONBLOCK | |
91 if((vo_mpegpes_fd = open("/dev/ost/video",O_RDWR)) < 0){ | |
92 perror("DVB VIDEO DEVICE: "); | |
93 return -1; | |
94 } | |
95 if((vo_mpegpes_fd2 = open("/dev/ost/audio",O_RDWR|O_NONBLOCK)) < 0){ | |
96 perror("DVB AUDIO DEVICE: "); | |
97 return -1; | |
98 } | |
99 if ( (ioctl(vo_mpegpes_fd,VIDEO_SET_BLANK, false) < 0)){ | |
100 perror("DVB VIDEO SET BLANK: "); | |
101 return -1; | |
102 } | |
103 if ( (ioctl(vo_mpegpes_fd,VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY) < 0)){ | |
104 perror("DVB VIDEO SELECT SOURCE: "); | |
105 return -1; | |
106 } | |
107 #if 1 | |
108 if ( (ioctl(vo_mpegpes_fd2,AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY) < 0)){ | |
109 perror("DVB AUDIO SELECT SOURCE: "); | |
110 return -1; | |
111 } | |
112 if ( (ioctl(vo_mpegpes_fd2,AUDIO_PLAY) < 0)){ | |
113 perror("DVB AUDIO PLAY: "); | |
114 return -1; | |
115 } | |
116 #else | |
117 if ( (ioctl(vo_mpegpes_fd2,AUDIO_STOP,0) < 0)){ | |
118 perror("DVB AUDIO STOP: "); | |
119 return -1; | |
120 } | |
121 #endif | |
122 if ( (ioctl(vo_mpegpes_fd,VIDEO_PLAY) < 0)){ | |
123 perror("DVB VIDEO PLAY: "); | |
124 return -1; | |
125 } | |
126 if ( (ioctl(vo_mpegpes_fd2,AUDIO_SET_AV_SYNC, false) < 0)){ | |
127 perror("DVB AUDIO SET AV SYNC: "); | |
128 return -1; | |
129 } | |
130 if ( (ioctl(vo_mpegpes_fd2,AUDIO_SET_MUTE, false) < 0)){ | |
131 perror("DVB AUDIO SET MUTE: "); | |
132 return -1; | |
133 } | |
134 | |
135 #else | |
136 vo_mpegpes_fd=open("grab.mpg",O_WRONLY|O_CREAT); | |
1872 | 137 if(vo_mpegpes_fd<0){ |
138 perror("vo_mpegpes"); | |
139 return -1; | |
140 } | |
1876 | 141 #endif |
1935 | 142 |
143 #ifdef USE_LIBAVCODEC | |
144 picture_buf=NULL; | |
145 if(format==IMGFMT_YV12){ | |
146 int size; | |
147 | |
148 if(!avcodec_inited){ | |
149 avcodec_init(); | |
150 avcodec_register_all(); | |
151 avcodec_inited=1; | |
152 } | |
153 | |
154 /* find the mpeg1 video encoder */ | |
155 codec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO); | |
156 if (!codec) { | |
157 fprintf(stderr, "mpeg1 codec not found\n"); | |
158 return -1; | |
159 } | |
160 memset(&codec_context,0,sizeof(codec_context)); | |
161 codec_context.bit_rate=100000; // not used | |
162 codec_context.frame_rate=25*FRAME_RATE_BASE; // !!!!! | |
163 codec_context.gop_size=0; // I frames only | |
164 codec_context.flags=CODEC_FLAG_QSCALE; | |
1986 | 165 codec_context.quality=1; // quality! 1..31 (1=best,slowest) |
1935 | 166 |
167 #if 0 | |
168 codec_context.width=width; | |
169 codec_context.height=height; | |
170 #else | |
171 if(width<=352 && height<=288){ | |
172 codec_context.width=352; | |
173 codec_context.height=288; | |
174 } else | |
175 if(width<=352 && height<=576){ | |
176 codec_context.width=352; | |
177 codec_context.height=576; | |
178 } else | |
179 if(width<=480 && height<=576){ | |
180 codec_context.width=480; | |
181 codec_context.height=576; | |
182 } else | |
183 if(width<=544 && height<=576){ | |
184 codec_context.width=544; | |
185 codec_context.height=576; | |
186 } else { | |
187 codec_context.width=704; | |
188 codec_context.height=576; | |
189 } | |
190 #endif | |
191 | |
1943 | 192 osd_w=s_width; |
1935 | 193 d_pos_x=(codec_context.width-(int)s_width)/2; |
194 if(d_pos_x<0){ | |
195 s_pos_x=-d_pos_x;d_pos_x=0; | |
1943 | 196 osd_w=codec_context.width; |
1935 | 197 } else s_pos_x=0; |
198 | |
1943 | 199 osd_h=s_height; |
1935 | 200 d_pos_y=(codec_context.height-(int)s_height)/2; |
201 if(d_pos_y<0){ | |
202 s_pos_y=-d_pos_y;d_pos_y=0; | |
1943 | 203 osd_h=codec_context.height; |
1935 | 204 } else s_pos_y=0; |
1943 | 205 |
1935 | 206 printf("[vo] position mapping: %d;%d => %d;%d\n",s_pos_x,s_pos_y,d_pos_x,d_pos_y); |
207 | |
208 /* open it */ | |
209 if (avcodec_open(&codec_context, codec) < 0) { | |
210 fprintf(stderr, "could not open codec\n"); | |
211 return -1; | |
212 } | |
213 | |
214 outbuf_size=10000+width*height; // must be enough! | |
215 outbuf = malloc(outbuf_size); | |
216 | |
217 size = codec_context.width*codec_context.height; | |
218 picture_buf = malloc((size * 3) / 2); /* size for YUV 420 */ | |
219 | |
220 memset(picture_buf,0,size); // clear Y | |
221 memset(picture_buf+size,128,size/2); // clear UV | |
222 | |
223 picture.data[0] = picture_buf; | |
224 picture.data[1] = picture.data[0] + size; | |
225 picture.data[2] = picture.data[1] + size / 4; | |
226 picture.linesize[0] = codec_context.width; | |
227 picture.linesize[1] = codec_context.width / 2; | |
228 picture.linesize[2] = codec_context.width / 2; | |
229 | |
230 } | |
231 #endif | |
1871 | 232 return 0; |
233 } | |
234 | |
235 static const vo_info_t* | |
236 get_info(void) | |
237 { | |
238 return &vo_info; | |
239 } | |
240 | |
1943 | 241 #ifdef USE_LIBAVCODEC |
242 static void draw_alpha(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){ | |
243 int x,y; | |
244 vo_draw_alpha_yv12(w,h,src,srca,stride, | |
245 picture.data[0]+(x0+d_pos_x)+(y0+d_pos_y)*picture.linesize[0],picture.linesize[0]); | |
246 } | |
247 #endif | |
248 | |
1871 | 249 static void draw_osd(void) |
250 { | |
1943 | 251 #ifdef USE_LIBAVCODEC |
252 if(picture_buf){ // YV12 only: | |
253 vo_draw_text(osd_w,osd_h,draw_alpha); | |
254 } | |
255 #endif | |
1871 | 256 } |
257 | |
1876 | 258 |
1872 | 259 static void my_write(unsigned char* data,int len){ |
2066
2b14cad013b7
using poll() only for DVB card - not required for file write
arpi
parents:
1986
diff
changeset
|
260 #ifdef HAVE_DVB |
2b14cad013b7
using poll() only for DVB card - not required for file write
arpi
parents:
1986
diff
changeset
|
261 #define NFD 2 |
1876 | 262 struct pollfd pfd[NFD]; |
263 | |
264 // printf("write %d bytes \n",len); | |
265 | |
266 pfd[0].fd = vo_mpegpes_fd; | |
267 pfd[0].events = POLLOUT; | |
268 | |
269 pfd[1].fd = vo_mpegpes_fd2; | |
270 pfd[1].events = POLLOUT; | |
271 | |
1872 | 272 while(len>0){ |
1876 | 273 if (poll(pfd,NFD,1)){ |
274 if (pfd[0].revents & POLLOUT){ | |
275 int ret=write(vo_mpegpes_fd,data,len); | |
276 // printf("ret=%d \n",ret); | |
277 if(ret<=0){ | |
278 perror("write"); | |
279 usleep(0); | |
280 } else { | |
281 len-=ret; data+=ret; | |
282 } | |
283 } else usleep(1000); | |
284 } | |
1872 | 285 } |
2066
2b14cad013b7
using poll() only for DVB card - not required for file write
arpi
parents:
1986
diff
changeset
|
286 |
2b14cad013b7
using poll() only for DVB card - not required for file write
arpi
parents:
1986
diff
changeset
|
287 #else |
2b14cad013b7
using poll() only for DVB card - not required for file write
arpi
parents:
1986
diff
changeset
|
288 write(vo_mpegpes_fd,data,len); // write to file |
2b14cad013b7
using poll() only for DVB card - not required for file write
arpi
parents:
1986
diff
changeset
|
289 #endif |
1872 | 290 } |
1871 | 291 |
1876 | 292 static unsigned char pes_header[PES_MAX_SIZE]; |
293 | |
294 static void send_pes_packet(unsigned char* data,int len,int id,int timestamp){ | |
295 int x; | |
296 | |
297 pes_header[0]=pes_header[1]=0; | |
298 pes_header[2]=id>>8; pes_header[3]=id&255; | |
299 | |
300 while(1){ | |
301 int payload_size=len+5; // data + PTS | |
302 if(6+payload_size>PES_MAX_SIZE) payload_size=PES_MAX_SIZE-6; | |
303 | |
304 // construct PES header: (code from ffmpeg's libav) | |
305 // startcode: | |
306 // packetsize: | |
307 pes_header[4]=(payload_size)>>8; | |
308 pes_header[5]=(payload_size)&255; | |
309 // stuffing: | |
310 // presentation time stamp: | |
311 x=(0x02 << 4) | (((timestamp >> 30) & 0x07) << 1) | 1; | |
312 pes_header[6]=x; | |
313 x=((((timestamp >> 15) & 0x7fff) << 1) | 1); | |
314 pes_header[7]=x>>8; pes_header[8]=x&255; | |
315 x=((((timestamp) & 0x7fff) << 1) | 1); | |
316 pes_header[9]=x>>8; pes_header[10]=x&255; | |
317 | |
318 payload_size-=5; | |
319 memcpy(&pes_header[6+5],data,payload_size); | |
320 my_write(pes_header,6+5+payload_size); | |
321 | |
322 len-=payload_size; data+=payload_size; | |
323 if(len<=0) break; | |
324 } | |
325 | |
326 // printf("PES: draw frame! pts=%d size=%d \n",timestamp,len); | |
327 | |
328 } | |
329 | |
1871 | 330 static uint32_t draw_frame(uint8_t * src[]) |
331 { | |
1872 | 332 vo_mpegpes_t *p=(vo_mpegpes_t *)src[0]; |
1876 | 333 unsigned char *data=p->data; |
334 // int tmp=-1; | |
335 send_pes_packet(p->data,p->size,p->id,p->timestamp); // video data | |
336 // send_pes_packet(&tmp,0,0x1C0,p->timestamp+30000); // fake audio data | |
1871 | 337 |
338 return 0; | |
339 } | |
340 | |
1935 | 341 static void flip_page (void) |
342 { | |
343 #ifdef USE_LIBAVCODEC | |
344 if(picture_buf){ // YV12 only: | |
345 int out_size; | |
346 static int fno=0; | |
347 /* encode the image */ | |
348 out_size = avcodec_encode_video(&codec_context, outbuf, outbuf_size, &picture); | |
349 send_pes_packet(outbuf,out_size,0x1E0,fno*(90000/25));++fno; | |
350 // printf("frame size: %d \n",out_size); | |
351 } | |
352 #endif | |
353 } | |
354 | |
355 static uint32_t draw_slice(uint8_t *srcimg[], int stride[], int w,int h,int x0,int y0) | |
356 { | |
357 #ifdef USE_LIBAVCODEC | |
358 int y; | |
359 unsigned char* s; | |
360 unsigned char* d; | |
361 | |
362 x0+=d_pos_x; | |
363 y0+=d_pos_y; | |
1986 | 364 if(x0+w>picture.linesize[0]) w=picture.linesize[0]-x0; // !! |
365 if(y0+h>codec_context.height) h=codec_context.height-y0; | |
1935 | 366 |
367 // Y | |
368 s=srcimg[0]+s_pos_x+s_pos_y*stride[0]; | |
369 d=picture.data[0]+x0+y0*picture.linesize[0]; | |
370 for(y=0;y<h;y++){ | |
371 memcpy(d,s,w); | |
372 s+=stride[0]; | |
373 d+=picture.linesize[0]; | |
374 } | |
375 | |
376 w/=2;h/=2;x0/=2;y0/=2; | |
377 | |
378 // U | |
379 s=srcimg[1]+(s_pos_x/2)+(s_pos_y/2)*stride[1]; | |
380 d=picture.data[1]+x0+y0*picture.linesize[1]; | |
381 for(y=0;y<h;y++){ | |
382 memcpy(d,s,w); | |
383 s+=stride[1]; | |
384 d+=picture.linesize[1]; | |
385 } | |
386 | |
387 // V | |
388 s=srcimg[2]+(s_pos_x/2)+(s_pos_y/2)*stride[2]; | |
389 d=picture.data[2]+x0+y0*picture.linesize[2]; | |
390 for(y=0;y<h;y++){ | |
391 memcpy(d,s,w); | |
392 s+=stride[2]; | |
393 d+=picture.linesize[2]; | |
394 } | |
395 #endif | |
396 return 0; | |
397 } | |
398 | |
399 | |
1871 | 400 static uint32_t |
401 query_format(uint32_t format) | |
402 { | |
403 if(format==IMGFMT_MPEGPES) return 1; | |
1935 | 404 #ifdef USE_LIBAVCODEC |
405 if(format==IMGFMT_YV12) return 1; | |
406 #endif | |
1871 | 407 return 0; |
408 } | |
409 | |
410 static void | |
411 uninit(void) | |
412 { | |
1935 | 413 #ifdef USE_LIBAVCODEC |
414 if(picture_buf){ // YV12 only: | |
415 free(outbuf); | |
416 free(picture_buf); | |
417 } | |
418 #endif | |
1876 | 419 if(vo_mpegpes_fd>=0){ close(vo_mpegpes_fd);vo_mpegpes_fd=-1;} |
420 if(vo_mpegpes_fd2>=0){ close(vo_mpegpes_fd2);vo_mpegpes_fd2=-1;} | |
1871 | 421 } |
422 | |
423 | |
424 static void check_events(void) | |
425 { | |
426 } | |
427 |