[MPlayer-dev-eng] Patch: Improved raw encoding support in mencoder

Fredrik Kuivinen freku045 at student.liu.se
Wed Jan 30 00:36:52 CET 2002


Hi

-ovc raw in current cvs don't work very well. Neither mplayer (at least not 
without -vc) or virtualdub is able to play the resulting file. This patch fixes
mencoder so that it produces uncompressed avi files with rgb data in a form
that virtualdub, xanim and hopefully all other programs that handle avi files 
can play. However mplayer currently can't play these files (yet). 

Just realized that it wont be possible to create files with uncompressed yv12
data for example. Maybe adding a new video codec, something like rawrgb, to
mencoder is the right thing to do. Well I am sending this anyway to get some
feedback.

/ Fredrik Kuivinen

-------------- next part --------------
Index: mencoder.c
===================================================================
RCS file: /cvsroot/mplayer/main/mencoder.c,v
retrieving revision 1.75
diff -u -3 -p -r1.75 mencoder.c
--- mencoder.c	28 Jan 2002 07:29:17 -0000	1.75
+++ mencoder.c	29 Jan 2002 23:44:27 -0000
@@ -46,6 +46,8 @@ static char* banner_text=
 #include "dec_audio.h"
 #include "dec_video.h"
 
+#include "postproc/rgb2rgb.h"
+
 #ifdef HAVE_DIVX4ENCORE
 #include <encore2.h>
 #include "divx4_vbr.h"
@@ -191,6 +193,7 @@ static int cfg_include(struct config *co
 }
 
 static int parse_end_at(struct config *conf, const char* param);
+static uint8_t* flip_upside_down(uint8_t* dst, const uint8_t* src, int width, int height);
 
 #include "get_path.c"
 
@@ -521,10 +524,10 @@ for(i=0;i<CODECS_MAX_OUTFMT;i++){
     if(out_fmt==0xFFFFFFFF) continue;
     if(IMGFMT_IS_RGB(out_fmt) || IMGFMT_IS_BGR(out_fmt)) break;
     if(out_fmt==IMGFMT_YV12) break;
-    if(out_fmt==IMGFMT_I420) break;
-    if(out_fmt==IMGFMT_IYUV) break;
-    if(out_fmt==IMGFMT_YUY2) break;
-    if(out_fmt==IMGFMT_UYVY) break;
+    if(out_video_codec != VCODEC_RAW && out_fmt==IMGFMT_I420) break;
+    if(out_video_codec != VCODEC_RAW && out_fmt==IMGFMT_IYUV) break;
+    if(out_video_codec != VCODEC_RAW && out_fmt==IMGFMT_YUY2) break;
+    if(out_video_codec != VCODEC_RAW && out_fmt==IMGFMT_UYVY) break;
 }
 if(i>=CODECS_MAX_OUTFMT){
     mp_msg(MSGT_MENCODER,MSGL_FATAL,MSGTR_VOincompCodec);
@@ -655,20 +658,26 @@ case VCODEC_COPY:
 	mux_v->bih->biBitCount, mux_v->bih->biCompression);
     break;
 case VCODEC_RAW:
-    if (sh_video->bih)
-	mux_v->bih=sh_video->bih;
-    else
-    {
 	mux_v->bih=malloc(sizeof(BITMAPINFOHEADER));
 	mux_v->bih->biSize=sizeof(BITMAPINFOHEADER);
 	mux_v->bih->biWidth=sh_video->disp_w;
 	mux_v->bih->biHeight=sh_video->disp_h;
 	mux_v->bih->biCompression=0;
 	mux_v->bih->biPlanes=1;
-	mux_v->bih->biBitCount=24; // FIXME!!!
+	
+	if(IMGFMT_IS_RGB(out_fmt))
+        mux_v->bih->biBitCount = IMGFMT_RGB_DEPTH(out_fmt);    
+	else if(IMGFMT_IS_BGR(out_fmt))
+        mux_v->bih->biBitCount = IMGFMT_BGR_DEPTH(out_fmt);
+	else {
+        mux_v->bih->biBitCount = 24;
+        yuv2rgb_init(24, MODE_BGR);
+	}
+    
+    if(mux_v->bih->biBitCount == 32)
+        mux_v->bih->biBitCount = 24;
+
 	mux_v->bih->biSizeImage=mux_v->bih->biWidth*mux_v->bih->biHeight*(mux_v->bih->biBitCount/8);
-    }
-    mux_v->bih->biCompression=0;
     printf("videocodec: raw (%dx%d %dbpp fourcc=%x)\n",
 	mux_v->bih->biWidth, mux_v->bih->biHeight,
 	mux_v->bih->biBitCount, mux_v->bih->biCompression);
