changeset 1935:fcd39f3b13d4

YV12 support (using libavcodec for mpeg1-I encoding)
author arpi
date Sat, 22 Sep 2001 18:50:09 +0000
parents b024d0c98457
children f12f03796f04
files libvo/vo_mpegpes.c
diffstat 1 files changed, 173 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/libvo/vo_mpegpes.c	Sat Sep 22 15:43:52 2001 +0000
+++ b/libvo/vo_mpegpes.c	Sat Sep 22 18:50:09 2001 +0000
@@ -1,4 +1,4 @@
-//#define HAVE_DVB
+#define HAVE_DVB
 #define PES_MAX_SIZE 2048
 /* 
  * Based on:
@@ -47,6 +47,24 @@
 int vo_mpegpes_fd=-1;
 int vo_mpegpes_fd2=-1;
 
+#ifdef USE_LIBAVCODEC
+
+#include "../libavcodec/avcodec.h"
+
+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 AVPicture picture;
+static AVCodec *codec=NULL;
+static AVCodecContext codec_context;
+extern int avcodec_inited;
+
+#endif
+
 static vo_info_t vo_info = 
 {
 #ifdef HAVE_DVB
@@ -60,7 +78,7 @@
 };
 
 static uint32_t
-init(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t fullscreen, char *title, uint32_t format)
+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
@@ -115,6 +133,92 @@
 	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=2; // 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
+
+    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;
+    } else s_pos_x=0;
+
+    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;
+    } 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;
 }
 
@@ -128,15 +232,6 @@
 {
 }
 
-static void flip_page (void)
-{
-}
-
-static uint32_t draw_slice(uint8_t *srcimg[], int stride[], int w,int h,int x,int y)
-{
-    return 0;
-}
-
 #define NFD   2
 
 static void my_write(unsigned char* data,int len){
@@ -215,16 +310,83 @@
     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(w>picture.linesize[0]) w=picture.linesize[0]; // !!
+
+    // 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;
+#ifdef USE_LIBAVCODEC
+    if(format==IMGFMT_YV12) return 1;
+#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;}
 }