[xiph-cvs] cvs commit: theora/lib toplevel.c

Mauricio Piacentini mauricio at xiph.org
Tue Jun 3 13:38:14 PDT 2003



mauricio    03/06/03 16:38:13

  Modified:    examples encoder_example.c
               include/theora theora.h
               lib      toplevel.c
  Log:
  this is a bitstream change!!! implementing a wiki TODO item
  added support for arbitrary pixel sizes encoded in the stream
  modified encoder_example file to support arbitrary frame sizes, centering the video window in a 16X16 canvas

Revision  Changes    Path
1.13      +73 -35    theora/examples/encoder_example.c

Index: encoder_example.c
===================================================================
RCS file: /usr/local/cvsroot/theora/examples/encoder_example.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- encoder_example.c	30 May 2003 20:40:16 -0000	1.12
+++ encoder_example.c	3 Jun 2003 20:38:13 -0000	1.13
@@ -12,7 +12,7 @@
 
   function: example encoder application; makes an Ogg Theora/Vorbis 
             file from YUV4MPEG2 and WAV input
-  last mod: $Id: encoder_example.c,v 1.12 2003/05/30 20:40:16 mauricio Exp $
+  last mod: $Id: encoder_example.c,v 1.13 2003/06/03 20:38:13 mauricio Exp $
 
  ********************************************************************/
 
@@ -39,9 +39,9 @@
 static double rint(double x)
 {
     if (x < 0.0)
-        (double)(int)(x - 0.5);
+        return (double)(int)(x - 0.5);
     else
-        (double)(int)(x + 0.5);
+        return (double)(int)(x + 0.5);
 }
 #endif
 
@@ -68,8 +68,11 @@
 
 int video_x=0;
 int video_y=0;
-int video_x_adj=0;
-int video_y_adj=0;
+/*added canvas and offset dimensions, support for arbitrary resolutions*/
+int video_x_canvas=0;
+int video_y_canvas=0;
+int video_x_offset=0;
+int video_y_offset=0;
 int video_hzn=0;
 int video_hzd=0;
 int video_an=0;
@@ -332,15 +335,27 @@
   /* You'll go to Hell for using static variables */
   static int          state=-1;
   static signed char *yuvframe[2];
+  static signed char *yuvcanvas[2];
   yuv_buffer          yuv;
   ogg_packet          op;
-  int i;
+  int i, e;
 
   if(state==-1){
-    /* initialize the double frame buffer */
+	/* initialize the double canvas buffer */
+    yuvcanvas[0]=malloc(video_x_canvas*video_y_canvas*3/2);
+    yuvcanvas[1]=malloc(video_x_canvas*video_y_canvas*3/2);
+
+	/* initialize the frame buffer, just a convenient way to parse YUVMPEG2*/
     yuvframe[0]=malloc(video_x*video_y*3/2);
     yuvframe[1]=malloc(video_x*video_y*3/2);
 
+	/*memset YUV canvas values, as canvas may be larger than actual video data*/
+	/*fill Y plane with 0x10 and UV planes with 0X80, for black data*/
+	memset(yuvcanvas[0],0x10,video_x_canvas*video_y_canvas);
+	memset(yuvcanvas[0]+video_x_canvas*video_y_canvas,0x80,video_x_canvas*video_y_canvas/2);
+	memset(yuvcanvas[1],0x10,video_x_canvas*video_y_canvas);
+	memset(yuvcanvas[1]+video_x_canvas*video_y_canvas,0x80,video_x_canvas*video_y_canvas/2);
+
     state=0;
   }
 
@@ -372,9 +387,32 @@
           exit(1);
         }
 
+	/*suck YUVMPEG4 frame from file to a buffer*/
         ret=fread(yuvframe[i],1,video_x*video_y*3/2,video);
