[xiph-commits] r11682 - in trunk/theora-exp: lib unix

tterribe at svn.xiph.org tterribe at svn.xiph.org
Sat Jul 1 07:53:21 PDT 2006


Author: tterribe
Date: 2006-07-01 07:53:19 -0700 (Sat, 01 Jul 2006)
New Revision: 11682

Modified:
   trunk/theora-exp/lib/apiwrapper.c
   trunk/theora-exp/unix/Makefile
Log:
Fixes for the libtheora decode API wrapper.
Formatting now matches the rest of the code.
Functional fixes:
- The lifetime of the theora_info and thera_state structs are now completely
   independent.
  You can clear your info struct as soon as you initialize a decoder, or
   initialize multiple decoders from a single info struct.
- The decoder is initialized from the values in the actual theora_info struct
   passed to the API, not the internal th_info struct filled in by
   th_decode_headerin().
  This should support whatever kinds of cleverness someone who is not using the
   Ogg encapsulation might come up with to avoid constructing header packets.

Currently only tested with libtheora's player_example.


Modified: trunk/theora-exp/lib/apiwrapper.c
===================================================================
--- trunk/theora-exp/lib/apiwrapper.c	2006-06-29 23:36:24 UTC (rev 11681)
+++ trunk/theora-exp/lib/apiwrapper.c	2006-07-01 14:53:19 UTC (rev 11682)
@@ -2,232 +2,239 @@
 #include <string.h>
 #include <limits.h>
 #include <ogg/ogg.h>
-
-/* libtheora header */
+/*libtheora header.
+  TODO: We should provide our own copy.*/
 #include <theora/theora.h>
-
-/* theora-exp header */
+/*theora-exp header.*/
 #include "theora/theoradec.h"
+/*For oc_ilog et al.*/
+#include "internal.h"
 
-/* TODO: Use appropriate allocation functions? */
+typedef struct th_api_wrapper th_api_wrapper;
 
-typedef struct {
-  th_info info;
-
+/*Generally only one of these pointers will be non-NULL in any given instance.
+  Technically we do not even really need this struct, since we should be able
+   to figure out which one from "context", but doing it this way makes sure we
+   don't flub it up.
+  It also means eventually adding encode support will work in the obvious
+   manner; theora_clear() does NOT provide enough context to distinguish
+   between an encoder and decoder without something like this.*/
+struct th_api_wrapper{
   th_setup_info *setup;
+  th_dec_ctx    *decode;
+};
 
-  th_dec_ctx *decode;
+const char *theora_version_string(void){
+  return th_version_string();
+}
 
-} th_api_wrapper;
+ogg_uint32_t theora_version_number(void){
+  return th_version_number();
+}
 
