[xiph-commits] r16714 - in trunk/theora: examples include/theora lib

tterribe at svn.xiph.org tterribe at svn.xiph.org
Sat Nov 21 19:34:21 PST 2009


Author: tterribe
Date: 2009-11-21 19:34:21 -0800 (Sat, 21 Nov 2009)
New Revision: 16714

Modified:
   trunk/theora/examples/encoder_example.c
   trunk/theora/include/theora/theoraenc.h
   trunk/theora/lib/encode.c
Log:
Add API support for passing the encoder a buffer the size of the picture
 region, instead of the size of a full frame.
This was always possible with the 1.0 API, but now we'll do the pointer
 arithmetic so that applications don't have to.


Modified: trunk/theora/examples/encoder_example.c
===================================================================
--- trunk/theora/examples/encoder_example.c	2009-11-17 07:00:01 UTC (rev 16713)
+++ trunk/theora/examples/encoder_example.c	2009-11-22 03:34:21 UTC (rev 16714)
@@ -1016,8 +1016,6 @@
  th_enc_ctx *td,ogg_packet *op){
   int                        ret;
   int                        pic_sz;
-  int                        frame_c_w;
-  int                        frame_c_h;
   int                        c_w;
   int                        c_h;
   int                        c_sz;
@@ -1034,8 +1032,6 @@
     frame_state=0;
   }
   pic_sz=pic_w*pic_h;
-  frame_c_w=frame_w/dst_c_dec_h;
-  frame_c_h=frame_h/dst_c_dec_v;
   c_w=(pic_w+dst_c_dec_h-1)/dst_c_dec_h;
   c_h=(pic_h+dst_c_dec_v-1)/dst_c_dec_v;
   c_sz=c_w*c_h;
@@ -1124,22 +1120,21 @@
       else buf_pos+=ret;
     }
   }
-  /*We submit the buffer to the library as if it were padded, but we do not
-     actually allocate space for the padding.
-    This is okay, because with the 1.0 API the library will never read data from the padded
-     region.*/
-  ycbcr[0].width=frame_w;
-  ycbcr[0].height=frame_h;
+  /*We submit the buffer using the size of the picture region.
+    libtheora will pad the picture region out to the full frame size for us,
+     whether we pass in a full frame or not.*/
+  ycbcr[0].width=pic_w;
+  ycbcr[0].height=pic_h;
   ycbcr[0].stride=pic_w;
-  ycbcr[0].data=yuvframe[0]-pic_x-pic_y*pic_w;
-  ycbcr[1].width=frame_c_w;
-  ycbcr[1].height=frame_c_h;
+  ycbcr[0].data=yuvframe[0];
+  ycbcr[1].width=c_w;
+  ycbcr[1].height=c_h;
   ycbcr[1].stride=c_w;
-  ycbcr[1].data=yuvframe[0]+pic_sz-(pic_x/dst_c_dec_h)-(pic_y/dst_c_dec_v)*c_w;
-  ycbcr[2].width=frame_c_w;
-  ycbcr[2].height=frame_c_h;
+  ycbcr[1].data=yuvframe[0]+pic_sz;
+  ycbcr[2].width=c_w;
+  ycbcr[2].height=c_h;
   ycbcr[2].stride=c_w;
