Skip to content

Latest commit

 

History

History
819 lines (698 loc) · 24 KB

theoraplay.c

File metadata and controls

819 lines (698 loc) · 24 KB
 
Jun 10, 2011
Jun 10, 2011
1
2
3
4
5
6
7
8
/**
* TheoraPlay; multithreaded Ogg Theora/Ogg Vorbis decoding.
*
* Please see the file LICENSE.txt in the source's root directory.
*
* This file written by Ryan C. Gordon.
*/
9
10
11
12
13
14
15
16
17
// I wrote this with a lot of peeking at the Theora example code in
// libtheora-1.1.1/examples/player_example.c, but this is all my own
// code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
Apr 23, 2013
Apr 23, 2013
18
19
20
21
#ifdef _WIN32
#include <windows.h>
#define THEORAPLAY_THREAD_T HANDLE
#define THEORAPLAY_MUTEX_T HANDLE
May 19, 2013
May 19, 2013
22
#define sleepms(x) Sleep(x)
Apr 23, 2013
Apr 23, 2013
23
24
#else
#include <pthread.h>
May 19, 2013
May 19, 2013
25
26
#include <unistd.h>
#define sleepms(x) usleep((x) * 1000)
Apr 23, 2013
Apr 23, 2013
27
28
29
30
#define THEORAPLAY_THREAD_T pthread_t
#define THEORAPLAY_MUTEX_T pthread_mutex_t
#endif
Jun 10, 2011
Jun 10, 2011
31
#include "theoraplay.h"
32
33
34
#include "theora/theoradec.h"
#include "vorbis/codec.h"
Jun 15, 2011
Jun 15, 2011
35
36
#define THEORAPLAY_INTERNAL 1
Jun 15, 2011
Jun 15, 2011
37
38
typedef THEORAPLAY_VideoFrame VideoFrame;
typedef THEORAPLAY_AudioPacket AudioPacket;
Jun 15, 2011
Jun 15, 2011
40
41
// !!! FIXME: these all count on the pixel format being TH_PF_420 for now.
Jun 15, 2011
Jun 15, 2011
42
43
44
typedef unsigned char *(*ConvertVideoFrameFn)(const th_info *tinfo,
const th_ycbcr_buffer ycbcr);
Jun 19, 2011
Jun 19, 2011
45
46
47
static unsigned char *ConvertVideoFrame420ToYUVPlanar(
const th_info *tinfo, const th_ycbcr_buffer ycbcr,
const int p0, const int p1, const int p2)
Jun 15, 2011
Jun 15, 2011
48
49
50
51
52
53
54
55
56
57
58
{
int i;
const int w = tinfo->pic_width;
const int h = tinfo->pic_height;
const int yoff = (tinfo->pic_x & ~1) + ycbcr[0].stride * (tinfo->pic_y & ~1);
const int uvoff = (tinfo->pic_x / 2) + (ycbcr[1].stride) * (tinfo->pic_y / 2);
unsigned char *yuv = (unsigned char *) malloc(w * h * 2);
if (yuv)
{
unsigned char *dst = yuv;
for (i = 0; i < h; i++, dst += w)
Jun 19, 2011
Jun 19, 2011
59
memcpy(dst, ycbcr[p0].data + yoff + ycbcr[p0].stride * i, w);
Jun 15, 2011
Jun 15, 2011
60
for (i = 0; i < (h / 2); i++, dst += w/2)
Jun 19, 2011
Jun 19, 2011
61
memcpy(dst, ycbcr[p1].data + uvoff + ycbcr[p1].stride * i, w / 2);
Jun 15, 2011
Jun 15, 2011
62
for (i = 0; i < (h / 2); i++, dst += w/2)
Jun 19, 2011
Jun 19, 2011
63
memcpy(dst, ycbcr[p2].data + uvoff + ycbcr[p2].stride * i, w / 2);
Jun 15, 2011
Jun 15, 2011
64
65
66
} // if
return yuv;
Jun 19, 2011
Jun 19, 2011
67
68
69
70
71
72
73
} // ConvertVideoFrame420ToYUVPlanar
static unsigned char *ConvertVideoFrame420ToYV12(const th_info *tinfo,
const th_ycbcr_buffer ycbcr)
{
return ConvertVideoFrame420ToYUVPlanar(tinfo, ycbcr, 0, 2, 1);
Jun 15, 2011
Jun 15, 2011
74
} // ConvertVideoFrame420ToYV12
Jun 15, 2011
Jun 15, 2011
75
76
Jun 19, 2011
Jun 19, 2011
77
78
79
80
81
82
83
static unsigned char *ConvertVideoFrame420ToIYUV(const th_info *tinfo,
const th_ycbcr_buffer ycbcr)
{
return ConvertVideoFrame420ToYUVPlanar(tinfo, ycbcr, 0, 1, 2);
} // ConvertVideoFrame420ToIYUV
Jun 15, 2011
Jun 15, 2011
84
85
86
87
88
89
// RGB
#define THEORAPLAY_CVT_FNNAME_420 ConvertVideoFrame420ToRGB
#define THEORAPLAY_CVT_RGB_ALPHA 0
#include "theoraplay_cvtrgb.h"
#undef THEORAPLAY_CVT_RGB_ALPHA
#undef THEORAPLAY_CVT_FNNAME_420
Jun 15, 2011
Jun 15, 2011
90
Jun 15, 2011
Jun 15, 2011
91
92
93
94
95
96
// RGBA
#define THEORAPLAY_CVT_FNNAME_420 ConvertVideoFrame420ToRGBA
#define THEORAPLAY_CVT_RGB_ALPHA 1
#include "theoraplay_cvtrgb.h"
#undef THEORAPLAY_CVT_RGB_ALPHA
#undef THEORAPLAY_CVT_FNNAME_420
Jun 15, 2011
Jun 15, 2011
97
98
99
100
101
typedef struct TheoraDecoder
{
// Thread wrangling...
Jun 10, 2011
Jun 10, 2011
102
int thread_created;
Apr 23, 2013
Apr 23, 2013
103
THEORAPLAY_MUTEX_T lock;
104
volatile int halt;
Jun 10, 2011
Jun 10, 2011
105
int thread_done;
Apr 23, 2013
Apr 23, 2013
106
THEORAPLAY_THREAD_T worker;
107
108
// API state...
Jun 24, 2011
Jun 24, 2011
109
THEORAPLAY_Io *io;
110
unsigned int maxframes; // Max video frames to buffer.
Jun 24, 2011
Jun 24, 2011
111
112
113
114
115
116
117
volatile unsigned int prepped;
volatile unsigned int videocount; // currently buffered frames.
volatile unsigned int audioms; // currently buffered audio samples.
volatile int hasvideo;
volatile int hasaudio;
volatile int decode_error;
Jun 15, 2011
Jun 15, 2011
118
119
THEORAPLAY_VideoFormat vidfmt;
ConvertVideoFrameFn vidcvt;
Jun 15, 2011
Jun 15, 2011
121
122
VideoFrame *videolist;
VideoFrame *videolisttail;
Jun 15, 2011
Jun 15, 2011
124
125
AudioPacket *audiolist;
AudioPacket *audiolisttail;
126
127
128
} TheoraDecoder;
Apr 23, 2013
Apr 23, 2013
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
#ifdef _WIN32
static inline int Thread_Create(TheoraDecoder *ctx, void *(*routine) (void*))
{
ctx->worker = CreateThread(
NULL,
0,
(LPTHREAD_START_ROUTINE) routine,
(LPVOID) ctx,
0,
NULL
);
return (ctx->worker == NULL);
}
static inline void Thread_Join(THEORAPLAY_THREAD_T thread)
{
WaitForSingleObject(thread, INFINITE);
CloseHandle(thread);
}
static inline int Mutex_Create(TheoraDecoder *ctx)
{
ctx->lock = CreateMutex(NULL, FALSE, NULL);
return (ctx->lock == NULL);
}
static inline void Mutex_Destroy(THEORAPLAY_MUTEX_T mutex)
{
CloseHandle(mutex);
}
static inline void Mutex_Lock(THEORAPLAY_MUTEX_T mutex)
{
WaitForSingleObject(mutex, INFINITE);
}
static inline void Mutex_Unlock(THEORAPLAY_MUTEX_T mutex)
{
ReleaseMutex(mutex);
}
#else
static inline int Thread_Create(TheoraDecoder *ctx, void *(*routine) (void*))
{
return pthread_create(&ctx->worker, NULL, routine, ctx);
}
static inline void Thread_Join(THEORAPLAY_THREAD_T thread)
{
pthread_join(thread, NULL);
}
static inline int Mutex_Create(TheoraDecoder *ctx)
{
return pthread_mutex_init(&ctx->lock, NULL);
}
static inline void Mutex_Destroy(THEORAPLAY_MUTEX_T mutex)
{
pthread_mutex_destroy(&mutex);
}
static inline void Mutex_Lock(THEORAPLAY_MUTEX_T mutex)
{
pthread_mutex_lock(&mutex);
}
static inline void Mutex_Unlock(THEORAPLAY_MUTEX_T mutex)
{
pthread_mutex_unlock(&mutex);
}
#endif
Jun 23, 2011
Jun 23, 2011
192
static int FeedMoreOggData(THEORAPLAY_Io *io, ogg_sync_state *sync)
Jun 11, 2011
Jun 11, 2011
194
long buflen = 4096;
Jun 10, 2011
Jun 10, 2011
195
char *buffer = ogg_sync_buffer(sync, buflen);
196
if (buffer == NULL)
Jun 10, 2011
Jun 10, 2011
197
return -1;
Jun 23, 2011
Jun 23, 2011
199
buflen = io->read(io, buffer, buflen);
200
201
202
if (buflen <= 0)
return 0;
Jun 10, 2011
Jun 10, 2011
203
return (ogg_sync_wrote(sync, buflen) == 0) ? 1 : -1;
204
205
} // FeedMoreOggData
Jun 10, 2011
Jun 10, 2011
206
207
208
// This massive function is where all the effort happens.
static void WorkerThread(TheoraDecoder *ctx)
209
210
211
{
// make sure we initialized the stream before using pagein, but the stream
// will know to ignore pages that aren't meant for it, so pass to both.
Jun 10, 2011
Jun 10, 2011
212
213
214
215
#define queue_ogg_page(ctx) do { \
if (tpackets) ogg_stream_pagein(&tstream, &page); \
if (vpackets) ogg_stream_pagein(&vstream, &page); \
} while (0)
216
217
218
219
unsigned long audioframes = 0;
unsigned long videoframes = 0;
double fps = 0.0;
Jun 10, 2011
Jun 10, 2011
220
221
int was_error = 1; // resets to 0 at the end.
int eos = 0; // end of stream flag.
Jun 10, 2011
Jun 10, 2011
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
// Too much Ogg/Vorbis/Theora state...
ogg_packet packet;
ogg_sync_state sync;
ogg_page page;
int vpackets = 0;
vorbis_info vinfo;
vorbis_comment vcomment;
ogg_stream_state vstream;
int vdsp_init = 0;
vorbis_dsp_state vdsp;
int tpackets = 0;
th_info tinfo;
th_comment tcomment;
ogg_stream_state tstream;
int vblock_init = 0;
vorbis_block vblock;
th_dec_ctx *tdec = NULL;
th_setup_info *tsetup = NULL;
ogg_sync_init(&sync);
vorbis_info_init(&vinfo);
vorbis_comment_init(&vcomment);
th_comment_init(&tcomment);
th_info_init(&tinfo);
247
248
249
250
int bos = 1;
while (!ctx->halt && bos)
{
Jun 23, 2011
Jun 23, 2011
251
if (FeedMoreOggData(ctx->io, &sync) <= 0)
Jun 10, 2011
Jun 10, 2011
252
goto cleanup;
253
254
// parse out the initial header.
Jun 10, 2011
Jun 10, 2011
255
while ( (!ctx->halt) && (ogg_sync_pageout(&sync, &page) > 0) )
256
257
258
{
ogg_stream_state test;
Jun 10, 2011
Jun 10, 2011
259
if (!ogg_page_bos(&page)) // not a header.
Jun 10, 2011
Jun 10, 2011
261
queue_ogg_page(ctx);
262
263
264
265
bos = 0;
break;
} // if
Jun 10, 2011
Jun 10, 2011
266
267
ogg_stream_init(&test, ogg_page_serialno(&page));
ogg_stream_pagein(&test, &page);
268
269
ogg_stream_packetout(&test, &packet);
Jun 10, 2011
Jun 10, 2011
270
if (!tpackets && (th_decode_headerin(&tinfo, &tcomment, &tsetup, &packet) >= 0))
Jun 10, 2011
Jun 10, 2011
272
273
memcpy(&tstream, &test, sizeof (test));
tpackets = 1;
274
} // if
Jun 10, 2011
Jun 10, 2011
275
else if (!vpackets && (vorbis_synthesis_headerin(&vinfo, &vcomment, &packet) >= 0))
Jun 10, 2011
Jun 10, 2011
277
278
memcpy(&vstream, &test, sizeof (test));
vpackets = 1;
279
280
281
282
283
284
285
286
287
288
} // else if
else
{
// whatever it is, we don't care about it
ogg_stream_clear(&test);
} // else
} // while
} // while
// no audio OR video?
Jun 10, 2011
Jun 10, 2011
289
290
if (ctx->halt || (!vpackets && !tpackets))
goto cleanup;
291
292
// apparently there are two more theora and two more vorbis headers next.
Jun 10, 2011
Jun 10, 2011
293
while ((!ctx->halt) && ((tpackets && (tpackets < 3)) || (vpackets && (vpackets < 3))))
Jun 10, 2011
Jun 10, 2011
295
while (!ctx->halt && tpackets && (tpackets < 3))
Jun 10, 2011
Jun 10, 2011
297
if (ogg_stream_packetout(&tstream, &packet) != 1)
298
break; // get more data?
Jun 10, 2011
Jun 10, 2011
299
300
301
if (!th_decode_headerin(&tinfo, &tcomment, &tsetup, &packet))
goto cleanup;
tpackets++;
302
303
} // while
Jun 10, 2011
Jun 10, 2011
304
while (!ctx->halt && vpackets && (vpackets < 3))
Jun 10, 2011
Jun 10, 2011
306
if (ogg_stream_packetout(&vstream, &packet) != 1)
307
break; // get more data?
Jun 10, 2011
Jun 10, 2011
308
309
310
if (vorbis_synthesis_headerin(&vinfo, &vcomment, &packet))
goto cleanup;
vpackets++;
311
312
313
} // while
// get another page, try again?
Jun 10, 2011
Jun 10, 2011
314
315
if (ogg_sync_pageout(&sync, &page) > 0)
queue_ogg_page(ctx);
Jun 23, 2011
Jun 23, 2011
316
else if (FeedMoreOggData(ctx->io, &sync) <= 0)
Jun 10, 2011
Jun 10, 2011
317
goto cleanup;
318
319
320
} // while
// okay, now we have our streams, ready to set up decoding.
Jun 10, 2011
Jun 10, 2011
321
if (!ctx->halt && tpackets)
322
323
{
// th_decode_alloc() docs say to check for insanely large frames yourself.
Jun 10, 2011
Jun 10, 2011
324
325
if ((tinfo.frame_width > 99999) || (tinfo.frame_height > 99999))
goto cleanup;
Jun 15, 2011
Jun 15, 2011
327
328
// We treat "unspecified" as NTSC. *shrug*
if ( (tinfo.colorspace != TH_CS_UNSPECIFIED) &&
Jun 15, 2011
Jun 15, 2011
329
330
(tinfo.colorspace != TH_CS_ITU_REC_470M) &&
(tinfo.colorspace != TH_CS_ITU_REC_470BG) )
Jun 15, 2011
Jun 15, 2011
331
332
333
334
335
{
assert(0 && "Unsupported colorspace."); // !!! FIXME
goto cleanup;
} // if
Jun 10, 2011
Jun 10, 2011
336
if (tinfo.pixel_fmt != TH_PF_420) { assert(0); goto cleanup; } // !!! FIXME
Jun 10, 2011
Jun 10, 2011
338
339
if (tinfo.fps_denominator != 0)
fps = ((double) tinfo.fps_numerator) / ((double) tinfo.fps_denominator);
Jun 10, 2011
Jun 10, 2011
341
342
tdec = th_decode_alloc(&tinfo, tsetup);
if (!tdec) goto cleanup;
343
344
345
346
// Set decoder to maximum post-processing level.
// Theoretically we could try dropping this level if we're not keeping up.
int pp_level_max = 0;
Jun 15, 2011
Jun 15, 2011
347
348
// !!! FIXME: maybe an API to set this?
//th_decode_ctl(tdec, TH_DECCTL_GET_PPLEVEL_MAX, &pp_level_max, sizeof(pp_level_max));
Jun 10, 2011
Jun 10, 2011
349
th_decode_ctl(tdec, TH_DECCTL_SET_PPLEVEL, &pp_level_max, sizeof(pp_level_max));
350
351
352
} // if
// Done with this now.
Jun 10, 2011
Jun 10, 2011
353
if (tsetup != NULL)
Jun 10, 2011
Jun 10, 2011
355
356
th_setup_free(tsetup);
tsetup = NULL;
357
358
} // if
Jun 10, 2011
Jun 10, 2011
359
if (!ctx->halt && vpackets)
Jun 10, 2011
Jun 10, 2011
361
362
363
364
365
366
vdsp_init = (vorbis_synthesis_init(&vdsp, &vinfo) == 0);
if (!vdsp_init)
goto cleanup;
vblock_init = (vorbis_block_init(&vdsp, &vblock) == 0);
if (!vblock_init)
goto cleanup;
367
368
369
370
371
} // if
// Now we can start the actual decoding!
// Note that audio and video don't _HAVE_ to start simultaneously.
Apr 23, 2013
Apr 23, 2013
372
Mutex_Lock(ctx->lock);
Jun 24, 2011
Jun 24, 2011
373
374
375
ctx->prepped = 1;
ctx->hasvideo = (tpackets != 0);
ctx->hasaudio = (vpackets != 0);
Apr 23, 2013
Apr 23, 2013
376
Mutex_Unlock(ctx->lock);
Jun 24, 2011
Jun 24, 2011
377
Jun 10, 2011
Jun 10, 2011
378
while (!ctx->halt && !eos)
379
380
381
382
383
384
{
int need_pages = 0; // need more Ogg pages?
int saw_video_frame = 0;
// Try to read as much audio as we can at once. We limit the outer
// loop to one video frame and as much audio as we can eat.
Jun 11, 2011
Jun 11, 2011
385
while (!ctx->halt && vpackets)
386
387
{
float **pcm = NULL;
Jun 10, 2011
Jun 10, 2011
388
const int frames = vorbis_synthesis_pcmout(&vdsp, &pcm);
389
390
if (frames > 0)
{
Jun 10, 2011
Jun 10, 2011
391
const int channels = vinfo.channels;
392
393
int chanidx, frameidx;
float *samples;
Jun 15, 2011
Jun 15, 2011
394
AudioPacket *item = (AudioPacket *) malloc(sizeof (AudioPacket));
Jun 10, 2011
Jun 10, 2011
395
396
if (item == NULL) goto cleanup;
item->playms = (unsigned long) ((((double) audioframes) / ((double) vinfo.rate)) * 1000.0);
397
item->channels = channels;
Jun 11, 2011
Jun 11, 2011
398
item->freq = vinfo.rate;
399
400
401
402
403
404
405
item->frames = frames;
item->samples = (float *) malloc(sizeof (float) * frames * channels);
item->next = NULL;
if (item->samples == NULL)
{
free(item);
Jun 10, 2011
Jun 10, 2011
406
goto cleanup;
407
408
409
410
} // if
// I bet this beats the crap out of the CPU cache...
samples = item->samples;
Jun 11, 2011
Jun 11, 2011
411
for (frameidx = 0; frameidx < frames; frameidx++)
412
413
414
415
416
{
for (chanidx = 0; chanidx < channels; chanidx++)
*(samples++) = pcm[chanidx][frameidx];
} // for
Jun 10, 2011
Jun 10, 2011
417
vorbis_synthesis_read(&vdsp, frames); // we ate everything.
418
419
audioframes += frames;
Jun 11, 2011
Jun 11, 2011
420
//printf("Decoded %d frames of audio.\n", (int) frames);
Apr 23, 2013
Apr 23, 2013
421
Mutex_Lock(ctx->lock);
Jun 24, 2011
Jun 24, 2011
422
ctx->audioms += item->playms;
423
424
425
426
427
428
429
430
431
432
433
if (ctx->audiolisttail)
{
assert(ctx->audiolist);
ctx->audiolisttail->next = item;
} // if
else
{
assert(!ctx->audiolist);
ctx->audiolist = item;
} // else
ctx->audiolisttail = item;
Apr 23, 2013
Apr 23, 2013
434
Mutex_Unlock(ctx->lock);
435
436
437
438
439
} // if
else // no audio available left in current packet?
{
// try to feed another packet to the Vorbis stream...
Jun 10, 2011
Jun 10, 2011
440
if (ogg_stream_packetout(&vstream, &packet) <= 0)
Jun 24, 2011
Jun 24, 2011
441
442
443
{
if (!tpackets)
need_pages = 1; // no video, get more pages now.
Jun 11, 2011
Jun 11, 2011
444
break; // we'll get more pages when the video catches up.
Jun 24, 2011
Jun 24, 2011
445
} // if
446
447
else
{
Jun 10, 2011
Jun 10, 2011
448
449
if (vorbis_synthesis(&vblock, &packet) == 0)
vorbis_synthesis_blockin(&vdsp, &vblock);
450
451
452
453
} // else
} // else
} // while
Jun 10, 2011
Jun 10, 2011
454
if (!ctx->halt && tpackets)
455
456
457
{
// Theora, according to example_player.c, is
// "one [packet] in, one [frame] out."
Jun 10, 2011
Jun 10, 2011
458
if (ogg_stream_packetout(&tstream, &packet) <= 0)
459
460
461
462
need_pages = 1;
else
{
ogg_int64_t granulepos = 0;
Jun 10, 2011
Jun 10, 2011
463
const int rc = th_decode_packetin(tdec, &packet, &granulepos);
464
465
466
467
468
if (rc == TH_DUPFRAME)
videoframes++; // nothing else to do.
else if (rc == 0) // new frame!
{
th_ycbcr_buffer ycbcr;
Jun 10, 2011
Jun 10, 2011
469
if (th_decode_ycbcr_out(tdec, ycbcr) == 0)
Jun 15, 2011
Jun 15, 2011
471
VideoFrame *item = (VideoFrame *) malloc(sizeof (VideoFrame));
Jun 10, 2011
Jun 10, 2011
472
if (item == NULL) goto cleanup;
Jun 11, 2011
Jun 11, 2011
473
item->playms = (fps == 0) ? 0 : (unsigned int) ((((double) videoframes) / fps) * 1000.0);
Jun 11, 2011
Jun 11, 2011
474
item->fps = fps;
Jun 15, 2011
Jun 15, 2011
475
476
477
478
item->width = tinfo.pic_width;
item->height = tinfo.pic_height;
item->format = ctx->vidfmt;
item->pixels = ctx->vidcvt(&tinfo, ycbcr);
479
480
item->next = NULL;
Jun 15, 2011
Jun 15, 2011
481
if (item->pixels == NULL)
482
483
{
free(item);
Jun 10, 2011
Jun 10, 2011
484
goto cleanup;
485
486
} // if
Jun 11, 2011
Jun 11, 2011
487
//printf("Decoded another video frame.\n");
Apr 23, 2013
Apr 23, 2013
488
Mutex_Lock(ctx->lock);
489
490
491
492
493
494
495
496
497
498
499
500
if (ctx->videolisttail)
{
assert(ctx->videolist);
ctx->videolisttail->next = item;
} // if
else
{
assert(!ctx->videolist);
ctx->videolist = item;
} // else
ctx->videolisttail = item;
ctx->videocount++;
Apr 23, 2013
Apr 23, 2013
501
Mutex_Unlock(ctx->lock);
502
503
504
505
506
507
508
509
510
511
saw_video_frame = 1;
} // if
videoframes++;
} // if
} // else
} // if
if (!ctx->halt && need_pages)
{
Jun 23, 2011
Jun 23, 2011
512
const int rc = FeedMoreOggData(ctx->io, &sync);
Jun 10, 2011
Jun 10, 2011
513
514
515
516
517
518
519
520
521
if (rc == 0)
eos = 1; // end of stream
else if (rc < 0)
goto cleanup; // i/o error, etc.
else
{
while (!ctx->halt && (ogg_sync_pageout(&sync, &page) > 0))
queue_ogg_page(ctx);
} // else
522
523
524
525
526
527
} // if
// Sleep the process until we have space for more frames.
if (saw_video_frame)
{
int go_on = !ctx->halt;
Jun 11, 2011
Jun 11, 2011
528
//printf("Sleeping.\n");
529
530
531
while (go_on)
{
// !!! FIXME: This is stupid. I should use a semaphore for this.
Apr 23, 2013
Apr 23, 2013
532
Mutex_Lock(ctx->lock);
533
go_on = !ctx->halt && (ctx->videocount >= ctx->maxframes);
Apr 23, 2013
Apr 23, 2013
534
Mutex_Unlock(ctx->lock);
535
if (go_on)
May 19, 2013
May 19, 2013
536
sleepms(10);
537
} // while
Jun 11, 2011
Jun 11, 2011
538
//printf("Awake!\n");
539
540
} // if
} // while
Jun 10, 2011
Jun 10, 2011
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
was_error = 0;
cleanup:
ctx->decode_error = (!ctx->halt && was_error);
if (tdec != NULL) th_decode_free(tdec);
if (tsetup != NULL) th_setup_free(tsetup);
if (vblock_init) vorbis_block_clear(&vblock);
if (vdsp_init) vorbis_dsp_clear(&vdsp);
if (tpackets) ogg_stream_clear(&tstream);
if (vpackets) ogg_stream_clear(&vstream);
th_info_clear(&tinfo);
th_comment_clear(&tcomment);
vorbis_comment_clear(&vcomment);
vorbis_info_clear(&vinfo);
ogg_sync_clear(&sync);
Jun 23, 2011
Jun 23, 2011
557
ctx->io->close(ctx->io);
Jun 10, 2011
Jun 10, 2011
558
ctx->thread_done = 1;
559
560
561
562
563
564
565
} // WorkerThread
static void *WorkerThreadEntry(void *_this)
{
TheoraDecoder *ctx = (TheoraDecoder *) _this;
WorkerThread(ctx);
Jun 11, 2011
Jun 11, 2011
566
//printf("Worker thread is done.\n");
567
568
569
return NULL;
} // WorkerThreadEntry
Jun 10, 2011
Jun 10, 2011
570
Jun 23, 2011
Jun 23, 2011
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
static long IoFopenRead(THEORAPLAY_Io *io, void *buf, long buflen)
{
FILE *f = (FILE *) io->userdata;
const size_t br = fread(buf, 1, buflen, f);
if ((br == 0) && ferror(f))
return -1;
return (long) br;
} // IoFopenRead
static void IoFopenClose(THEORAPLAY_Io *io)
{
FILE *f = (FILE *) io->userdata;
fclose(f);
free(io);
} // IoFopenClose
THEORAPLAY_Decoder *THEORAPLAY_startDecodeFile(const char *fname,
const unsigned int maxframes,
THEORAPLAY_VideoFormat vidfmt)
{
THEORAPLAY_Io *io = (THEORAPLAY_Io *) malloc(sizeof (THEORAPLAY_Io));
if (io == NULL)
return NULL;
FILE *f = fopen(fname, "rb");
if (f == NULL)
{
free(io);
return NULL;
} // if
io->read = IoFopenRead;
io->close = IoFopenClose;
io->userdata = f;
return THEORAPLAY_startDecode(io, maxframes, vidfmt);
} // THEORAPLAY_startDecodeFile
THEORAPLAY_Decoder *THEORAPLAY_startDecode(THEORAPLAY_Io *io,
Jun 15, 2011
Jun 15, 2011
612
613
const unsigned int maxframes,
THEORAPLAY_VideoFormat vidfmt)
Jun 10, 2011
Jun 10, 2011
614
{
Jun 15, 2011
Jun 15, 2011
615
616
617
618
619
TheoraDecoder *ctx = NULL;
ConvertVideoFrameFn vidcvt = NULL;
switch (vidfmt)
{
Jun 15, 2011
Jun 15, 2011
620
621
// !!! FIXME: current expects TH_PF_420.
#define VIDCVT(t) case THEORAPLAY_VIDFMT_##t: vidcvt = ConvertVideoFrame420To##t; break;
Jun 15, 2011
Jun 15, 2011
622
VIDCVT(YV12)
Jun 19, 2011
Jun 19, 2011
623
VIDCVT(IYUV)
Jun 15, 2011
Jun 15, 2011
624
625
626
VIDCVT(RGB)
VIDCVT(RGBA)
#undef VIDCVT
Jun 23, 2011
Jun 23, 2011
627
default: goto startdecode_failed; // invalid/unsupported format.
Jun 15, 2011
Jun 15, 2011
628
629
} // switch
May 19, 2013
May 19, 2013
630
ctx = (TheoraDecoder *) malloc(sizeof (TheoraDecoder));
Jun 10, 2011
Jun 10, 2011
631
if (ctx == NULL)
Jun 23, 2011
Jun 23, 2011
632
goto startdecode_failed;
Jun 10, 2011
Jun 10, 2011
633
634
635
memset(ctx, '\0', sizeof (TheoraDecoder));
ctx->maxframes = maxframes;
Jun 15, 2011
Jun 15, 2011
636
637
ctx->vidfmt = vidfmt;
ctx->vidcvt = vidcvt;
Jun 23, 2011
Jun 23, 2011
638
ctx->io = io;
Jun 10, 2011
Jun 10, 2011
639
Apr 23, 2013
Apr 23, 2013
640
if (Mutex_Create(ctx) == 0)
Jun 10, 2011
Jun 10, 2011
641
{
Apr 23, 2013
Apr 23, 2013
642
ctx->thread_created = (Thread_Create(ctx, WorkerThreadEntry) == 0);
Jun 23, 2011
Jun 23, 2011
643
644
if (ctx->thread_created)
return (THEORAPLAY_Decoder *) ctx;
Jun 10, 2011
Jun 10, 2011
645
646
} // if
Apr 23, 2013
Apr 23, 2013
647
Mutex_Destroy(ctx->lock);
Jun 23, 2011
Jun 23, 2011
648
649
650
startdecode_failed:
io->close(io);
Jun 10, 2011
Jun 10, 2011
651
652
653
654
655
656
657
658
free(ctx);
return NULL;
} // THEORAPLAY_startDecode
void THEORAPLAY_stopDecode(THEORAPLAY_Decoder *decoder)
{
TheoraDecoder *ctx = (TheoraDecoder *) decoder;
Jun 14, 2011
Jun 14, 2011
659
660
if (!ctx)
return;
Jun 10, 2011
Jun 10, 2011
661
662
663
664
if (ctx->thread_created)
{
ctx->halt = 1;
Apr 23, 2013
Apr 23, 2013
665
666
Thread_Join(ctx->worker);
Mutex_Destroy(ctx->lock);
Jun 10, 2011
Jun 10, 2011
667
668
} // if
Jun 15, 2011
Jun 15, 2011
669
VideoFrame *videolist = ctx->videolist;
Jun 10, 2011
Jun 10, 2011
670
671
while (videolist)
{
Jun 15, 2011
Jun 15, 2011
672
VideoFrame *next = videolist->next;
Jun 15, 2011
Jun 15, 2011
673
free(videolist->pixels);
Jun 10, 2011
Jun 10, 2011
674
675
676
677
free(videolist);
videolist = next;
} // while
Jun 15, 2011
Jun 15, 2011
678
AudioPacket *audiolist = ctx->audiolist;
Jun 10, 2011
Jun 10, 2011
679
680
while (audiolist)
{
Jun 15, 2011
Jun 15, 2011
681
AudioPacket *next = audiolist->next;
Jun 10, 2011
Jun 10, 2011
682
683
684
685
686
687
688
689
690
691
692
free(audiolist->samples);
free(audiolist);
audiolist = next;
} // while
free(ctx);
} // THEORAPLAY_stopDecode
int THEORAPLAY_isDecoding(THEORAPLAY_Decoder *decoder)
{
Jun 24, 2011
Jun 24, 2011
693
694
695
696
TheoraDecoder *ctx = (TheoraDecoder *) decoder;
int retval = 0;
if (ctx)
{
Apr 23, 2013
Apr 23, 2013
697
Mutex_Lock(ctx->lock);
Jun 24, 2011
Jun 24, 2011
698
699
retval = ( ctx && (ctx->audiolist || ctx->videolist ||
(ctx->thread_created && !ctx->thread_done)) );
Apr 23, 2013
Apr 23, 2013
700
Mutex_Unlock(ctx->lock);
Jun 24, 2011
Jun 24, 2011
701
702
} // if
return retval;
Jun 10, 2011
Jun 10, 2011
703
704
705
} // THEORAPLAY_isDecoding
Jun 24, 2011
Jun 24, 2011
706
707
708
709
#define GET_SYNCED_VALUE(typ, defval, decoder, member) \
TheoraDecoder *ctx = (TheoraDecoder *) decoder; \
typ retval = defval; \
if (ctx) { \
Apr 23, 2013
Apr 23, 2013
710
Mutex_Lock(ctx->lock); \
Jun 24, 2011
Jun 24, 2011
711
retval = ctx->member; \
Apr 23, 2013
Apr 23, 2013
712
Mutex_Unlock(ctx->lock); \
Jun 24, 2011
Jun 24, 2011
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
} \
return retval;
int THEORAPLAY_isInitialized(THEORAPLAY_Decoder *decoder)
{
GET_SYNCED_VALUE(int, 0, decoder, prepped);
} // THEORAPLAY_isInitialized
int THEORAPLAY_hasVideoStream(THEORAPLAY_Decoder *decoder)
{
GET_SYNCED_VALUE(int, 0, decoder, hasvideo);
} // THEORAPLAY_hasVideoStream
int THEORAPLAY_hasAudioStream(THEORAPLAY_Decoder *decoder)
{
GET_SYNCED_VALUE(int, 0, decoder, hasaudio);
} // THEORAPLAY_hasAudioStream
unsigned int THEORAPLAY_availableVideo(THEORAPLAY_Decoder *decoder)
{
GET_SYNCED_VALUE(unsigned int, 0, decoder, videocount);
} // THEORAPLAY_hasAudioStream
unsigned int THEORAPLAY_availableAudio(THEORAPLAY_Decoder *decoder)
{
GET_SYNCED_VALUE(unsigned int, 0, decoder, audioms);
} // THEORAPLAY_hasAudioStream
Jun 10, 2011
Jun 10, 2011
746
747
int THEORAPLAY_decodingError(THEORAPLAY_Decoder *decoder)
{
Jun 24, 2011
Jun 24, 2011
748
GET_SYNCED_VALUE(int, 0, decoder, decode_error);
Jun 10, 2011
Jun 10, 2011
749
750
751
} // THEORAPLAY_decodingError
Jun 15, 2011
Jun 15, 2011
752
const THEORAPLAY_AudioPacket *THEORAPLAY_getAudio(THEORAPLAY_Decoder *decoder)
Jun 10, 2011
Jun 10, 2011
753
754
{
TheoraDecoder *ctx = (TheoraDecoder *) decoder;
Jun 15, 2011
Jun 15, 2011
755
AudioPacket *retval;
Jun 10, 2011
Jun 10, 2011
756
Apr 23, 2013
Apr 23, 2013
757
Mutex_Lock(ctx->lock);
Jun 10, 2011
Jun 10, 2011
758
759
760
retval = ctx->audiolist;
if (retval)
{
Jun 24, 2011
Jun 24, 2011
761
ctx->audioms -= retval->playms;
Jun 10, 2011
Jun 10, 2011
762
763
764
765
766
ctx->audiolist = retval->next;
retval->next = NULL;
if (ctx->audiolist == NULL)
ctx->audiolisttail = NULL;
} // if
Apr 23, 2013
Apr 23, 2013
767
Mutex_Unlock(ctx->lock);
Jun 10, 2011
Jun 10, 2011
768
769
770
771
772
return retval;
} // THEORAPLAY_getAudio
Jun 15, 2011
Jun 15, 2011
773
void THEORAPLAY_freeAudio(const THEORAPLAY_AudioPacket *_item)
Jun 10, 2011
Jun 10, 2011
774
{
Jun 15, 2011
Jun 15, 2011
775
THEORAPLAY_AudioPacket *item = (THEORAPLAY_AudioPacket *) _item;
Jun 11, 2011
Jun 11, 2011
776
777
778
779
780
781
if (item != NULL)
{
assert(item->next == NULL);
free(item->samples);
free(item);
} // if
Jun 10, 2011
Jun 10, 2011
782
783
784
} // THEORAPLAY_freeAudio
Jun 15, 2011
Jun 15, 2011
785
const THEORAPLAY_VideoFrame *THEORAPLAY_getVideo(THEORAPLAY_Decoder *decoder)
Jun 10, 2011
Jun 10, 2011
786
787
{
TheoraDecoder *ctx = (TheoraDecoder *) decoder;
Jun 15, 2011
Jun 15, 2011
788
VideoFrame *retval;
Jun 10, 2011
Jun 10, 2011
789
Apr 23, 2013
Apr 23, 2013
790
Mutex_Lock(ctx->lock);
Jun 10, 2011
Jun 10, 2011
791
792
793
794
795
796
797
798
799
800
retval = ctx->videolist;
if (retval)
{
ctx->videolist = retval->next;
retval->next = NULL;
if (ctx->videolist == NULL)
ctx->videolisttail = NULL;
assert(ctx->videocount > 0);
ctx->videocount--;
} // if
Apr 23, 2013
Apr 23, 2013
801
Mutex_Unlock(ctx->lock);
Jun 10, 2011
Jun 10, 2011
802
803
804
805
806
return retval;
} // THEORAPLAY_getVideo
Jun 15, 2011
Jun 15, 2011
807
void THEORAPLAY_freeVideo(const THEORAPLAY_VideoFrame *_item)
Jun 10, 2011
Jun 10, 2011
808
{
Jun 15, 2011
Jun 15, 2011
809
THEORAPLAY_VideoFrame *item = (THEORAPLAY_VideoFrame *) _item;
Jun 11, 2011
Jun 11, 2011
810
811
812
if (item != NULL)
{
assert(item->next == NULL);
Jun 15, 2011
Jun 15, 2011
813
free(item->pixels);
Jun 11, 2011
Jun 11, 2011
814
815
free(item);
} // if
Jun 10, 2011
Jun 10, 2011
816
817
} // THEORAPLAY_freeVideo
818
// end of theoraplay.cpp ...