~ubuntu-branches/ubuntu/trusty/kvirc/trusty-proposed

« back to all changes in this revision

Viewing changes to src/kvilib/ext/kvi_oggtheora.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Kai Wasserbäch, Kai Wasserbäch, Raúl Sánchez Siles
  • Date: 2011-02-12 10:40:21 UTC
  • mfrom: (14.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20110212104021-5mh4f75jlku20mnt
The combined "Twisted Experiment" and "Nocturnal Raid" release.

[ Kai Wasserbäch ]
* Synced to upstream's SVN revision 5467.
* debian/rules:
  - Added .PHONY line.
  - Resurrect -DMANUAL_REVISION, got lost somewhere and we build SVN
    revisions again.
  - Replace "-DWITH_NO_EMBEDDED_CODE=YES" with "-DWANT_CRYPTOPP=YES".
  - Change the remaining -DWITH/-DWITHOUT to the new -DWANT syntax.
* debian/control:
  - Removed DMUA, I'm a DD now.
  - Changed my e-mail address.
  - Removed unneeded relationships (no upgrades over two releases are
    supported).
  - Fix Suggests for kvirc-dbg.
  - kvirc-data: Make the "Suggests: kvirc" a Recommends, doesn't make much
    sense to install the -data package without the program.
* debian/source/local-options: Added with "unapply-patches".
* debian/kvirc.lintian-overrides: Updated to work for 4.1.1.
* debian/patches/21_make_shared-mime-info_B-D_superfluous.patch: Updated.
* debian/kvirc-data.install: Added .notifyrc.

[ Raúl Sánchez Siles ]
* Stating the right version where kvirc-data break and replace should happen.
* Fixing link to license file.
* Added French and Portuguese man pages.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//=============================================================================
2
 
//
3
 
//   File : kvi_oggtheora.cpp
4
 
//   Creation date : Sat Nov 21 2009 22:53:21 CEST by Fabio Bas
5
 
//
6
 
//   This file is part of the KVirc irc client distribution
7
 
//   Copyright (C) 2009 Fabio Bas (ctrlaltca at libero dot it)
8
 
//
9
 
//   This program is FREE software. You can redistribute it and/or
10
 
//   modify it under the terms of the GNU General Public License
11
 
//   as published by the Free Software Foundation; either version 2
12
 
//   of the License, or (at your opinion) any later version.
13
 
//
14
 
//   This program is distributed in the HOPE that it will be USEFUL,
15
 
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
 
//   See the GNU General Public License for more details.
18
 
//
19
 
//   You should have received a copy of the GNU General Public License
20
 
//   along with this program. If not, write to the Free Software Foundation,
21
 
//   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22
 
//
23
 
//   Based on the example encoder/player from Xiph.Org Foundation:
24
 
//=============================================================================
25
 
//
26
 
//  function: example encoder application; makes an Ogg Theora/Vorbis
27
 
//            file from YUV4MPEG2 and WAV input
28
 
//  last mod: $Id: encoder_example.c 16517 2009-08-25 19:48:57Z giles $
29
 
//
30
 
//=============================================================================
31
 
//
32
 
//  function: example SDL player application; plays Ogg Theora files (with
33
 
//            optional Vorbis audio second stream)
34
 
//  last mod: $Id: player_example.c 16628 2009-10-10 05:50:52Z gmaxwell $
35
 
//
36
 
//=============================================================================
37
 
 
38
 
#ifndef COMPILE_DISABLE_OGG_THEORA
39
 
 
40
 
#include <string.h>
41
 
#include <stdlib.h>
42
 
#include <time.h>
43
 
#include <sys/time.h>
44
 
#include <math.h>
45
 
 
46
 
#include "kvi_oggtheora.h"
47
 
#include "kvi_oggirct.h"
48
 
 
49
 
#include "kvi_databuffer.h"
50
 
 
51
 
using namespace KviOggIrcText;
52
 
 
53
 
static void rgb32toyuv444(QRgb * rgbPt, unsigned char *yuvPt, int w, int h)
54
 
{
55
 
        for(int i = 0; i < h; i++) {
56
 
                for (int j = 0; j < w; j++) {
57
 
                        yuvPt[i * w + j] = (unsigned char) (( 66 * qRed(*rgbPt) + 129 * qGreen(*rgbPt) +  25 * qBlue(*rgbPt) + 128) >> 8) + 16;   // y
58
 
                        yuvPt[(i + h) * w + j] = (unsigned char) ((-38 * qRed(*rgbPt) -  74 * qGreen(*rgbPt) + 112 * qBlue(*rgbPt) + 128) >> 8) + 128;  // u
59
 
                        yuvPt[(i + 2 * h)  * w + j] = (unsigned char) ((112 * qRed(*rgbPt) -  94 * qGreen(*rgbPt) -  18 * qBlue(*rgbPt) + 128) >> 8) + 128;  // v
60
 
                        //this moves the pointer forward 4 bytes (ARGB)
61
 
                        rgbPt++;
62
 
                }
63
 
        }
64
 
        return;
65
 
}
66
 
 
67
 
KviTheoraEncoder::KviTheoraEncoder(KviDataBuffer * stream, int iWidth, int iHeight, int iFpsN, int iFpsD, int iParN, int iParD)
68
 
{
69
 
        //used to check functions results
70
 
        int ret;
71
 
        videoflag=0;
72
 
        videoYuv=0;
73
 
        frame_state=-1;
74
 
 
75
 
        //text
76
 
        text_sofar=0;
77
 
 
78
 
        //user settings
79
 
        m_pStream=stream;
80
 
        geometry.pic_w=iWidth;
81
 
        geometry.pic_h=iHeight;
82
 
        //frame per second
83
 
        int video_fps_n=iFpsN;
84
 
        int video_fps_d=iFpsD;
85
 
        //aspect ratio
86
 
        int video_par_n=iParN;
87
 
        int video_par_d=iParD;
88
 
 
89
 
 
90
 
        // preset settings
91
 
        int video_q=48;
92
 
        ogg_uint32_t keyframe_frequency=64;
93
 
 
94
 
        y4m_dst_buf_read_sz = geometry.pic_w * geometry.pic_h * 3;
95
 
        y4m_aux_buf_sz = y4m_aux_buf_read_sz=0;
96
 
 
97
 
        // buffer allocations
98
 
        y4m_dst_buf_read_sz = geometry.pic_w * geometry.pic_h * 3;
99
 
        y4m_aux_buf_sz = y4m_aux_buf_read_sz=0;
100
 
        // The size of the final frame buffers is always computed from the destination chroma decimation type.
101
 
        y4m_dst_buf_sz = geometry.pic_w * geometry.pic_h * 3;
102
 
 
103
 
        // Set up Ogg output stream
104
 
        srand(time(NULL));
105
 
        ogg_stream_init(&to,rand());
106
 
 
107
 
        ogg_stream_init(&zo,rand());
108
 
        ret = irct_encode_init();
109
 
        if(ret)
110
 
        {
111
 
                qDebug("error initializing irctext");
112
 
                return;
113
 
        }
114
 
 
115
 
 
116
 
        // Set up Theora encoder
117
 
        // Theora has a divisible-by-sixteen restriction for the encoded frame size
118
 
        // scale the picture size up to the nearest /16 and calculate offsets
119
 
        geometry.frame_w = (geometry.pic_w + 15) &~ 0xF;
120
 
        geometry.frame_h = (geometry.pic_h + 15) &~ 0xF;
121
 
        // Force the offsets to be even so that chroma samples line up like we expect.
122
 
        geometry.pic_x = (geometry.frame_w - geometry.pic_w) >> 1 &~ 1;
123
 
        geometry.pic_y = (geometry.frame_h - geometry.pic_h) >> 1 &~ 1;
124
 
 
125
 
        // Fill in a th_info structure with details on the format of the video you wish to encode.
126
 
        th_info_init(&ti);
127
 
        ti.frame_width=geometry.frame_w;
128
 
        ti.frame_height=geometry.frame_h;
129
 
        ti.pic_width=geometry.pic_w;
130
 
        ti.pic_height=geometry.pic_h;
131
 
        ti.pic_x=geometry.pic_x;
132
 
        ti.pic_y=geometry.pic_y;
133
 
        ti.fps_numerator=video_fps_n;
134
 
        ti.fps_denominator=video_fps_d;
135
 
        ti.aspect_numerator=video_par_n;
136
 
        ti.aspect_denominator=video_par_d;
137
 
        ti.colorspace=TH_CS_UNSPECIFIED;
138
 
        //use vbr, not cbr
139
 
        ti.target_bitrate=0;
140
 
        ti.quality=video_q;
141
 
        ti.keyframe_granule_shift=ilog(keyframe_frequency-1);
142
 
        ti.pixel_fmt=TH_PF_444;
143
 
        // Allocate a th_enc_ctx handle with th_encode_alloc().
144
 
        td=th_encode_alloc(&ti);
145
 
        if(td==0){
146
 
                qDebug("Could not th_encode_alloc().");
147
 
                return;
148
 
        }
149
 
 
150
 
        th_info_clear(&ti);
151
 
        // Perform any additional encoder configuration required with th_encode_ctl().
152
 
        // setting just the granule shift only allows power-of-two keyframe spacing. Set the actual requested spacing.
153
 
        ret=th_encode_ctl(td,TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE,&keyframe_frequency,sizeof(keyframe_frequency-1));
154
 
        if(ret<0){
155
 
                qDebug("Could not set keyframe interval to %d.",(int)keyframe_frequency);
156
 
        }
157
 
        // write the bitstream header packets with proper page interleave
158
 
        th_comment_init(&tc);
159
 
        
160
 
        // Repeatedly call th_encode_flushheader() to retrieve all the header packets.
161
 
        // first packet will get its own page automatically
162
 
        if(th_encode_flushheader(td,&tc,&op)<=0){
163
 
                qDebug("Internal Theora library error.");
164
 
                return;
165
 
        }
166
 
 
167
 
        ogg_stream_packetin(&to,&op);
168
 
        if(ogg_stream_pageout(&to,&og)!=1){
169
 
                qDebug("Internal Ogg library error.");
170
 
                return;
171
 
        }
172
 
 
173
 
        m_pStream->append(og.header,og.header_len);
174
 
        m_pStream->append(og.body,og.body_len);
175
 
 
176
 
        // create the remaining theora headers
177
 
        for(;;){
178
 
                ret=th_encode_flushheader(td,&tc,&op);
179
 
                if(ret<0){
180
 
                        qDebug("Internal Theora library error.");
181
 
                        return;
182
 
                }
183
 
                else if(!ret)break;
184
 
                ogg_stream_packetin(&to,&op);
185
 
        }
186
 
 
187
 
        //irct
188
 
        ogg_packet header;
189
 
        irct_encode_headerout(&header);
190
 
        ogg_stream_packetin(&zo,&header); // automatically placed in its own page
191
 
        if(ogg_stream_pageout(&zo,&og)!=1){
192
 
                qDebug("Internal Ogg library error (irct).");
193
 
                return;
194
 
        }
195
 
        m_pStream->append(og.header,og.header_len);
196
 
        m_pStream->append(og.body,og.body_len);
197
 
 
198
 
        // Flush the rest of our headers. This ensures the actual data in each stream
199
 
        // will start on a new page, as per spec.
200
 
        for(;;)
201
 
        {
202
 
                int result = ogg_stream_flush(&to,&og);
203
 
                if(result<0){
204
 
                        // can't get here
205
 
                        qDebug("Internal Ogg library error.");
206
 
                        return;
207
 
                }
208
 
                if(result==0)break;
209
 
                m_pStream->append(og.header,og.header_len);
210
 
                m_pStream->append(og.body,og.body_len);
211
 
        }
212
 
}
213
 
 
214
 
KviTheoraEncoder::~KviTheoraEncoder()
215
 
{
216
 
        // Call th_encode_free() to release all encoder memory.
217
 
        th_encode_free(td);
218
 
 
219
 
        // clear out state
220
 
 
221
 
        ogg_stream_clear(&to);
222
 
        th_comment_clear(&tc);
223
 
 
224
 
        irct_encode_clear();
225
 
}
226
 
 
227
 
void KviTheoraEncoder::addVideoFrame(QRgb * rgb32, int)
228
 
{
229
 
        /*
230
 
         * For each uncompressed frame:
231
 
         *      o Submit the uncompressed frame via th_encode_ycbcr_in()
232
 
         *      o Repeatedly call th_encode_packetout() to retrieve any video data packets that are ready.
233
 
         */
234
 
 
235
 
        if(!videoYuv)
236
 
                videoYuv = new quint8[geometry.pic_w * geometry.pic_h * YUV444_BPP];
237
 
 
238
 
        rgb32toyuv444(rgb32, videoYuv, geometry.pic_w, geometry.pic_h);
239
 
//      qDebug("addFrame p%p size%d yuv%p",rgb32,videoSize,videoYuv);
240
 
        
241
 
        ogg_page videopage;
242
 
 
243
 
        // is there a video page flushed?  If not, fetch one if possible
244
 
        videoflag=fetch_and_process_video(videoYuv,&videopage,&to,td,videoflag);
245
 
 
246
 
        // no pages?
247
 
        if(!videoflag) return;
248
 
 
249
 
        th_granule_time(td,ogg_page_granulepos(&videopage));
250
 
 
251
 
        // flush a video page
252
 
        m_pStream->append(videopage.header,videopage.header_len);
253
 
        m_pStream->append(videopage.body,videopage.body_len);
254
 
        videoflag=0;
255
 
}
256
 
 
257
 
void KviTheoraEncoder::addTextFrame(unsigned char* textPkt, int textSize)
258
 
{
259
 
        ogg_page textpage;
260
 
        ogg_packet op;
261
 
 
262
 
        text_sofar++;
263
 
 
264
 
        // is there an audio page flushed?  If not, fetch one if possible
265
 
        textflag=irct_encode_packetout((char *) textPkt, textSize, text_sofar,&op);
266
 
        ogg_stream_packetin(&zo, &op);
267
 
        ogg_stream_pageout(&zo, &textpage);
268
 
 
269
 
        // no pages?  Must be end of stream.
270
 
//      if(!textflag) return;
271
 
 
272
 
        m_pStream->append(textpage.header,textpage.header_len);
273
 
        m_pStream->append(textpage.body,textpage.body_len);
274
 
        textflag=0;
275
 
}
276
 
 
277
 
int KviTheoraEncoder::fetch_and_process_video_packet(quint8 * videoYuv,th_enc_ctx *td,ogg_packet *op)
278
 
{
279
 
        th_ycbcr_buffer ycbcr;
280
 
 
281
 
        if(frame_state==-1)
282
 
        {
283
 
                /* initialize the double frame buffer */
284
 
                yuvframe[0]=(unsigned char *)malloc(y4m_dst_buf_sz);
285
 
                yuvframe[1]=(unsigned char *)malloc(y4m_dst_buf_sz);
286
 
                yuvframe[2]=(unsigned char *)malloc(y4m_aux_buf_sz);
287
 
                frame_state=0;
288
 
        }
289
 
        /* read and process more video */
290
 
 
291
 
        /* have two frame buffers full (if possible) before
292
 
        proceeding.  after first pass and until eos, one will
293
 
        always be full when we get here */
294
 
        for(;frame_state<2;)
295
 
        {
296
 
                /*Read the frame data that needs no conversion.*/
297
 
                memcpy(yuvframe[frame_state],videoYuv,y4m_dst_buf_read_sz);
298
 
                /*Read the frame data that does need conversion.*/
299
 
                memcpy(yuvframe[2],videoYuv,y4m_aux_buf_read_sz);
300
 
                frame_state++;
301
 
        }
302
 
        /* check to see if there are dupes to flush */
303
 
        if(th_encode_packetout(td,frame_state<1,op)>0)return 1;
304
 
        if(frame_state<1)
305
 
        {
306
 
                /* can't get here unless YUV4MPEG stream has no video */
307
 
                qDebug("Video input contains no frames.");
308
 
                return 0;
309
 
        }
310
 
        /* Theora is a one-frame-in,one-frame-out system; submit a frame
311
 
        for compression and pull out the packet */
312
 
 
313
 
        /*We submit the buffer to the library as if it were padded, but we do not
314
 
        actually allocate space for the padding.
315
 
        This is okay, because with the 1.0 API the library will never read data from the padded
316
 
        region.*/
317
 
        ycbcr[0].width=geometry.frame_w;
318
 
        ycbcr[0].height=geometry.frame_h;
319
 
        ycbcr[0].stride=geometry.pic_w;
320
 
        ycbcr[0].data=yuvframe[0] - geometry.pic_x  -geometry.pic_y * geometry.pic_w;
321
 
 
322
 
        ycbcr[1].width=geometry.frame_w;
323
 
        ycbcr[1].height=geometry.frame_h;
324
 
        ycbcr[1].stride=geometry.pic_w;
325
 
        ycbcr[1].data=yuvframe[0] + (geometry.pic_w * geometry.pic_h) - geometry.pic_x - geometry.pic_y * geometry.frame_w;
326
 
 
327
 
        ycbcr[2].width=geometry.frame_w;
328
 
        ycbcr[2].height=geometry.frame_h;
329
 
        ycbcr[2].stride=geometry.pic_w;
330
 
        ycbcr[2].data=ycbcr[1].data+(geometry.frame_w * geometry.frame_h);
331
 
 
332
 
        th_encode_ycbcr_in(td,ycbcr);
333
 
        {
334
 
                unsigned char *temp=yuvframe[0];
335
 
                yuvframe[0]=yuvframe[1];
336
 
                yuvframe[1]=temp;
337
 
                frame_state--;
338
 
        }
339
 
        /* if there was only one frame, it's the last in the stream */
340
 
        return th_encode_packetout(td,frame_state<1,op);
341
 
}
342
 
 
343
 
int KviTheoraEncoder::fetch_and_process_video(quint8 * videoYuv,ogg_page *videopage,
344
 
ogg_stream_state *to,th_enc_ctx *td,int videoflag)
345
 
{
346
 
        ogg_packet op;
347
 
        int ret;
348
 
        /* is there a video page flushed?  If not, work until there is. */
349
 
        while(!videoflag)
350
 
        {
351
 
                //qDebug("fetch_and_process_video loop");
352
 
                if(ogg_stream_pageout(to,videopage)>0) return 1;
353
 
                if(ogg_stream_eos(to)) return 0;
354
 
                ret=fetch_and_process_video_packet(videoYuv,td,&op);
355
 
                if(ret<=0)return 0;
356
 
                ogg_stream_packetin(to,&op);
357
 
        }
358
 
        return videoflag;
359
 
}
360
 
 
361
 
int KviTheoraEncoder::ilog(unsigned _v)
362
 
{
363
 
        int ret;
364
 
        for(ret=0;_v;ret++)_v>>=1;
365
 
        return ret;
366
 
}
367
 
 
368
 
 
369
 
//------------------------------------------------------------------------------
370
 
#define OC_CLAMP255(_x)     ((unsigned char)((((_x)<0)-1)&((_x)|-((_x)>255))))
371
 
 
372
 
KviTheoraDecoder::KviTheoraDecoder(KviDataBuffer * videoSignal,KviDataBuffer * textSignal)
373
 
{
374
 
        m_pVideoSignal=videoSignal;
375
 
        m_pTextSignal=textSignal;
376
 
        theora_p=0;
377
 
        stateflag=0;
378
 
        ts=NULL;
379
 
        thda=false;
380
 
        thtic=false;
381
 
 
382
 
        irct_p=0;
383
 
 
384
 
        /* single frame video buffering */
385
 
        videobuf_ready=0;
386
 
        videobuf_granulepos=-1;
387
 
        videobuf_time=0;
388
 
 
389
 
        /* start up Ogg stream synchronization layer */
390
 
        ogg_sync_init(&oy);
391
 
 
392
 
        /* init supporting Theora structures needed in header parsing */
393
 
        th_comment_init(&tc);
394
 
        th_info_init(&ti);
395
 
 
396
 
        for(int i=0;i<256;i++)
397
 
        {
398
 
                lu_Y[i]  =  2441889*(i- 16) + 1048576;
399
 
                lu_R[i]  =  3347111*(i-128);
400
 
                lu_GV[i] = -1704917*(i-128);
401
 
                lu_GU[i] =  -821585*(i-128);
402
 
                lu_B[i]  =  4230442*(i-128);
403
 
        }
404
 
}
405
 
 
406
 
KviTheoraDecoder::~KviTheoraDecoder()
407
 
{
408
 
        if(theora_p){
409
 
                ogg_stream_clear(&to);
410
 
                th_decode_free(td);
411
 
                th_comment_clear(&tc);
412
 
                th_info_clear(&ti);
413
 
        }
414
 
 
415
 
        if(irct_p)
416
 
        {
417
 
                ogg_stream_clear(&zo);
418
 
                irct_encode_clear();
419
 
        }
420
 
 
421
 
        ogg_sync_clear(&oy);
422
 
}
423
 
 
424
 
void KviTheoraDecoder::addData(KviDataBuffer * stream)
425
 
{
426
 
//      qDebug("adddata signal %p stream size %d",m_pVideoSignal, stream->size() );
427
 
        if(stream->size()==0)return;
428
 
        /* Ogg file open; parse the headers */
429
 
                
430
 
        if(!stateflag)
431
 
        {
432
 
 
433
 
                char *buffer=ogg_sync_buffer(&oy,stream->size());
434
 
                memcpy(buffer,stream->data(),stream->size());
435
 
                ogg_sync_wrote(&oy,stream->size());
436
 
                stream->clear();
437
 
 
438
 
                while(ogg_sync_pageout(&oy,&og)>0)
439
 
                {
440
 
                        ogg_stream_state test;
441
 
 
442
 
                        /* is this a mandated initial header? If not, stop parsing */
443
 
                        if(!ogg_page_bos(&og))
444
 
                        {
445
 
                                /* don't leak the page; get it into the appropriate stream */
446
 
//                              qDebug("queue_page && return");
447
 
                                queue_page(&og);
448
 
                                stateflag=1;
449
 
                                return;
450
 
                        }
451
 
 
452
 
                        ogg_stream_init(&test,ogg_page_serialno(&og));
453
 
                        ogg_stream_pagein(&test,&og);
454
 
                        ogg_stream_packetout(&test,&op);
455
 
 
456
 
 
457
 
                        /* identify the codec: try theora */
458
 
                        if(!theora_p && th_decode_headerin(&ti,&tc,&ts,&op)>=0){
459
 
                                qDebug("is theora, ts=%p &ts=%p",ts, &ts);
460
 
                                /* it is theora */
461
 
                                memcpy(&to,&test,sizeof(test));
462
 
                                theora_p=1;
463
 
                        }else if(!irct_p && irct_decode_headerin(&op)>=0){
464
 
                                qDebug("is irct");
465
 
                                /* it is irct */
466
 
                                memcpy(&zo,&test,sizeof(test));
467
 
                                irct_p=1;
468
 
                        }else{
469
 
//                              qDebug("is other");
470
 
                                /* whatever it is, we don't care about it */
471
 
                                ogg_stream_clear(&test);
472
 
                        }
473
 
                }
474
 
                /* fall through to non-bos page parsing */
475
 
        }
476
 
 
477
 
//      qDebug("checkpoint 2, theora_p=%d ",theora_p);
478
 
        /* we're expecting more header packets. */
479
 
        if((theora_p && theora_p<3))
480
 
        {
481
 
                int ret;
482
 
 
483
 
                /* look for further theora headers */
484
 
                while(theora_p && (theora_p<3) && (ret=ogg_stream_packetout(&to,&op)))
485
 
                {
486
 
                        if(ret<0){
487
 
                                qDebug("Error parsing Theora stream headers; corrupt stream?");
488
 
                                return;
489
 
                        }
490
 
                        if(!th_decode_headerin(&ti,&tc,&ts,&op)){
491
 
                                qDebug("Error parsing Theora stream headers; corrupt stream?");
492
 
                                return;
493
 
                        }
494
 
                        theora_p++;
495
 
                }
496
 
 
497
 
                /* The header pages/packets will arrive before anything else we
498
 
                care about, or the stream is not obeying spec */
499
 
                if(ogg_sync_pageout(&oy,&og)>0)
500
 
                {
501
 
                        qDebug("queue_page");
502
 
                        queue_page(&og); /* demux into the appropriate stream */
503
 
                } else {
504
 
                        qDebug("TheoraDecoder: need more data!");
505
 
                        //need more data
506
 
                        return;
507
 
                }
508
 
        }
509
 
 
510
 
//      qDebug("checkpoint 3");
511
 
        /* and now we have it all.  initialize decoders */
512
 
        if(theora_p && !thda)
513
 
        {
514
 
                thda=true;
515
 
                td=th_decode_alloc(&ti,ts);
516
 
                qDebug("Ogg logical stream %lx is Theora %dx%d %.02f fps",
517
 
                        to.serialno,ti.pic_width,ti.pic_height,
518
 
                        (double)ti.fps_numerator/ti.fps_denominator);
519
 
 
520
 
                geometry.pic_w = ti.pic_width;
521
 
                geometry.pic_h = ti.pic_height;
522
 
                geometry.frame_w = ti.frame_width;
523
 
                geometry.frame_h = ti.frame_height;
524
 
                geometry.pic_x = ti.pic_x;
525
 
                geometry.pic_y = ti.pic_y;
526
 
                
527
 
                px_fmt=ti.pixel_fmt;
528
 
                switch(ti.pixel_fmt)
529
 
                {
530
 
                        case TH_PF_444: qDebug(" 4:4:4 video"); break;
531
 
                        default:
532
 
                        qDebug(" video  (UNSUPPORTED Chroma sampling!)");
533
 
                        return;
534
 
                        break;
535
 
                }
536
 
                th_decode_ctl(td,TH_DECCTL_GET_PPLEVEL_MAX,&pp_level_max,sizeof(pp_level_max));
537
 
                pp_level=pp_level_max;
538
 
                th_decode_ctl(td,TH_DECCTL_SET_PPLEVEL,&pp_level,sizeof(pp_level));
539
 
                pp_inc=0;
540
 
 
541
 
                int w = ((ti.pic_x + ti.pic_width + 1) &~ 1) - (ti.pic_x &~ 1);
542
 
                int h = ((ti.pic_y + ti.pic_height + 1) &~ 1) - (ti.pic_y &~ 1);
543
 
                RGBbuffer = (unsigned char *) calloc(sizeof(char), w * h * 4);
544
 
        } else if(!thtic)
545
 
        {
546
 
                thtic=true;
547
 
                /* tear down the partial theora setup */
548
 
                th_info_clear(&ti);
549
 
                th_comment_clear(&tc);
550
 
 
551
 
                th_setup_free(ts);
552
 
        }
553
 
//       stateflag=0; /* playback has not begun */
554
 
 
555
 
        if(irct_p)
556
 
        {
557
 
                if(ogg_stream_packetout(&zo,&op)>0)
558
 
                {
559
 
                        char * textPkt=0;
560
 
                        int textSize=0;
561
 
                        if(irct_decode_packetin(&textPkt, &textSize, &op)==0)
562
 
                        {
563
 
                                m_pTextSignal->append((unsigned char *)textPkt, textSize);
564
 
                        }
565
 
                }
566
 
        }
567
 
 
568
 
        if(theora_p && !videobuf_ready)
569
 
        {
570
 
                if(stream->size()>0)
571
 
                {
572
 
                        char *buffer=ogg_sync_buffer(&oy,stream->size());
573
 
                        memcpy(buffer,stream->data(),stream->size());
574
 
                        ogg_sync_wrote(&oy,stream->size());
575
 
                        stream->clear();
576
 
 
577
 
                        while(ogg_sync_pageout(&oy,&og)>0)
578
 
                                queue_page(&og);
579
 
                }
580
 
//              qDebug("loop4 theora_p=%d videobuf_ready=%d",theora_p, videobuf_ready);
581
 
        // theora is one in, one out...
582
 
 
583
 
                if(ogg_stream_packetout(&to,&op)>0)
584
 
                {
585
 
                        if(th_decode_packetin(td,&op,&videobuf_granulepos)==0)
586
 
                                videobuf_ready=1;
587
 
                } else {
588
 
//                      qDebug("ogg_stream_packetout <=0");
589
 
                        //need more data :)
590
 
                        return;
591
 
                }
592
 
        }
593
 
 
594
 
        if(!videobuf_ready)return;
595
 
 
596
 
 
597
 
        if(stateflag && videobuf_ready)
598
 
        {
599
 
                video_write();
600
 
                videobuf_ready=0;
601
 
        }
602
 
 
603
 
        // if our buffers either don't exist or are ready to go,we can begin playback
604
 
        if(!theora_p || videobuf_ready)stateflag=1;
605
 
}
606
 
 
607
 
/* helper: push a page into the appropriate steam */
608
 
/* this can be done blindly; a stream won't accept a page
609
 
                that doesn't belong to it */
610
 
int KviTheoraDecoder::queue_page(ogg_page *page)
611
 
{
612
 
        if(theora_p)ogg_stream_pagein(&to,page);
613
 
        if(irct_p)ogg_stream_pagein(&zo,page);
614
 
        return 0;
615
 
}
616
 
 
617
 
void KviTheoraDecoder::video_write(void)
618
 
{
619
 
        th_ycbcr_buffer yuv;
620
 
        int y_offset;
621
 
        th_decode_ycbcr_out(td,yuv);
622
 
 
623
 
        y_offset=(geometry.pic_x&~1)+yuv[0].stride*(geometry.pic_y&~1);
624
 
 
625
 
        for(int i=0;i<geometry.pic_h;i++)
626
 
        {
627
 
                unsigned char *in_y  = (unsigned char *)yuv[0].data+y_offset+yuv[0].stride*i;
628
 
                unsigned char *in_u  = (unsigned char *)yuv[1].data+y_offset+yuv[1].stride*i;
629
 
                unsigned char *in_v  = (unsigned char *)yuv[2].data+y_offset+yuv[2].stride*i;
630
 
                unsigned char *out = RGBbuffer+(geometry.pic_w * i * ARGB32_BPP);
631
 
                for (int j=0;j<geometry.pic_w;j++)
632
 
                {
633
 
                        int r, g, b;
634
 
                        int y = lu_Y[in_y[j]];
635
 
                        b=(y + lu_B[in_u[j]])>>21;
636
 
                        out[j*4]     = OC_CLAMP255(b);
637
 
                        g=(y + lu_GV[in_v[j]] + lu_GU[in_u[j]])>>21;
638
 
                        out[j*4+1]   = OC_CLAMP255(g);
639
 
                        r=(y + lu_R[in_v[j]])>>21;
640
 
                        out[j*4+2]   = OC_CLAMP255(r);
641
 
                        out[j*4+3]   = 255; //alpha
642
 
                }
643
 
                
644
 
        }
645
 
 
646
 
        int size = sizeof(char) * geometry.pic_w * geometry.pic_h * ARGB32_BPP;
647
 
 
648
 
//      qDebug("VIDEO WRITE size=%d",size);
649
 
        m_pVideoSignal->clear();
650
 
        m_pVideoSignal->append(RGBbuffer, size);
651
 
}
652
 
 
653
 
#endif // COMPILE_DISABLE_OGG_THEORA
 
 
b'\\ No newline at end of file'