-  ycbcr[2].data=ycbcr[1].data+c_sz;
+  ycbcr[2].data=yuvframe[0]+pic_sz+c_sz;
   th_encode_ycbcr_in(td,ycbcr);
   {
     unsigned char *temp=yuvframe[0];

Modified: trunk/theora/include/theora/theoraenc.h
===================================================================
--- trunk/theora/include/theora/theoraenc.h	2009-11-17 07:00:01 UTC (rev 16713)
+++ trunk/theora/include/theora/theoraenc.h	2009-11-22 03:34:21 UTC (rev 16714)
@@ -441,11 +441,25 @@
 /**Submits an uncompressed frame to the encoder.
  * \param _enc   A #th_enc_ctx handle.
  * \param _ycbcr A buffer of Y'CbCr data to encode.
+ *               If the width and height of the buffer matches the frame size
+ *                the encoder was initialized with, the encoder will only
+ *                reference the portion inside the picture region.
+ *               Any data outside this region will be ignored, and need not map
+ *                to a valid address.
+ *               Alternatively, you can pass a buffer equal to the size of the
+ *                picture region, if this is less than the full frame size.
+ *               When using subsampled chroma planes, odd picture sizes or odd
+ *                picture offsets may require an unexpected chroma plane size,
+ *                and their use is generally discouraged, as they will not be
+ *                well-supported by players and other media frameworks.
+ *               See Section 4.4 of 
+ *                <a href="http://www.theora.org/doc/Theora.pdf">the Theora
+ *                specification</a> for details if you wish to use them anyway.
  * \retval 0         Success.
  * \retval TH_EFAULT \a _enc or \a _ycbcr is <tt>NULL</tt>.
- * \retval TH_EINVAL The buffer size does not match the frame size the encoder
- *                    was initialized with, or encoding has already
- *                    completed.*/
+ * \retval TH_EINVAL The buffer size matches neither the frame size nor the
+ *                    picture size the encoder was initialized with, or
+ *                    encoding has already completed.*/
 extern int th_encode_ycbcr_in(th_enc_ctx *_enc,th_ycbcr_buffer _ycbcr);
 /**Retrieves encoded video data packets.
  * This should be called repeatedly after each frame is submitted to flush any

Modified: trunk/theora/lib/encode.c
===================================================================
--- trunk/theora/lib/encode.c	2009-11-17 07:00:01 UTC (rev 16713)
+++ trunk/theora/lib/encode.c	2009-11-22 03:34:21 UTC (rev 16714)
@@ -1492,34 +1492,45 @@
   if(_enc==NULL||_img==NULL)return TH_EFAULT;
   if(_enc->packet_state==OC_PACKET_DONE)return TH_EINVAL;
   if(_enc->rc.twopass&&_enc->rc.twopass_buffer_bytes==0)return TH_EINVAL;
-  if((ogg_uint32_t)_img[0].width!=_enc->state.info.frame_width||
-   (ogg_uint32_t)_img[0].height!=_enc->state.info.frame_height){
-    return TH_EINVAL;
-  }
   hdec=!(_enc->state.info.pixel_fmt&1);
   vdec=!(_enc->state.info.pixel_fmt&2);
   cframe_width=_enc->state.info.frame_width>>hdec;
   cframe_height=_enc->state.info.frame_height>>vdec;
-  if(_img[1].width!=cframe_width||_img[2].width!=cframe_width||
-   _img[1].height!=cframe_height||_img[2].height!=cframe_height){
-    return TH_EINVAL;
+  cpic_x=_enc->state.info.pic_x>>hdec;
+  cpic_y=_enc->state.info.pic_y>>vdec;
+  cpic_width=(_enc->state.info.pic_x+_enc->state.info.pic_width+hdec>>hdec)
+   -cpic_x;
+  cpic_height=(_enc->state.info.pic_y+_enc->state.info.pic_height+vdec>>vdec)
+   -cpic_y;
+  /*Flip the input buffer upside down.*/
+  oc_ycbcr_buffer_flip(img,_img);
+  if((ogg_uint32_t)img[0].width!=_enc->state.info.frame_width||
+   (ogg_uint32_t)img[0].height!=_enc->state.info.frame_height||
+   img[1].width!=cframe_width||img[2].width!=cframe_width||
+   img[1].height!=cframe_height||img[2].height!=cframe_height){
+    /*The buffer does not match the frame size.
+      Check to see if it matches the picture size.*/
+    if((ogg_uint32_t)img[0].width!=_enc->state.info.pic_width||
+     (ogg_uint32_t)img[0].height!=_enc->state.info.pic_height||
+     img[1].width!=cpic_width||img[2].width!=cpic_width||
+     img[1].height!=cpic_height||img[2].height!=cpic_height){
+      /*It doesn't; we don't know how to handle it.*/
+      return TH_EINVAL;
+    }
+    /*Adjust the pointers to address a full frame.
+      We still only use the picture region, however.*/
+    img[0].data-=_enc->state.info.pic_y*img[0].stride+_enc->state.info.pic_x;
+    img[1].data-=cpic_y*img[1].stride+cpic_x;
+    img[2].data-=cpic_y*img[2].stride+cpic_x;
   }
   /*Step 2: Copy the input to our internal buffer.
     This lets us add padding, if necessary, so we don't have to worry about
      dereferencing possibly invalid addresses, and allows us to use the same
      strides and fragment offsets for both the input frame and the reference
      frames.*/
-  /*Flip the input buffer upside down.*/
-  oc_ycbcr_buffer_flip(img,_img);
   oc_img_plane_copy_pad(_enc->state.ref_frame_bufs[OC_FRAME_IO]+0,img+0,
    _enc->state.info.pic_x,_enc->state.info.pic_y,
    _enc->state.info.pic_width,_enc->state.info.pic_height);
-  cpic_x=_enc->state.info.pic_x>>hdec;
-  cpic_y=_enc->state.info.pic_y>>vdec;
-  cpic_width=(_enc->state.info.pic_x+_enc->state.info.pic_width+hdec>>hdec)
-   -cpic_x;
-  cpic_height=(_enc->state.info.pic_y+_enc->state.info.pic_height+vdec>>vdec)
-   -cpic_y;
   for(pli=1;pli<3;pli++){
     oc_img_plane_copy_pad(_enc->state.ref_frame_bufs[OC_FRAME_IO]+pli,img+pli,
      cpic_x,cpic_y,cpic_width,cpic_height);



More information about the commits mailing list