@@ -1275,16 +1284,50 @@ case VCODEC_COPY:
     if(skip_flag<=0) aviwrite_write_chunk(muxer,mux_v,muxer_f,in_size,(sh_video->ds->flags&1)?0x10:0);
     break;
 case VCODEC_RAW:
-    blit_frame=decode_video(&video_out,sh_video,start,in_size,0);
-    if(skip_flag>0) break;
-    if(!blit_frame){
-	// empty.
-	aviwrite_write_chunk(muxer,mux_v,muxer_f,0,0);
-	break;
-    }
-    mux_v->buffer = vo_image_ptr;
-    aviwrite_write_chunk(muxer,mux_v,muxer_f,mux_v->buffer_size,0x10);
-    break;
+ {
+     static uint8_t* raw_rgb_buffer = NULL;
+     static uint8_t* raw_rgb_buffer2 = NULL;
+        
+     if(!raw_rgb_buffer) {
+         raw_rgb_buffer = malloc(vo_w*vo_h*4);
+         raw_rgb_buffer2 = malloc(vo_w*vo_h*4);
+     }
+	    
+     blit_frame=decode_video(&video_out,sh_video,start,in_size,0);
+     if(skip_flag>0) break;
+     if(!blit_frame){
+         // empty.
+         aviwrite_write_chunk(muxer,mux_v,muxer_f,0,0);
+         break;
+     }
+
+     if(IMGFMT_IS_BGR(out_fmt)) {
+         if(IMGFMT_BGR_DEPTH(out_fmt) == 32) {
+             rgb32to24(vo_image_ptr, raw_rgb_buffer, vo_w*vo_h*4);
+             mux_v->buffer = flip_upside_down(raw_rgb_buffer, raw_rgb_buffer, vo_w*3, vo_h);
+         }
+         else
+             mux_v->buffer = flip_upside_down(raw_rgb_buffer, vo_image_ptr, vo_w*3, vo_h);
+     }
+     else if(IMGFMT_IS_RGB(out_fmt)) {
+         if(IMGFMT_RGB_DEPTH(out_fmt) == 32) {
+             rgb32tobgr32(vo_image_ptr, raw_rgb_buffer2, vo_w*vo_h*4);
+             rgb32to24(raw_rgb_buffer2, raw_rgb_buffer, vo_w*vo_h*4);
+             mux_v->buffer = flip_upside_down(raw_rgb_buffer, raw_rgb_buffer, vo_w*3, vo_h);
+         }
+         else
+             mux_v->buffer = flip_upside_down(raw_rgb_buffer, vo_image_ptr, vo_w*3, vo_h);
+     }
+     else {
+         yuv2rgb(raw_rgb_buffer, vo_image_ptr, vo_image_ptr + vo_w*vo_h*5/4, vo_image_ptr + vo_w*vo_h, 
+                 vo_w, vo_h, vo_w*24/8, vo_w, vo_w/2);
+         mux_v->buffer = flip_upside_down(raw_rgb_buffer, raw_rgb_buffer, vo_w*3, vo_h);
+     }
+
+     
+     aviwrite_write_chunk(muxer,mux_v,muxer_f, vo_w*vo_h*3, 0x10);  // mux_v->buffer_size,0x10);
+ }
+ break;
 case VCODEC_FRAMENO: {
     mux_v->buffer=&decoded_frameno; // tricky
     if(skip_flag<=0) aviwrite_write_chunk(muxer,mux_v,muxer_f,sizeof(int),0x10);
@@ -1437,7 +1480,7 @@ if(sh_audio && !demuxer2){
 	    (p>0.001) ? (int)(ftell(muxer_f)/p/1024/1024) : 0,
 	    v_pts_corr,
 	    (mux_v->timer>1) ? (int)(mux_v->size/mux_v->timer/125) : 0,
-	    (mux_a->timer>1) ? (int)(mux_a->size/mux_a->timer/125) : 0
+	    (mux_a && mux_a->timer>1) ? (int)(mux_a->size/mux_a->timer/125) : 0
 	);
 #endif
     }
@@ -1537,4 +1580,22 @@ static int parse_end_at(struct config *c
         return ERR_FUNC_ERR;
 
     return 1;
+}
+
+/* Flip the image in src and store the result in dst. src and dst may overlap.
+   width is the size of each line in bytes. */
+static uint8_t* flip_upside_down(uint8_t* dst, const uint8_t* src, int width,
+                                 int height)
+{
+    uint8_t* tmp = malloc(width);
+    int i;
+
+    for(i = 0; i < height/2; i++) {
+        memcpy(tmp, &src[i*width], width);
+        memcpy(&dst[i * width], &src[(height - i) * width], width);
+        memcpy(&dst[(height - i) * width], tmp, width);
+    }
+
+    free(tmp);
+    return dst;
 }


More information about the MPlayer-dev-eng mailing list