-	if(ret!=video_x*video_y*3/2)break;
-	
+	  if(ret!=video_x*video_y*3/2) break;
+
+	/* copy YUV data aligning it to canvas size (multiple of 16) */
+	/* get and align Y plane first*/
+	for (e=0;e<video_y;e++){
+	  memcpy((yuvcanvas[i]+e*video_x_canvas)
+		  +video_x_canvas*video_y_offset + video_x_offset,
+		  yuvframe[i] +e*video_x
+		  ,video_x);
+	}
+	/* now get U plane*/
+	for (e=0;e<video_y/2;e++){
+	  memcpy((yuvcanvas[i]+(video_x_canvas*video_y_canvas)+e*video_x_canvas/2)
+		  +(video_x_canvas/2)*(video_y_offset/2) + video_x_offset/2,
+		  yuvframe[i]+(video_x*video_y)+e*video_x/2
+		  ,video_x/2);
+	}
+	/* finally get V plane*/
+	for (e=0;e<video_y/2;e++){
+	  memcpy((yuvcanvas[i]+(video_x_canvas*video_y_canvas*5/4)+e*video_x_canvas/2)
+		  +(video_x_canvas/2)*(video_y_offset/2) + video_x_offset/2,
+		  yuvframe[i]+(video_x*video_y*5/4)+e*video_x/2,video_x/2);
+	}
+
         state++;
       }
 
@@ -384,28 +422,21 @@
         exit(1);
       }
       
-      /* Theora is a one-frame-in,one-frame-out system; subit a frame
+      /* Theora is a one-frame-in,one-frame-out system; submit a frame
          for compression and pull out the packet */
       
-      /* center crop the input to a /16 size */
-      {
-	int x_adj= (video_x-video_x_adj)/2;
-	int y_adj= (video_y-video_y_adj)/2;
-
-	yuv.y_width=video_x_adj;
-	yuv.y_height=video_y_adj;
-	yuv.y_stride=video_x;
+	  {
+	yuv.y_width=video_x_canvas;
+	yuv.y_height=video_y_canvas;
+	yuv.y_stride=video_x_canvas;
         
-	yuv.uv_width=video_x_adj/2;
-	yuv.uv_height=video_y_adj/2;
-	yuv.uv_stride=video_x/2;
+	yuv.uv_width=video_x_canvas/2;
+	yuv.uv_height=video_y_canvas/2;
+	yuv.uv_stride=video_x_canvas/2;
         
-	yuv.y= yuvframe[0]+ 
-	  video_x*y_adj + x_adj;
-	yuv.u= yuvframe[0]+ video_x*video_y +
-	  (video_x/2)*(y_adj/2) + x_adj/2;
-	yuv.v= yuvframe[0]+ video_x*video_y*5/4 +
-	  (video_x/2)*(y_adj/2) + x_adj/2;
+	yuv.y= yuvcanvas[0];
+	yuv.u= yuvcanvas[0]+ video_x_canvas*video_y_canvas;
+	yuv.v= yuvcanvas[0]+ video_x_canvas*video_y_canvas*5/4 ;
       }
       
       theora_encode_YUVin(td,&yuv);
@@ -419,9 +450,9 @@
       ogg_stream_packetin(to,&op);
       
       {
-	signed char *temp=yuvframe[0];
-	yuvframe[0]=yuvframe[1];
-	yuvframe[1]=temp;
+	signed char *temp=yuvcanvas[0];
+	yuvcanvas[0]=yuvcanvas[1];
+	yuvcanvas[1]=temp;
         state--;
       }
       
@@ -537,12 +568,19 @@
     fprintf(stderr,"No video files submitted for compression?\n");
     exit(1);
   }
-  /* Theora has a divisible-by-sixteen restriction for encoding */
-  video_x_adj=(video_x>>4)<<4;
-  video_y_adj=(video_y>>4)<<4;
+  /* Theora has a divisible-by-sixteen restriction for encoding in the canvas */
+  /* get a larger canvas if input not divisible by 16, and calculate offsets*/
+  video_x_canvas=((video_x + 15) >>4)<<4;
+  video_y_canvas=((video_y + 15) >>4)<<4;
+  video_x_offset = (video_x_canvas-video_x)/2;
+  video_y_offset = (video_y_canvas-video_y)/2;
   
