media/libtheora/lib/decapiwrapper.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /********************************************************************
michael@0 2 * *
michael@0 3 * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
michael@0 4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
michael@0 5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
michael@0 6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
michael@0 7 * *
michael@0 8 * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
michael@0 9 * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
michael@0 10 * *
michael@0 11 ********************************************************************
michael@0 12
michael@0 13 function:
michael@0 14 last mod: $Id: decapiwrapper.c 13596 2007-08-23 20:05:38Z tterribe $
michael@0 15
michael@0 16 ********************************************************************/
michael@0 17
michael@0 18 #include <stdlib.h>
michael@0 19 #include <string.h>
michael@0 20 #include <limits.h>
michael@0 21 #include "apiwrapper.h"
michael@0 22 #include "decint.h"
michael@0 23 #include "theora/theoradec.h"
michael@0 24
michael@0 25 static void th_dec_api_clear(th_api_wrapper *_api){
michael@0 26 if(_api->setup)th_setup_free(_api->setup);
michael@0 27 if(_api->decode)th_decode_free(_api->decode);
michael@0 28 memset(_api,0,sizeof(*_api));
michael@0 29 }
michael@0 30
michael@0 31 static void theora_decode_clear(theora_state *_td){
michael@0 32 if(_td->i!=NULL)theora_info_clear(_td->i);
michael@0 33 memset(_td,0,sizeof(*_td));
michael@0 34 }
michael@0 35
michael@0 36 static int theora_decode_control(theora_state *_td,int _req,
michael@0 37 void *_buf,size_t _buf_sz){
michael@0 38 return th_decode_ctl(((th_api_wrapper *)_td->i->codec_setup)->decode,
michael@0 39 _req,_buf,_buf_sz);
michael@0 40 }
michael@0 41
michael@0 42 static ogg_int64_t theora_decode_granule_frame(theora_state *_td,
michael@0 43 ogg_int64_t _gp){
michael@0 44 return th_granule_frame(((th_api_wrapper *)_td->i->codec_setup)->decode,_gp);
michael@0 45 }
michael@0 46
michael@0 47 static double theora_decode_granule_time(theora_state *_td,ogg_int64_t _gp){
michael@0 48 return th_granule_time(((th_api_wrapper *)_td->i->codec_setup)->decode,_gp);
michael@0 49 }
michael@0 50
michael@0 51 static const oc_state_dispatch_vtable OC_DEC_DISPATCH_VTBL={
michael@0 52 (oc_state_clear_func)theora_decode_clear,
michael@0 53 (oc_state_control_func)theora_decode_control,
michael@0 54 (oc_state_granule_frame_func)theora_decode_granule_frame,
michael@0 55 (oc_state_granule_time_func)theora_decode_granule_time,
michael@0 56 };
michael@0 57
michael@0 58 static void th_info2theora_info(theora_info *_ci,const th_info *_info){
michael@0 59 _ci->version_major=_info->version_major;
michael@0 60 _ci->version_minor=_info->version_minor;
michael@0 61 _ci->version_subminor=_info->version_subminor;
michael@0 62 _ci->width=_info->frame_width;
michael@0 63 _ci->height=_info->frame_height;
michael@0 64 _ci->frame_width=_info->pic_width;
michael@0 65 _ci->frame_height=_info->pic_height;
michael@0 66 _ci->offset_x=_info->pic_x;
michael@0 67 _ci->offset_y=_info->pic_y;
michael@0 68 _ci->fps_numerator=_info->fps_numerator;
michael@0 69 _ci->fps_denominator=_info->fps_denominator;
michael@0 70 _ci->aspect_numerator=_info->aspect_numerator;
michael@0 71 _ci->aspect_denominator=_info->aspect_denominator;
michael@0 72 switch(_info->colorspace){
michael@0 73 case TH_CS_ITU_REC_470M:_ci->colorspace=OC_CS_ITU_REC_470M;break;
michael@0 74 case TH_CS_ITU_REC_470BG:_ci->colorspace=OC_CS_ITU_REC_470BG;break;
michael@0 75 default:_ci->colorspace=OC_CS_UNSPECIFIED;break;
michael@0 76 }
michael@0 77 switch(_info->pixel_fmt){
michael@0 78 case TH_PF_420:_ci->pixelformat=OC_PF_420;break;
michael@0 79 case TH_PF_422:_ci->pixelformat=OC_PF_422;break;
michael@0 80 case TH_PF_444:_ci->pixelformat=OC_PF_444;break;
michael@0 81 default:_ci->pixelformat=OC_PF_RSVD;
michael@0 82 }
michael@0 83 _ci->target_bitrate=_info->target_bitrate;
michael@0 84 _ci->quality=_info->quality;
michael@0 85 _ci->keyframe_frequency_force=1<<_info->keyframe_granule_shift;
michael@0 86 }
michael@0 87
michael@0 88 int theora_decode_init(theora_state *_td,theora_info *_ci){
michael@0 89 th_api_info *apiinfo;
michael@0 90 th_api_wrapper *api;
michael@0 91 th_info info;
michael@0 92 api=(th_api_wrapper *)_ci->codec_setup;
michael@0 93 /*Allocate our own combined API wrapper/theora_info struct.
michael@0 94 We put them both in one malloc'd block so that when the API wrapper is
michael@0 95 freed, the info struct goes with it.
michael@0 96 This avoids having to figure out whether or not we need to free the info
michael@0 97 struct in either theora_info_clear() or theora_clear().*/
michael@0 98 apiinfo=(th_api_info *)_ogg_calloc(1,sizeof(*apiinfo));
michael@0 99 if(apiinfo==NULL)return OC_FAULT;
michael@0 100 /*Make our own copy of the info struct, since its lifetime should be
michael@0 101 independent of the one we were passed in.*/
michael@0 102 *&apiinfo->info=*_ci;
michael@0 103 /*Convert the info struct now instead of saving the the one we decoded with
michael@0 104 theora_decode_header(), since the user might have modified values (i.e.,
michael@0 105 color space, aspect ratio, etc. can be specified from a higher level).
michael@0 106 The user also might be doing something "clever" with the header packets if
michael@0 107 they are not using an Ogg encapsulation.*/
michael@0 108 oc_theora_info2th_info(&info,_ci);
michael@0 109 /*Don't bother to copy the setup info; th_decode_alloc() makes its own copy
michael@0 110 of the stuff it needs.*/
michael@0 111 apiinfo->api.decode=th_decode_alloc(&info,api->setup);
michael@0 112 if(apiinfo->api.decode==NULL){
michael@0 113 _ogg_free(apiinfo);
michael@0 114 return OC_EINVAL;
michael@0 115 }
michael@0 116 apiinfo->api.clear=(oc_setup_clear_func)th_dec_api_clear;
michael@0 117 _td->internal_encode=NULL;
michael@0 118 /*Provide entry points for ABI compatibility with old decoder shared libs.*/
michael@0 119 _td->internal_decode=(void *)&OC_DEC_DISPATCH_VTBL;
michael@0 120 _td->granulepos=0;
michael@0 121 _td->i=&apiinfo->info;
michael@0 122 _td->i->codec_setup=&apiinfo->api;
michael@0 123 return 0;
michael@0 124 }
michael@0 125
michael@0 126 int theora_decode_header(theora_info *_ci,theora_comment *_cc,ogg_packet *_op){
michael@0 127 th_api_wrapper *api;
michael@0 128 th_info info;
michael@0 129 int ret;
michael@0 130 api=(th_api_wrapper *)_ci->codec_setup;
michael@0 131 /*Allocate an API wrapper struct on demand, since it will not also include a
michael@0 132 theora_info struct like the ones that are used in a theora_state struct.*/
michael@0 133 if(api==NULL){
michael@0 134 _ci->codec_setup=_ogg_calloc(1,sizeof(*api));
michael@0 135 if(_ci->codec_setup==NULL)return OC_FAULT;
michael@0 136 api=(th_api_wrapper *)_ci->codec_setup;
michael@0 137 api->clear=(oc_setup_clear_func)th_dec_api_clear;
michael@0 138 }
michael@0 139 /*Convert from the theora_info struct instead of saving our own th_info
michael@0 140 struct between calls.
michael@0 141 The user might be doing something "clever" with the header packets if they
michael@0 142 are not using an Ogg encapsulation, and we don't want to break this.*/
michael@0 143 oc_theora_info2th_info(&info,_ci);
michael@0 144 /*We rely on the fact that theora_comment and th_comment structures are
michael@0 145 actually identical.
michael@0 146 Take care not to change this fact unless you change the code here as
michael@0 147 well!*/
michael@0 148 ret=th_decode_headerin(&info,(th_comment *)_cc,&api->setup,_op);
michael@0 149 /*We also rely on the fact that the error return code values are the same,
michael@0 150 and that the implementations of these two functions return the same set of
michael@0 151 them.
michael@0 152 Note that theora_decode_header() really can return OC_NOTFORMAT, even
michael@0 153 though it is not currently documented to do so.*/
michael@0 154 if(ret<0)return ret;
michael@0 155 th_info2theora_info(_ci,&info);
michael@0 156 return 0;
michael@0 157 }
michael@0 158
michael@0 159 int theora_decode_packetin(theora_state *_td,ogg_packet *_op){
michael@0 160 th_api_wrapper *api;
michael@0 161 ogg_int64_t gp;
michael@0 162 int ret;
michael@0 163 if(!_td||!_td->i||!_td->i->codec_setup)return OC_FAULT;
michael@0 164 api=(th_api_wrapper *)_td->i->codec_setup;
michael@0 165 ret=th_decode_packetin(api->decode,_op,&gp);
michael@0 166 if(ret<0)return OC_BADPACKET;
michael@0 167 _td->granulepos=gp;
michael@0 168 return 0;
michael@0 169 }
michael@0 170
michael@0 171 int theora_decode_YUVout(theora_state *_td,yuv_buffer *_yuv){
michael@0 172 th_api_wrapper *api;
michael@0 173 th_dec_ctx *decode;
michael@0 174 th_ycbcr_buffer buf;
michael@0 175 int ret;
michael@0 176 if(!_td||!_td->i||!_td->i->codec_setup)return OC_FAULT;
michael@0 177 api=(th_api_wrapper *)_td->i->codec_setup;
michael@0 178 decode=(th_dec_ctx *)api->decode;
michael@0 179 if(!decode)return OC_FAULT;
michael@0 180 ret=th_decode_ycbcr_out(decode,buf);
michael@0 181 if(ret>=0){
michael@0 182 _yuv->y_width=buf[0].width;
michael@0 183 _yuv->y_height=buf[0].height;
michael@0 184 _yuv->y_stride=buf[0].stride;
michael@0 185 _yuv->uv_width=buf[1].width;
michael@0 186 _yuv->uv_height=buf[1].height;
michael@0 187 _yuv->uv_stride=buf[1].stride;
michael@0 188 _yuv->y=buf[0].data;
michael@0 189 _yuv->u=buf[1].data;
michael@0 190 _yuv->v=buf[2].data;
michael@0 191 }
michael@0 192 return ret;
michael@0 193 }

mercurial