[xiph-commits] r13842 - in trunk/theora-exp: lib unix
tterribe at svn.xiph.org
tterribe at svn.xiph.org
Sun Sep 16 15:05:14 PDT 2007
Author: tterribe
Date: 2007-09-16 15:05:14 -0700 (Sun, 16 Sep 2007)
New Revision: 13842
Modified:
trunk/theora-exp/lib/Makefile.am
trunk/theora-exp/lib/apiwrapper.c
trunk/theora-exp/lib/encinfo.c
trunk/theora-exp/lib/encode.c
trunk/theora-exp/lib/internal.h
trunk/theora-exp/unix/Makefile
Log:
New API wrapper for the encoder.
This includes some reworking of the way the API wrapper works for the decoder
that should let us be able to mix and match encoder and decoder shared
library versions.
Modified: trunk/theora-exp/lib/Makefile.am
===================================================================
--- trunk/theora-exp/lib/Makefile.am 2007-09-16 21:55:42 UTC (rev 13841)
+++ trunk/theora-exp/lib/Makefile.am 2007-09-16 22:05:14 UTC (rev 13842)
@@ -26,6 +26,7 @@
endif
noinst_HEADERS = \
+ apiwrapper.h \
dct.h \
decint.h \
dequant.h \
@@ -45,8 +46,10 @@
x86/x86int.h
libtheoracompat_la_SOURCES = \
- apiwrapper.c
-
+ apiwrapper.c \
+ decapiwrapper.c
+# encapiwrapper.c
+
libtheoradec_la_SOURCES = \
decinfo.c \
decode.c \
Modified: trunk/theora-exp/lib/apiwrapper.c
===================================================================
--- trunk/theora-exp/lib/apiwrapper.c 2007-09-16 21:55:42 UTC (rev 13841)
+++ trunk/theora-exp/lib/apiwrapper.c 2007-09-16 22:05:14 UTC (rev 13842)
@@ -1,27 +1,9 @@
#include <stdlib.h>
#include <string.h>
#include <limits.h>
-#include <ogg/ogg.h>
-/*libtheora header.*/
-#include <theora/theora.h>
-/*theora-exp header.*/
-#include "theora/theoradec.h"
-/*For oc_ilog et al.*/
-#include "internal.h"
+#include "apiwrapper.h"
-typedef struct th_api_wrapper th_api_wrapper;
-/*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;
-};
const char *theora_version_string(void){
return th_version_string();
@@ -32,30 +14,71 @@
}
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;
}
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));
+ if(api!=NULL){
+ if(api->clear!=NULL)(*api->clear)(api);
+ free(api);
+ }
}
-void theora_clear(theora_state *_td){
- if(_td->i!=NULL){
- theora_info_clear(_td->i);
- _ogg_free(_td->i);
- _td->i=NULL;
+void theora_clear(theora_state *_th){
+ /*Provide compatibility with mixed encoder and decoder shared lib versions.*/
+ if(_th->internal_decode!=NULL){
+ (*((oc_state_dispatch_vtbl *)_th->internal_decode)->clear)(_th);
}
+ if(_th->internal_encode!=NULL){
+ (*((oc_state_dispatch_vtbl *)_th->internal_encode)->clear)(_th);
+ }
+ if(_th->i!=NULL)theora_info_clear(_th->i);
+ memset(_th,0,sizeof(*_th));
}
-static void theora_info2th_info(th_info *_info,const theora_info *_ci){
+int theora_control(theora_state *_th,int _req,void *_buf,size_t _buf_sz){
+ /*Provide compatibility with mixed encoder and decoder shared lib versions.*/
+ if(_th->internal_decode!=NULL){
+ return (*((oc_state_dispatch_vtbl *)_th->internal_decode)->control)(_th,
+ _req,_buf,_buf_sz);
+ }
+ else if(_th->internal_encode!=NULL){
+ return (*((oc_state_dispatch_vtbl *)_th->internal_encode)->control)(_th,
+ _req,_buf,_buf_sz);
+ }
+ else return TH_EINVAL;
+}
+
+ogg_int64_t theora_granule_frame(theora_state *_th,ogg_int64_t _gp){
+ /*Provide compatibility with mixed encoder and decoder shared lib versions.*/
+ if(_th->internal_decode!=NULL){
+ return (*((oc_state_dispatch_vtbl *)_th->internal_decode)->granule_frame)(
+ _th,_gp);
+ }
+ else if(_th->internal_encode!=NULL){
+ return (*((oc_state_dispatch_vtbl *)_th->internal_encode)->granule_frame)(
+ _th,_gp);
+ }
+ else return -1;
+}
+
+double theora_granule_time(theora_state *_th, ogg_int64_t _gp){
+ /*Provide compatibility with mixed encoder and decoder shared lib versions.*/
+ if(_th->internal_decode!=NULL){
+ return (*((oc_state_dispatch_vtbl *)_th->internal_decode)->granule_time)(
+ _th,_gp);
+ }
+ else if(_th->internal_encode!=NULL){
+ return (*((oc_state_dispatch_vtbl *)_th->internal_encode)->granule_time)(
+ _th,_gp);
+ }
+ else return -1;
+}
+
+void oc_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;
@@ -86,127 +109,6 @@
OC_MINI(31,oc_ilog(_ci->keyframe_frequency_force-1)):0;
}
-int theora_decode_init(theora_state *_td,theora_info *_ci){
- th_api_wrapper *api;
- th_api_wrapper *dapi;
- theora_info *ci;
- 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.*/
- ci=(theora_info *)_ogg_malloc(sizeof(*_td->i));
- *ci=*_ci;
- /*Also make our own copy of the wrapper.*/
- dapi=(th_api_wrapper *)_ogg_calloc(1,sizeof(*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);
- if(dapi->decode==NULL){
- _ogg_free(ci);
- _ogg_free(dapi);
- return OC_EINVAL;
- }
- _td->i=ci;
- _td->i->codec_setup=dapi;
- return 0;
-}
-
-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_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 *_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 *_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);
}
@@ -222,14 +124,6 @@
return oc_ilog(_ci->keyframe_frequency_force-1);
}
-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 *_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);
}
@@ -245,3 +139,11 @@
void theora_comment_clear(theora_comment *_tc){
th_comment_clear((th_comment *)_tc);
}
+
+void theora_comment_add(theora_comment *_tc,char *_comment){
+ th_comment_add((th_comment *)_tc,_comment);
+}
+
+void theora_comment_add_tag(theora_comment *_tc, char *_tag, char *_value){
+ th_comment_add_tag((th_comment *)_tc,_tag,_value);
+}
Modified: trunk/theora-exp/lib/encinfo.c
===================================================================
--- trunk/theora-exp/lib/encinfo.c 2007-09-16 21:55:42 UTC (rev 13841)
+++ trunk/theora-exp/lib/encinfo.c 2007-09-16 22:05:14 UTC (rev 13842)
@@ -21,10 +21,11 @@
oggpack_buffer *_opb,const th_quant_info *_qinfo,
const th_huff_code _codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS],
const char *_vendor,th_comment *_tc,ogg_packet *_op){
- if(_state==NULL||_op==NULL)return TH_EFAULT;
+ if(_op==NULL)return TH_EFAULT;
switch(*_packet_state){
/*Codec info header.*/
case OC_PACKET_INFO_HDR:{
+ if(_state==NULL)return TH_EFAULT;
oggpackB_reset(_opb);
/*Mark this packet as the info header.*/
oggpackB_write(_opb,0x80,8);
Modified: trunk/theora-exp/lib/encode.c
===================================================================
--- trunk/theora-exp/lib/encode.c 2007-09-16 21:55:42 UTC (rev 13841)
+++ trunk/theora-exp/lib/encode.c 2007-09-16 22:05:14 UTC (rev 13842)
@@ -1433,6 +1433,7 @@
}
int th_encode_flushheader(th_enc_ctx *_enc,th_comment *_tc,ogg_packet *_op){
+ if(_enc==NULL)return TH_EFAULT;
return oc_state_flushheader(&_enc->state,&_enc->packet_state,&_enc->opb,
&_enc->qinfo,(const th_huff_table *)_enc->huff_codes,th_version_string(),
_tc,_op);
Modified: trunk/theora-exp/lib/internal.h
===================================================================
--- trunk/theora-exp/lib/internal.h 2007-09-16 21:55:42 UTC (rev 13841)
+++ trunk/theora-exp/lib/internal.h 2007-09-16 22:05:14 UTC (rev 13842)
@@ -435,4 +435,28 @@
int _refi,int _pli,int _fragy0,int _fragy_end);
void oc_restore_fpu_c(void);
+/*We need a way to call a few enocder functions without introducing a link-time
+ dependency into the decoder, while still allowing the old alpha API which
+ does not distinguish between encoder and decoder objects to be used.
+ We do this by placing a function table at the start of the encoder object
+ which can dispatch into the encoder library.*/
+/*We don't ship theora.h, so we don't want to include it to force theora_state
+ to be defined; thus it is replaced by void * below.*/
+typedef void (*oc_state_clear_func)(void *_th);
+typedef int (*oc_state_control_func)(void *th,int req,
+ void *buf,size_t buf_sz);
+typedef ogg_int64_t (*oc_state_granule_frame_func)(void *_th,
+ ogg_int64_t _granulepos);
+typedef double (*oc_state_granule_time_func)(void *_th,
+ ogg_int64_t _granulepos);
+
+typedef struct oc_state_dispatch_vtbl oc_state_dispatch_vtbl;
+
+struct oc_state_dispatch_vtbl{
+ oc_state_clear_func clear;
+ oc_state_control_func control;
+ oc_state_granule_frame_func granule_frame;
+ oc_state_granule_time_func granule_time;
+};
+
#endif
Modified: trunk/theora-exp/unix/Makefile
===================================================================
--- trunk/theora-exp/unix/Makefile 2007-09-16 21:55:42 UTC (rev 13841)
+++ trunk/theora-exp/unix/Makefile 2007-09-16 22:05:14 UTC (rev 13842)
@@ -39,6 +39,7 @@
# C source file lists
LIBTHEORABASE_CHEADERS = \
+apiwrapper.h \
dct.h \
idct.h \
huffman.h \
@@ -49,6 +50,7 @@
LIBTHEORADEC_CSOURCES = \
apiwrapper.c \
+decapiwrapper.c \
decinfo.c \
decode.c \
dequant.c \
@@ -75,6 +77,7 @@
LIBTHEORAENC_CSOURCES = \
bitrate.c \
+encapiwrapper.c \
encinfo.c \
encode.c \
enquant.c \
More information about the commits
mailing list