Mercurial > mplayer.hg
view libvo/vo_mpegpes.c @ 3603:baa8b0c0ff30
Removed unnecessary check after the protocol autodetection.
Now it will try to start streaming even if the autodetection failed.
This will allow to work with web server that doesn't report a
proper mime-type.
author | bertrand |
---|---|
date | Wed, 19 Dec 2001 09:02:52 +0000 |
parents | a44484066941 |
children | 8e157167cee5 |
line wrap: on
line source
#define PES_MAX_SIZE 2048 /* * Based on: * * test_av.c - Test program for new API * * Copyright (C) 2000 Ralph Metzler <ralph@convergence.de> * & Marcus Metzler <marcus@convergence.de> * for convergence integrated media GmbH * * libav - MPEG-PS multiplexer, part of ffmpeg * Copyright Gerard Lantau (see http://ffmpeg.sf.net) * */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include "config.h" #ifdef HAVE_DVB #include <sys/poll.h> #include <sys/ioctl.h> #include <stdio.h> #include <time.h> #include <unistd.h> #include <ost/dmx.h> #include <ost/frontend.h> #include <ost/sec.h> #include <ost/video.h> #include <ost/audio.h> #endif #include "config.h" #include "video_out.h" #include "video_out_internal.h" LIBVO_EXTERN (mpegpes) int vo_mpegpes_fd=-1; int vo_mpegpes_fd2=-1; #ifdef USE_LIBAVCODEC #ifdef USE_LIBAVCODEC_SO #include <libffmpeg/avcodec.h> #else #include "../libavcodec/avcodec.h" #endif static unsigned char *picture_buf=NULL; static unsigned char *outbuf=NULL; static int outbuf_size = 100000; static int s_pos_x,s_pos_y; static int d_pos_x,d_pos_y; static int osd_w,osd_h; static AVPicture picture; static AVCodec *codec=NULL; static AVCodecContext codec_context; extern int avcodec_inited; #endif static vo_info_t vo_info = { #ifdef HAVE_DVB "Mpeg-PES to DVB card", #else "Mpeg-PES file", #endif "mpegpes", "A'rpi", "" }; static uint32_t init(uint32_t s_width, uint32_t s_height, uint32_t width, uint32_t height, uint32_t fullscreen, char *title, uint32_t format) { #ifdef HAVE_DVB //|O_NONBLOCK if((vo_mpegpes_fd = open("/dev/ost/video",O_RDWR)) < 0){ perror("DVB VIDEO DEVICE: "); return -1; } if((vo_mpegpes_fd2 = open("/dev/ost/audio",O_RDWR|O_NONBLOCK)) < 0){ perror("DVB AUDIO DEVICE: "); return -1; } if ( (ioctl(vo_mpegpes_fd,VIDEO_SET_BLANK, false) < 0)){ perror("DVB VIDEO SET BLANK: "); return -1; } if ( (ioctl(vo_mpegpes_fd,VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY) < 0)){ perror("DVB VIDEO SELECT SOURCE: "); return -1; } #if 1 if ( (ioctl(vo_mpegpes_fd2,AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY) < 0)){ perror("DVB AUDIO SELECT SOURCE: "); return -1; } if ( (ioctl(vo_mpegpes_fd2,AUDIO_PLAY) < 0)){ perror("DVB AUDIO PLAY: "); return -1; } #else if ( (ioctl(vo_mpegpes_fd2,AUDIO_STOP,0) < 0)){ perror("DVB AUDIO STOP: "); return -1; } #endif if ( (ioctl(vo_mpegpes_fd,VIDEO_PLAY) < 0)){ perror("DVB VIDEO PLAY: "); return -1; } if ( (ioctl(vo_mpegpes_fd2,AUDIO_SET_AV_SYNC, false) < 0)){ perror("DVB AUDIO SET AV SYNC: "); return -1; } if ( (ioctl(vo_mpegpes_fd2,AUDIO_SET_MUTE, false) < 0)){ perror("DVB AUDIO SET MUTE: "); return -1; } #else vo_mpegpes_fd=open("grab.mpg",O_WRONLY|O_CREAT); if(vo_mpegpes_fd<0){ perror("vo_mpegpes"); return -1; } #endif #ifdef USE_LIBAVCODEC picture_buf=NULL; if(format==IMGFMT_YV12){ int size; if(!avcodec_inited){ avcodec_init(); avcodec_register_all(); avcodec_inited=1; } /* find the mpeg1 video encoder */ codec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO); if (!codec) { fprintf(stderr, "mpeg1 codec not found\n"); return -1; } memset(&codec_context,0,sizeof(codec_context)); codec_context.bit_rate=100000; // not used codec_context.frame_rate=25*FRAME_RATE_BASE; // !!!!! codec_context.gop_size=0; // I frames only codec_context.flags=CODEC_FLAG_QSCALE; codec_context.quality=1; // quality! 1..31 (1=best,slowest) #if 0 codec_context.width=width; codec_context.height=height; #else if(width<=352 && height<=288){ codec_context.width=352; codec_context.height=288; } else if(width<=352 && height<=576){ codec_context.width=352; codec_context.height=576; } else if(width<=480 && height<=576){ codec_context.width=480; codec_context.height=576; } else if(width<=544 && height<=576){ codec_context.width=544; codec_context.height=576; } else { codec_context.width=704; codec_context.height=576; } #endif osd_w=s_width; d_pos_x=(codec_context.width-(int)s_width)/2; if(d_pos_x<0){ s_pos_x=-d_pos_x;d_pos_x=0; osd_w=codec_context.width; } else s_pos_x=0; osd_h=s_height; d_pos_y=(codec_context.height-(int)s_height)/2; if(d_pos_y<0){ s_pos_y=-d_pos_y;d_pos_y=0; osd_h=codec_context.height; } else s_pos_y=0; printf("[vo] position mapping: %d;%d => %d;%d\n",s_pos_x,s_pos_y,d_pos_x,d_pos_y); /* open it */ if (avcodec_open(&codec_context, codec) < 0) { fprintf(stderr, "could not open codec\n"); return -1; } outbuf_size=10000+width*height; // must be enough! outbuf = malloc(outbuf_size); size = codec_context.width*codec_context.height; picture_buf = malloc((size * 3) / 2); /* size for YUV 420 */ memset(picture_buf,0,size); // clear Y memset(picture_buf+size,128,size/2); // clear UV picture.data[0] = picture_buf; picture.data[1] = picture.data[0] + size; picture.data[2] = picture.data[1] + size / 4; picture.linesize[0] = codec_context.width; picture.linesize[1] = codec_context.width / 2; picture.linesize[2] = codec_context.width / 2; } #endif return 0; } static const vo_info_t* get_info(void) { return &vo_info; } #ifdef USE_LIBAVCODEC static void draw_alpha(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){ int x,y; vo_draw_alpha_yv12(w,h,src,srca,stride, picture.data[0]+(x0+d_pos_x)+(y0+d_pos_y)*picture.linesize[0],picture.linesize[0]); } #endif static void draw_osd(void) { #ifdef USE_LIBAVCODEC if(picture_buf){ // YV12 only: vo_draw_text(osd_w,osd_h,draw_alpha); } #endif } static void my_write(unsigned char* data,int len){ #ifdef HAVE_DVB #define NFD 2 struct pollfd pfd[NFD]; // printf("write %d bytes \n",len); pfd[0].fd = vo_mpegpes_fd; pfd[0].events = POLLOUT; pfd[1].fd = vo_mpegpes_fd2; pfd[1].events = POLLOUT; while(len>0){ if (poll(pfd,NFD,1)){ if (pfd[0].revents & POLLOUT){ int ret=write(vo_mpegpes_fd,data,len); // printf("ret=%d \n",ret); if(ret<=0){ perror("write"); usleep(0); } else { len-=ret; data+=ret; } } else usleep(1000); } } #else write(vo_mpegpes_fd,data,len); // write to file #endif } static unsigned char pes_header[PES_MAX_SIZE]; void send_pes_packet(unsigned char* data,int len,int id,int timestamp){ int x; pes_header[0]=pes_header[1]=0; pes_header[2]=id>>8; pes_header[3]=id&255; while(1){ int payload_size=len+5; // data + PTS if(6+payload_size>PES_MAX_SIZE) payload_size=PES_MAX_SIZE-6; // construct PES header: (code from ffmpeg's libav) // startcode: // packetsize: pes_header[4]=(payload_size)>>8; pes_header[5]=(payload_size)&255; // stuffing: // presentation time stamp: x=(0x02 << 4) | (((timestamp >> 30) & 0x07) << 1) | 1; pes_header[6]=x; x=((((timestamp >> 15) & 0x7fff) << 1) | 1); pes_header[7]=x>>8; pes_header[8]=x&255; x=((((timestamp) & 0x7fff) << 1) | 1); pes_header[9]=x>>8; pes_header[10]=x&255; payload_size-=5; memcpy(&pes_header[6+5],data,payload_size); my_write(pes_header,6+5+payload_size); len-=payload_size; data+=payload_size; if(len<=0) break; } // printf("PES: draw frame! pts=%d size=%d \n",timestamp,len); } void send_lpcm_packet(unsigned char* data,int len,int id,int timestamp){ int x; pes_header[0]=pes_header[1]=0; pes_header[2]=1; pes_header[3]=0xBD; while(len>=4){ int payload_size; payload_size=PES_MAX_SIZE-6-20; // max possible data len if(payload_size>len) payload_size=len; payload_size&=(~3); // align! payload_size+=20; // PTS+headers //if(6+payload_size>PES_MAX_SIZE) payload_size=PES_MAX_SIZE-6; // construct PES header: (code from ffmpeg's libav) // startcode: // packetsize: pes_header[4]=(payload_size)>>8; pes_header[5]=(payload_size)&255; // stuffing: pes_header[6]=0x81; pes_header[7]=0x80; pes_header[8]=10; // hdrlen // presentation time stamp: x=(0x02 << 4) | (((timestamp >> 30) & 0x07) << 1) | 1; pes_header[9]=x; x=((((timestamp >> 15) & 0x7fff) << 1) | 1); pes_header[10]=x>>8; pes_header[11]=x&255; x=((((timestamp) & 0x7fff) << 1) | 1); pes_header[12]=x>>8; pes_header[13]=x&255; pes_header[14]= pes_header[15]= pes_header[16]= pes_header[17]= pes_header[18]=0xFF; // stuffing pes_header[19]=id; pes_header[20]=0x07; // dunnowhat pes_header[21]=0x00; pes_header[22]=0x04; pes_header[23]=0x0C; pes_header[24]=0x01; // LPCM id pes_header[25]=0x80; payload_size-=20; memcpy(&pes_header[6+20],data,payload_size); my_write(pes_header,6+20+payload_size); len-=payload_size; data+=payload_size; if(len<=0) break; } // printf("PES: draw frame! pts=%d size=%d \n",timestamp,len); } static uint32_t draw_frame(uint8_t * src[]) { vo_mpegpes_t *p=(vo_mpegpes_t *)src[0]; unsigned char *data=p->data; // int tmp=-1; send_pes_packet(p->data,p->size,p->id,p->timestamp); // video data // send_pes_packet(&tmp,0,0x1C0,p->timestamp+30000); // fake audio data return 0; } static void flip_page (void) { #ifdef USE_LIBAVCODEC if(picture_buf){ // YV12 only: int out_size; static int fno=0; /* encode the image */ out_size = avcodec_encode_video(&codec_context, outbuf, outbuf_size, &picture); send_pes_packet(outbuf,out_size,0x1E0,fno*(90000/25));++fno; // printf("frame size: %d \n",out_size); } #endif } static uint32_t draw_slice(uint8_t *srcimg[], int stride[], int w,int h,int x0,int y0) { #ifdef USE_LIBAVCODEC int y; unsigned char* s; unsigned char* d; x0+=d_pos_x; y0+=d_pos_y; if(x0+w>picture.linesize[0]) w=picture.linesize[0]-x0; // !! if(y0+h>codec_context.height) h=codec_context.height-y0; // Y s=srcimg[0]+s_pos_x+s_pos_y*stride[0]; d=picture.data[0]+x0+y0*picture.linesize[0]; for(y=0;y<h;y++){ memcpy(d,s,w); s+=stride[0]; d+=picture.linesize[0]; } w/=2;h/=2;x0/=2;y0/=2; // U s=srcimg[1]+(s_pos_x/2)+(s_pos_y/2)*stride[1]; d=picture.data[1]+x0+y0*picture.linesize[1]; for(y=0;y<h;y++){ memcpy(d,s,w); s+=stride[1]; d+=picture.linesize[1]; } // V s=srcimg[2]+(s_pos_x/2)+(s_pos_y/2)*stride[2]; d=picture.data[2]+x0+y0*picture.linesize[2]; for(y=0;y<h;y++){ memcpy(d,s,w); s+=stride[2]; d+=picture.linesize[2]; } #endif return 0; } static uint32_t query_format(uint32_t format) { if(format==IMGFMT_MPEGPES) return 1|256; #ifdef USE_LIBAVCODEC if(format==IMGFMT_YV12) return 1|256; #endif return 0; } static void uninit(void) { #ifdef USE_LIBAVCODEC if(picture_buf){ // YV12 only: free(outbuf); free(picture_buf); } #endif if(vo_mpegpes_fd>=0){ close(vo_mpegpes_fd);vo_mpegpes_fd=-1;} if(vo_mpegpes_fd2>=0){ close(vo_mpegpes_fd2);vo_mpegpes_fd2=-1;} } static void check_events(void) { }