-const char *theora_version_string(void) {
-    return th_version_string();
+void theora_info_init(theora_info *_ci){
+  th_api_wrapper *api;
+  api=(th_api_wrapper *)_ogg_calloc(1,sizeof(*api));
+  memset(_ci,0,sizeof(*_ci));
+  _ci->codec_setup=api;
 }
 
-ogg_uint32_t theora_version_number(void) {
-    return th_version_number();
+void theora_info_clear(theora_info *_ci){
+  th_api_wrapper *api;
+  api=(th_api_wrapper *)_ci->codec_setup;
+  if(api->setup)th_setup_free(api->setup);
+  if(api->decode)th_decode_free(api->decode);
+  free(api);
+  memset(_ci,0,sizeof(*_ci));
 }
 
-void theora_info_init(theora_info *c)
-{
-    th_api_wrapper *api = calloc(1, sizeof(th_api_wrapper));
-
-    memset(c, 0, sizeof(theora_info));
-
-    c->codec_setup = api;
-
-    th_info_init(&api->info);
+void theora_clear(theora_state *_td){
+  if(_td->i!=NULL){
+    theora_info_clear(_td->i);
+    _ogg_free(_td->i);
+    _td->i=NULL;
+  }
 }
 
-void theora_info_clear (theora_info *c)
-{
-    th_api_wrapper *api = (th_api_wrapper *)c->codec_setup;
-
-    if (api->setup)
-        th_setup_free(api->setup);
-
-    if (api->decode)
-        th_decode_free(api->decode);
-
-    th_info_clear(&api->info);
-
-    free (c->codec_setup);
-    
-    memset(c, 0, sizeof(theora_info));
+static void theora_info2th_info(th_info *_info,const theora_info *_ci){
+  _info->version_major=_ci->version_major;
+  _info->version_minor=_ci->version_minor;
+  _info->version_subminor=_ci->version_subminor;
+  _info->frame_width=_ci->width;
+  _info->frame_height=_ci->height;
+  _info->pic_width=_ci->frame_width;
+  _info->pic_height=_ci->frame_height;
+  _info->pic_x=_ci->offset_x;
+  _info->pic_y=_ci->offset_y;
+  _info->fps_numerator=_ci->fps_numerator;
+  _info->fps_denominator=_ci->fps_denominator;
+  _info->aspect_numerator=_ci->aspect_numerator;
+  _info->aspect_denominator=_ci->aspect_denominator;
+  switch(_ci->colorspace){
+    case OC_CS_ITU_REC_470M:_info->colorspace=TH_CS_ITU_REC_470M;break;
+    case OC_CS_ITU_REC_470BG:_info->colorspace=TH_CS_ITU_REC_470BG;break;
+    default:_info->colorspace=TH_CS_UNSPECIFIED;break;
+  }
+  switch(_ci->pixelformat){
+    case OC_PF_420:_info->pixel_fmt=TH_PF_420;break;
+    case OC_PF_422:_info->pixel_fmt=TH_PF_422;break;
+    case OC_PF_444:_info->pixel_fmt=TH_PF_444;break;
+    default:_info->pixel_fmt=TH_PF_RSVD;
+  }
+  _info->target_bitrate=_ci->target_bitrate;
+  _info->quality=_ci->quality;
+  _info->keyframe_granule_shift=_ci->keyframe_frequency_force>0?
+   OC_MINI(31,oc_ilog(_ci->keyframe_frequency_force-1)):0;
 }
 
-/* TODO: see if this is ok - which bits are we allowed to clear here? */
-void theora_clear(theora_state *t)
-{
-    th_api_wrapper *api = (th_api_wrapper *)t->i->codec_setup;
-
-    api->decode = NULL; /* Should we clear this here? Right now we do it in
-                           info_clear. TODO */
-
+int theora_decode_init(theora_state *_td,theora_info *_ci){
+  th_api_wrapper *api;
+  th_api_wrapper *dapi;
+  th_info         info;
+  /*We don't need these two fields.*/
+  _td->internal_encode=NULL;
+  _td->internal_decode=NULL;
+  _td->granulepos=0;
+  api=(th_api_wrapper *)_ci->codec_setup;
+  /*Make our own copy of the info struct, since its lifetime should be
+     independent of the one we were passed in.*/
+  _td->i=(theora_info *)_ogg_malloc(sizeof(*_td->i));
+  *_td->i=*_ci;
+  /*Also make our own copy of the wrapper.*/
+  dapi=(th_api_wrapper *)_ogg_calloc(1,sizeof(*dapi));
+  _td->i->codec_setup=dapi;
+  /*Convert the info struct now instead of saving the the one we decoded with
+     theora_decode_header(), since the user might have modified values (i.e.,
+     color space, aspect ratio, etc. can be specified from a higher level).
+    The user also might be doing something "clever" with the header packets if
+     they are not using an Ogg encapsulation.*/
+  theora_info2th_info(&info,_ci);
+  /*Don't bother to copy the setup info; th_decode_alloc() makes its own copy
+     of the stuff it needs.*/
+  dapi->decode=th_decode_alloc(&info,api->setup);
 }
 
-int theora_decode_init (theora_state *th, theora_info *c)
-{
-    th_api_wrapper *api = (th_api_wrapper *)c->codec_setup;
-
-    th->internal_encode = NULL;
-    th->internal_decode = NULL; /* We don't need this */
-    th->i = c;
-    th->granulepos = 0;
-
-    api->decode = th_decode_alloc(&api->info, api->setup);
+static void th_info2theora_info(theora_info *_ci,const th_info *_info){
+  _ci->version_major=_info->version_major;
+  _ci->version_minor=_info->version_minor;
+  _ci->version_subminor=_info->version_subminor;
+  _ci->width=_info->frame_width;
+  _ci->height=_info->frame_height;
+  _ci->frame_width=_info->pic_width;
+  _ci->frame_height=_info->pic_height;
+  _ci->offset_x=_info->pic_x;
+  _ci->offset_y=_info->pic_y;
+  _ci->fps_numerator=_info->fps_numerator;
+  _ci->fps_denominator=_info->fps_denominator;
+  _ci->aspect_numerator=_info->aspect_numerator;
+  _ci->aspect_denominator=_info->aspect_denominator;
+  switch(_info->colorspace){
+    case TH_CS_ITU_REC_470M:_ci->colorspace=OC_CS_ITU_REC_470M;break;
+    case TH_CS_ITU_REC_470BG:_ci->colorspace=OC_CS_ITU_REC_470BG;break;
+    default:_ci->colorspace=OC_CS_UNSPECIFIED;break;
+  }
+  switch(_info->pixel_fmt){
+    case TH_PF_420:_ci->pixelformat=OC_PF_420;break;
+    case TH_PF_422:_ci->pixelformat=OC_PF_422;break;
+    case TH_PF_444:_ci->pixelformat=OC_PF_444;break;
+    default:_ci->pixelformat=OC_PF_RSVD;
+  }
+  _ci->target_bitrate=_info->target_bitrate;
+  _ci->quality=_info->quality;
+  _ci->keyframe_frequency_force=1<<_info->keyframe_granule_shift;
 }
 
-int theora_decode_header(theora_info *ci, theora_comment *cc, ogg_packet *op)
-{
-    th_api_wrapper *api = (th_api_wrapper *)ci->codec_setup;
-    th_info *info = &api->info;
-    int ret;
-
-    /* Rely on the fact that theora_comment and th_comment structures are
-     * actually identical. Take care not to break this invariant unless you
-     * change the code here as well! */
-
-    ret = th_decode_headerin(info, (th_comment *)cc, &api->setup, op);
-
-    if (ret < 0)
-        return ret; // TODO: map_ret_val(ret);
-
-    ci->width = info->frame_width;
-    ci->height = info->frame_height;
-    ci->frame_width = info->pic_width;
-    ci->frame_height = info->pic_height;
-    ci->offset_x = info->pic_x;
-    ci->offset_y = info->pic_y;
-
-    ci->fps_numerator = info->fps_numerator;
-    ci->fps_denominator = info->fps_denominator;
-    ci->aspect_numerator = info->aspect_numerator;
-    ci->aspect_denominator = info->aspect_denominator;
-
-    switch (info->colorspace) {
-        case TH_CS_ITU_REC_470M:
-            ci->colorspace = OC_CS_ITU_REC_470M;
-            break;
-        case TH_CS_ITU_REC_470BG:
-            ci->colorspace = OC_CS_ITU_REC_470BG;
-            break;
-        default:
-            ci->colorspace = OC_CS_UNSPECIFIED;
-    }
-
-    ci->target_bitrate = info->target_bitrate;
-    ci->quality = info->quality;
-
-    switch (info->pixel_fmt) {
-        case TH_PF_420:
-            ci->pixelformat = OC_PF_420;
-            break;
-        case TH_PF_422:
-            ci->pixelformat = OC_PF_422;
-            break;
-        case TH_PF_444:
-            ci->pixelformat = OC_PF_444;
-            break;
-        default:
-            ci->pixelformat = OC_PF_RSVD;
-    }
-
-    ci->keyframe_frequency_force = 1 << info->keyframe_granule_shift;
-
-    ci->version_major = info->version_major;
-    ci->version_minor = info->version_minor;
-    ci->version_subminor = info->version_subminor;
-
-    return 0;
+int theora_decode_header(theora_info *_ci,theora_comment *_cc,ogg_packet *_op){
+  th_api_wrapper *api;
+  th_info         info;
+  int             ret;
+  api=(th_api_wrapper *)_ci->codec_setup;
+  /*Convert from the theora_info struct instead of saving our own th_info
+     struct between calls.
+    The user might be doing something "clever" with the header packets if they
+     are not using an Ogg encapsulation, and we don't want to break this.*/
+  theora_info2th_info(&info,_ci);
+  /*We rely on the fact that theora_comment and th_comment structures are
+     actually identical.
+    Take care not to change this fact unless you change the code here as
+     well!*/
+  ret=th_decode_headerin(&info,(th_comment *)_cc,&api->setup,_op);
+  /*We also rely on the fact that the error return code values are the same,
+    and that the implementations of these two functions return the same set of
+    them.
+   Note that theora_decode_header() really can return OC_NOTFORMAT, even
+    though it is not currently documented to do so.*/
+  if(ret<0)return ret;
+  th_info2theora_info(_ci,&info);
+  return 0;
 }
 
-int theora_decode_packetin(theora_state *th, ogg_packet *op)
-{
-    th_api_wrapper *api = (th_api_wrapper *)th->i->codec_setup;
-    int ret;
-    ogg_int64_t gp;
-
-    ret = th_decode_packetin(api->decode, op, &gp);
-
-    if (ret)
-        return OC_BADPACKET;
-
-    th->granulepos = gp;
-
-    return 0;
+int theora_decode_packetin(theora_state *_td,ogg_packet *_op){
+  th_api_wrapper *api;
+  ogg_int64_t     gp;
+  int             ret;
+  api=(th_api_wrapper *)_td->i->codec_setup;
+  ret=th_decode_packetin(api->decode,_op,&gp);
+  if(ret<0)return OC_BADPACKET;
+  _td->granulepos=gp;
+  return 0;
 }
 
-int theora_decode_YUVout(theora_state *th, yuv_buffer *yuv)
-{
-    th_api_wrapper *api = (th_api_wrapper *)th->i->codec_setup;
-    int ret;
-    th_ycbcr_buffer buf;
-
-    ret = th_decode_ycbcr_out(api->decode, buf);
-
-    if (!ret) {
-        /* Convert... */
-        yuv->y_width = buf[0].width;
-        yuv->y_height = buf[0].height;
-        yuv->y_stride = buf[0].ystride;
-
-        yuv->uv_width = buf[1].width;
-        yuv->uv_height = buf[1].height;
-        yuv->uv_stride = buf[1].ystride;
-
-        yuv->y = buf[0].data;
-        yuv->u = buf[1].data;
-        yuv->v = buf[2].data;
-    }
-
-    return ret;
+int theora_decode_YUVout(theora_state *_td,yuv_buffer *_yuv){
+  th_api_wrapper *api;
+  th_ycbcr_buffer buf;
+  int             ret;
+  api=(th_api_wrapper *)_td->i->codec_setup;
+  ret=th_decode_ycbcr_out(api->decode,buf);
+  if(ret>=0){
+    _yuv->y_width=buf[0].width;
+    _yuv->y_height=buf[0].height;
+    _yuv->y_stride=buf[0].ystride;
+    _yuv->uv_width=buf[1].width;
+    _yuv->uv_height=buf[1].height;
+    _yuv->uv_stride=buf[1].ystride;
+    _yuv->y=buf[0].data;
+    _yuv->u=buf[1].data;
+    _yuv->v=buf[2].data;
+  }
+  return ret;
 }
 
-int theora_packet_isheader(ogg_packet *op)
-{
-    return th_packet_isheader(op);
+int theora_packet_isheader(ogg_packet *_op){
+  return th_packet_isheader(_op);
 }
 
-int theora_packet_iskeyframe(ogg_packet *op)
-{
-    return th_packet_iskeyframe(op);
+int theora_packet_iskeyframe(ogg_packet *_op){
+  return th_packet_iskeyframe(_op);
 }
 
-int theora_granule_shift (theora_info *ti)
-{
-    return ((th_api_wrapper *)ti->codec_setup)->info.keyframe_granule_shift;
+int theora_granule_shift(theora_info *_ci){
+  /*This breaks when keyframe_frequency_force is not positive or is larger than
+     2**31 (if your int is more than 32 bits), but that's what the original
+     function does.*/
+  return oc_ilog(_ci->keyframe_frequency_force-1);
 }
 
-ogg_int64_t theora_granule_frame (theora_state *th, ogg_int64_t granulepos)
-{
-    return th_granule_frame (((th_api_wrapper *)th->i->codec_setup)->decode, 
-            granulepos);
+ogg_int64_t theora_granule_frame(theora_state *_td,ogg_int64_t _gp){
+  return th_granule_frame(((th_api_wrapper *)_td->i->codec_setup)->decode,_gp);
 }
 
-double theora_granule_time(theora_state *th, ogg_int64_t granulepos)
-{
-    return th_granule_time (((th_api_wrapper *)th->i->codec_setup)->decode, 
-            granulepos);
+double theora_granule_time(theora_state *_td, ogg_int64_t _gp){
+  return th_granule_time(((th_api_wrapper *)_td->i->codec_setup)->decode,_gp);
 }
 
-void theora_comment_init(theora_comment *tc)
-{
-    th_comment_init((th_comment *)tc);
+void theora_comment_init(theora_comment *_tc){
+  th_comment_init((th_comment *)_tc);
 }
 
-char *theora_comment_query(theora_comment *tc, char *tag, int count)
-{
-    return th_comment_query((th_comment *)tc, tag, count);
+char *theora_comment_query(theora_comment *_tc,char *_tag,int _count){
+  return th_comment_query((th_comment *)_tc,_tag,_count);
 }
 
-int theora_comment_query_count(theora_comment *tc, char *tag)
-{
-    return th_comment_query_count((th_comment *)tc, tag);
+int theora_comment_query_count(theora_comment *_tc,char *_tag){
+  return th_comment_query_count((th_comment *)_tc,_tag);
 }
 
-void theora_comment_clear(theora_comment *tc)
-{
-    th_comment_clear((th_comment *)tc);
+void theora_comment_clear(theora_comment *_tc){
+  th_comment_clear((th_comment *)_tc);
 }
-

Modified: trunk/theora-exp/unix/Makefile
===================================================================
--- trunk/theora-exp/unix/Makefile	2006-06-29 23:36:24 UTC (rev 11681)
+++ trunk/theora-exp/unix/Makefile	2006-07-01 14:53:19 UTC (rev 11682)
@@ -45,6 +45,7 @@
 ../include/theora/theora.h \
 
 LIBTHEORADEC_CSOURCES = \
+apiwrapper.c \
 decinfo.c \
 decode.c \
 dequant.c \



More information about the commits mailing list