TheoraDecoder.cpp

00001 /*********************************************************************** 00002 * * 00003 * ViTooKi * 00004 * * 00005 * title: TheoraDecoder.cpp * 00006 * * 00007 * * 00008 * * 00009 * ITEC institute of the University of Klagenfurt (Austria) * 00010 * http://www.itec.uni-klu.ac.at * 00011 * * 00012 * * 00013 * For more information visit the ViTooKi homepage: * 00014 * http://ViTooKi.sourceforge.net * 00015 * vitooki-user@lists.sourceforge.net * 00016 * vitooki-devel@lists.sourceforge.net * 00017 * * 00018 * This file is part of ViTooKi, a free video toolkit. * 00019 * ViTooKi is free software; you can redistribute it and/or * 00020 * modify it under the terms of the GNU General Public License * 00021 * as published by the Free Software Foundation; either version 2 * 00022 * of the License, or (at your option) any later version. * 00023 * * 00024 * This program is distributed in the hope that it will be useful, * 00025 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00026 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00027 * GNU General Public License for more details. * 00028 * * 00029 * You should have received a copy of the GNU General Public License * 00030 * along with this program; if not, write to the Free Software * 00031 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * 00032 * MA 02111-1307, USA. * 00033 * * 00034 ***********************************************************************/ 00035 00036 /*********************************************************************** 00037 * * 00038 * REVISION HISTORY: * 00039 * * 00040 * * 00041 * * 00042 ***********************************************************************/ 00043 00044 00056 #ifdef ENABLE_OGG 00057 00058 #include "TheoraDecoder.hpp" 00059 //#include "ESInfo.hpp" 00060 00061 int framesSeen; 00062 OGGStreamInfo *osi; 00063 yuv_buffer *yuv; 00064 int frameSize = 0; 00065 // FILE* out; 00066 theora_info* ti; 00067 VideoESInfo* ves; 00068 00069 TheoraDecoder::TheoraDecoder(VideoESInfo* es){ 00070 dprintf_full("TheoraDecoder::TheoraDecoder(ves) isVisualStream = %s, HandlerType = %i, FPS = %f\n", 00071 (es->isVisualStream() ? "TURE" : "FALSE"), 00072 es->getHandlerType(), 00073 es->getFPS() 00074 ); 00075 ves = es; 00076 initialized = 0; 00077 initialize(); 00078 } 00079 00080 TheoraDecoder::~TheoraDecoder(){ 00081 dprintf_full("TheoraDecoder::~TheoraDecoder()\n"); 00082 if(initialized){ 00083 delete ts; 00084 // fclose(out); 00085 } 00086 } 00087 00088 list < Frame * > TheoraDecoder::adapt(Frame * frm){ 00089 OGGContainerFile::oggMutexLock("TheoraDecoder"); 00090 list < Frame * >tmp; 00091 AU *au = frm->getAU(); 00092 00093 double vid_time; 00094 ogg_packet *op = (ogg_packet*)au->payload; 00095 yuv = new yuv_buffer; //(yuv_buffer*)malloc(sizeof(yuv_buffer)); 00096 00097 if (frm->getAU() == NULL){ 00098 dprintf_full("TheoraDecoder::adapt: frm->getAU() was NULL!!\n"); 00099 OGGContainerFile::oggMutexRelease("TheoraDecoder"); 00100 return tmp; 00101 } 00102 00103 double start_dtime, now_dtime; 00104 struct timeval now_tv; 00105 gettimeofday(&now_tv, NULL); 00106 start_dtime = now_tv.tv_sec + now_tv.tv_usec/1000000.0; 00107 00108 // create ogg-package for theora-decoder 00109 dprintf_full("TheoraDecoder::adapt: got Frame %p, AU %p, cts %u!\n",frm, frm->getAU(), frm->getAU()->cts); 00110 00111 // decode FRAME! 00112 { 00113 theora_decode_packetin(ts, op); 00114 theora_decode_YUVout(ts, yuv); 00115 } 00116 00117 //vid_time = theora_granule_time(ts, ts->granulepos); 00118 vid_time = framesSeen / ves->getFPS(); 00119 dprintf_full("THDEC: VID_T = %f, FPS: %f, Frame#: %i\n", vid_time, ves->getFPS(), framesSeen); 00120 00121 // make FRAME for ViTooKi 00122 AU *dAU = new AU(); 00123 UncompressedVideoFrame *uvf; 00124 Frame::FrameType type = Frame::YUV_VOP; 00125 00126 dAU->size = (u32)((float)frameSize * 1.5); 00127 dAU->payload = new u8[dAU->size]; 00128 00129 dAU->cts = (u32)(vid_time*90000.0); 00130 dAU->dts = au->cts; 00131 00132 dprintf_full("TheoraDecoder::adapt: vid_timestamp: %f,\t granule_frame: %li,\t cts: %u, old_cts: %u\n", 00133 vid_time, 00134 (long)theora_granule_frame(ts, ts->granulepos), 00135 dAU->cts, au->cts); 00136 /* 00137 * size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); 00138 * DESCRIPTION 00139 * The function fwrite writes nmemb elements of data, each size bytes long, 00140 * to the stream pointed to by stream, obtaining them from the location given by ptr. 00141 */ 00142 { 00143 uint i = 0; int crop_offset = 0; 00144 crop_offset = ti->offset_x + yuv->y_stride * ti->offset_y; 00145 for(i=0; i < ti->height; i++){ 00146 memcpy(dAU->payload + ti->width * i, yuv->y + crop_offset + yuv->y_stride * i, ti->width); 00147 // fwrite(yuv->y + crop_offset + yuv->y_stride * i, 1, ti->width, out); 00148 } 00149 00150 crop_offset = ti->offset_x/2 + yuv->uv_stride * (ti->offset_y/2); 00151 for(i=0; i < ti->height/2; i++){ 00152 memcpy(dAU->payload + frameSize + ti->width/2 * i , yuv->u + crop_offset + yuv->uv_stride*i, ti->width/2); 00153 // fwrite(yuv->u + crop_offset + yuv->uv_stride*i, 1, ti->width/2, out); 00154 } 00155 00156 for(i=0; i < ti->height/2; i++){ 00157 memcpy(dAU->payload + frameSize + frameSize/4 + ti->width/2 * i, yuv->v + crop_offset + yuv->uv_stride*i, ti->width/2); 00158 // fwrite(yuv->v + crop_offset + yuv->uv_stride*i, 1, ti->width/2, out); 00159 } 00160 } 00161 uvf = new UncompressedVideoFrame(type, yuv->y_width, yuv->y_height); 00162 uvf->setAU(dAU); 00163 00164 tmp.push_back(uvf); 00165 00166 delete yuv; 00167 00168 gettimeofday(&now_tv,NULL); 00169 now_dtime = now_tv.tv_sec + now_tv.tv_usec/1000000.0; 00170 dprintf_full("TheoraDecoder::adapt(): worked for %2.0f msecs\n", 00171 (now_dtime-start_dtime)*1000.0); 00172 00173 if(au){ 00174 dprintf_full("DEL START\n"); 00175 if(op){ 00176 dprintf_full("OP-> YES (%p)!!!\n",op); 00177 // should do: 00178 // ogg_packet_clear(op); 00179 // but ogg_packet is a mapping from au->payload!!! 00180 // so I only have to clear op->packet, because this was malloc'd by me 00181 // free(op->packet); 00182 } 00183 else{ 00184 dprintf_full("OP-> NO!!!!\n"); 00185 // frm->getAU()->payload = NULL; 00186 } 00187 dprintf_full("DEL FINISH\n"); 00188 } 00189 00190 OGGContainerFile::oggMutexRelease("TheoraDecoder"); 00191 00192 framesSeen++; 00193 return tmp; 00194 } 00195 00196 void TheoraDecoder::initialize(){ 00197 OGGHandler *ogh = OGGContainerFile::getOGGHandler(); 00198 OGGStreamInfo *tmp = ogh->osi; 00199 dprintf_full("TheoraDecoder::initialize()\n"); 00200 00201 if(tmp){ 00202 do{ 00203 // in the TheoraDecoder we only seek for THEORA streams 00204 if(tmp->getStreamType() == OGG_THEORA){ 00205 dprintf_full("TheoraDecoder::initialize(): FOUND OGG_THEORA\n"); 00206 osi = tmp; 00207 // set width and height of stream 00208 break; 00209 } 00210 /* 00211 else if(tmp->getStreamType() == OGG_VORBIS){ 00212 dprintf_full("TheoraDecoder::initialize(): FOUND OGG_VORBIS\n"); 00213 */ 00214 tmp = tmp->getNext(); 00215 }while(tmp); 00216 } 00217 if(!osi){ 00218 dprintf_err("TheoraDecoder::initialize(): no stream in OGG-file found... ABORTING!\n"); 00219 exit(1); 00220 } 00221 ti = (theora_info*)osi->getCodecInfo(); 00222 00223 ts = new theora_state; 00224 theora_decode_init(ts, ti); 00225 dprintf_full("TheoraDecoder::THEORA_DECODE_INIT -- width %i , height %i\n",ti->width,ti->height); 00226 frameSize = ti->width * ti->height; 00227 00228 framesSeen = 0; 00229 00230 // YUV-out 00231 // out = fopen("./out.yuv","w"); 00232 00233 initialized = 1; 00234 } 00235 00236 #endif