-  ti.width=video_x_adj;
-  ti.height=video_y_adj;
+  ti.width=video_x_canvas;
+  ti.height=video_y_canvas;
+  ti.pixel_width=video_x;
+  ti.pixel_height=video_y;
+  ti.x_offset=video_x_offset;
+  ti.y_offset=video_y_offset;
   ti.fps_numerator=video_hzn;
   ti.fps_denominator=video_hzd;
   ti.aspect_numerator=video_an;

<p><p>1.7       +5 -1      theora/include/theora/theora.h

Index: theora.h
===================================================================
RCS file: /usr/local/cvsroot/theora/include/theora/theora.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- theora.h	2 Jun 2003 19:07:08 -0000	1.6
+++ theora.h	3 Jun 2003 20:38:13 -0000	1.7
@@ -11,7 +11,7 @@
  ********************************************************************
 
   function: 
-  last mod: $Id: theora.h,v 1.6 2003/06/02 19:07:08 mauricio Exp $
+  last mod: $Id: theora.h,v 1.7 2003/06/03 20:38:13 mauricio Exp $
 
  ********************************************************************/
 
@@ -38,6 +38,10 @@
 typedef struct{
   ogg_uint32_t  width;
   ogg_uint32_t  height;
+  ogg_uint32_t  pixel_width;
+  ogg_uint32_t  pixel_height;
+  ogg_uint32_t  x_offset;
+  ogg_uint32_t  y_offset;
   ogg_uint32_t  fps_numerator;
   ogg_uint32_t  fps_denominator;
   ogg_uint32_t  aspect_numerator;

<p><p>1.19      +9 -1      theora/lib/toplevel.c

Index: toplevel.c
===================================================================
RCS file: /usr/local/cvsroot/theora/lib/toplevel.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -r1.18 -r1.19
--- toplevel.c	12 May 2003 22:23:03 -0000	1.18
+++ toplevel.c	3 Jun 2003 20:38:13 -0000	1.19
@@ -11,7 +11,7 @@
  ********************************************************************
 
   function: 
-  last mod: $Id: toplevel.c,v 1.18 2003/05/12 22:23:03 mauricio Exp $
+  last mod: $Id: toplevel.c,v 1.19 2003/06/03 20:38:13 mauricio Exp $
 
  ********************************************************************/
 
@@ -1038,6 +1038,10 @@
 
   oggpackB_write(&cpi->oggbuffer,cpi->pb.info.width>>4,16);
   oggpackB_write(&cpi->oggbuffer,cpi->pb.info.height>>4,16);
+  oggpackB_write(&cpi->oggbuffer,cpi->pb.info.pixel_width>>4,16);
+  oggpackB_write(&cpi->oggbuffer,cpi->pb.info.pixel_height>>4,16);
+  oggpackB_write(&cpi->oggbuffer,cpi->pb.info.x_offset>>4,16);
+  oggpackB_write(&cpi->oggbuffer,cpi->pb.info.y_offset>>4,16);
   oggpackB_write(&cpi->oggbuffer,cpi->pb.info.fps_numerator,32);
   oggpackB_write(&cpi->oggbuffer,cpi->pb.info.fps_denominator,32);
   oggpackB_write(&cpi->oggbuffer,cpi->pb.info.aspect_numerator,24);
@@ -1195,6 +1199,10 @@
 
   c->width=oggpackB_read(&opb,16)<<4;
   c->height=oggpackB_read(&opb,16)<<4;
+  c->pixel_width=oggpackB_read(&opb,16)<<4;
+  c->pixel_height=oggpackB_read(&opb,16)<<4;
+  c->x_offset=oggpackB_read(&opb,16)<<4;
+  c->y_offset=oggpackB_read(&opb,16)<<4;
   c->fps_numerator=oggpackB_read(&opb,32);
   c->fps_denominator=oggpackB_read(&opb,32);
   c->aspect_numerator=oggpackB_read(&opb,24);

<p><p>--- >8 ----
List archives:  http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the commits mailing list