1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "sludge/movie.h"
24 #include "sludge/sound.h"
25
26 namespace Sludge {
27
28 // sound_openal.cpp
29 void playMovieStream(int a);
30 #if 0
31 int initMovieSound(int f, ALenum format, int audioChannels, ALuint samplerate,
32 ALuint(*callback)(void *userdata, ALubyte *data, ALuint bytes));
33 #endif
34
35 MovieStates movieIsPlaying = nothing;
36
37 int movieIsEnding = 0;
38
39 float movieAspect = 1.6F;
40 #if 0
41 typedef struct audioBuffers {
42 char *buffer;
43 uint size;
44 audioBuffers *next;
45 Uint32 time_ms;
46 }audioBuffers;
47
48 typedef struct audioQueue {
49 audioBuffers *first, *last;
50 int size;
51 SDL_mutex *mutex;
52 SDL_cond *cond;
53 }audioQueue;
54
55 audioQueue audioQ;
56
57 uint32 movieStartTick, movieCurrentTime;
58
59 int64 audioNsPerByte;
60 int64 audioNsPlayed;
61 int64 audioNsBuffered;
62 int64 audioBufferLen;
63 bool movieSoundPlaying = false;
64 int movieAudioIndex;
65 GLuint yTextureName = 0;
66 GLuint uTextureName = 0;
67 GLuint vTextureName = 0;
68
69 typedef struct videoBuffers {
70 GLubyte *ytex;
71 GLubyte *utex;
72 GLubyte *vtex;
73 videoBuffers *next;
74 GLsizei w, h;
75 Uint32 time_ms;
76 }videoBuffers;
77
78 typedef struct videoQueue {
79 videoBuffers *first, *last;
80 int size;
81 SDL_mutex *mutex;
82 SDL_cond *cond;
83 }videoQueue;
84
85 videoQueue videoQ;
86
87 void audio_queue_init(audioQueue *q) {
88 memset(q, 0, sizeof(audioQueue));
89
90 q->mutex = SDL_CreateMutex();
91 q->cond = SDL_CreateCond();
92
93 }
94 int audio_queue_put(audioQueue *q, char *buffer, uint size, int64 time_ms) {
95
96 audioBuffers *audioBuf = new audioBuffers;
97 if (!audioBuf)
98 return -1;
99 audioBuf->buffer = buffer;
100 audioBuf->next = NULL;
101 audioBuf->size = size;
102 audioBuf->time_ms = time_ms;
103
104 SDL_LockMutex(q->mutex);
105
106 if (!q->last)
107 q->first = audioBuf;
108 else
109 q->last->next = audioBuf;
110 q->last = audioBuf;
111 q->size ++;
112 SDL_CondSignal(q->cond);
113
114 SDL_UnlockMutex(q->mutex);
115
116 return 0;
117 }
118 inline static int audio_queue_get(audioQueue *q, char **buffer) {
119 int ret = 0;
120
121 audioBuffers *audioBuf;
122
123 SDL_LockMutex(q->mutex);
124
125 audioBuf = q->first;
126 if (audioBuf) {
127 // Synch video timer to audio
128 Uint32 tick = SDL_GetTicks() + 100;
129 if (ABS((long int)((tick - movieStartTick) - (audioBuf->time_ms))) > 300) {
130 movieStartTick = tick - audioBuf->time_ms;
131 }
132
133 q->first = audioBuf->next;
134 if (!q->first)
135 q->last = NULL;
136 q->size--;
137 *buffer = audioBuf->buffer;
138 ret = audioBuf->size;
139 delete audioBuf;
140 }
141
142 SDL_UnlockMutex(q->mutex);
143
144 return ret;
145 }
146
147 void video_queue_init(videoQueue *q) {
148 memset(q, 0, sizeof(videoQueue));
149 q->mutex = SDL_CreateMutex();
150 q->cond = SDL_CreateCond();
151 }
152 int video_queue_put(videoQueue *q, GLubyte *ytex,
153 GLubyte *utex,
154 GLubyte *vtex,
155 GLsizei w, GLsizei h,
156 int64 time_ms) {
157
158 videoBuffers *videoBuf = new videoBuffers;
159 if (!videoBuf)
160 return -1;
161 videoBuf->ytex = ytex;
162 videoBuf->utex = utex;
163 videoBuf->vtex = vtex;
164 videoBuf->next = NULL;
165 videoBuf->w = w;
166 videoBuf->h = h;
167 videoBuf->time_ms = time_ms;
168
169 SDL_LockMutex(q->mutex);
170
171 if (!q->last)
172 q->first = videoBuf;
173 else
174 q->last->next = videoBuf;
175 q->last = videoBuf;
176 q->size ++;
177 SDL_CondSignal(q->cond);
178
179 SDL_UnlockMutex(q->mutex);
180 return 0;
181 }
182 inline static int video_queue_get(videoQueue *q,
183 GLubyte **ytex,
184 GLubyte **utex,
185 GLubyte **vtex,
186 GLsizei *w, GLsizei *h) {
187 videoBuffers *videoBuf;
188 int ret = 0;
189
190 SDL_LockMutex(q->mutex);
191
192 videoBuf = q->first;
193 if (videoBuf) {
194 q->first = videoBuf->next;
195 if (!q->first)
196 q->last = NULL;
197 q->size--;
198 *ytex = videoBuf->ytex;
199 *utex = videoBuf->utex;
200 *vtex = videoBuf->vtex;
201 *w = videoBuf->w;
202 *h = videoBuf->h;
203 ret = 1;
204 delete videoBuf;
205 }
206
207 SDL_UnlockMutex(q->mutex);
208
209 return ret;
210 }
211
212 #if 0
213 static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
214 //const char *detail = vpx_codec_error_detail(ctx);
215 fatal(s, vpx_codec_error(ctx));
216 }
217 #endif
218
219 void setMovieViewport() {
220 float realAspect = (float) realWinWidth / realWinHeight;
221
222 int vpHeight, vpWidth, vpOffsetX, vpOffsetY;
223 if (realAspect > movieAspect) {
224 vpHeight = realWinHeight;
225 vpWidth = (int)(realWinHeight * movieAspect);
226 vpOffsetY = 0;
227 vpOffsetX = (realWinWidth - vpWidth) / 2;
228 } else {
229 vpWidth = realWinWidth;
230 vpHeight = (int)((float) realWinWidth / movieAspect);
231 vpOffsetY = (realWinHeight - vpHeight) / 2;
232 vpOffsetX = 0;
233 }
234 #if 0
235 glViewport(vpOffsetX, vpOffsetY, vpWidth, vpHeight);
236 #endif
237 const GLfloat bPMVMatrix[] = {
238 2.0f / 640.f, .0, .0, .0,
239 .0, -2.0f / 400.f, .0, .0,
240 .0, .0, 1.0f, .0,
241 -1.0, 1.0f, .0, 1.0f
242
243 };
244 for (int i = 0; i < 16; i++) {
245 aPMVMatrix[i] = bPMVMatrix[i];
246 }
247 }
248
249 static uint64_t xiph_lace_value(byte **np) {
250 uint64_t lace;
251 uint64_t value;
252 byte *p = *np;
253
254 lace = *p++;
255 value = lace;
256 while (lace == 255) {
257 lace = *p++;
258 value += lace;
259 }
260
261 *np = p;
262
263 return value;
264 }
265
266 vorbis_dsp_state vorbisDspState;
267 int64 audioChannels;
268
269 bool fakeAudio = false;
270
271 // send audio to audio device...
272 ALuint feedAudio(void *userdata, ALubyte *data, ALuint length) {
273 static char *buffer = NULL;
274 static uint bufOffset = 0;
275 static uint bufSize = 0;
276
277 ALuint got = 0;
278 int bufLen;
279
280 if (! buffer) {
281 bufSize = audio_queue_get(&audioQ, &buffer);
282 bufOffset = 0;
283 if (bufSize <= 0) {
284 bufSize = 0;
285 buffer = NULL;
286 if (! got) {
287 got = audioChannels * 2;
288 memset(data, 0, got);
289 fprintf(stderr, "Faking audio...\n");
290 fakeAudio = true;
291 }
292 // SDL_CondSignal(audioQ.cond);
293 return got;
294 }
295 }
296
297 fakeAudio = false;
298
299 if (length > bufSize - bufOffset)
300 bufLen = bufSize - bufOffset;
301 else
302 bufLen = length;
303
304 memcpy(data, buffer + bufOffset, bufLen);
305
306 bufOffset += bufLen;
307 length -= bufLen;
308 got += bufLen;
309
310 if (bufSize <= bufOffset) {
311 buffer = NULL;
312 delete [] buffer;
313 }
314 // fprintf (stderr, "Sending %d bytes of audio.\n", got);
315
316 return got;
317 }
318 #endif
319
playMovie(int fileNumber)320 int playMovie(int fileNumber) {
321 #if 0
322 if (specialSettings & SPECIAL_SILENT)
323 return 0;
324
325 if (movieIsPlaying) return 0;
326
327 movieSoundPlaying = false;
328
329 vpx_codec_ctx_t codec;
330
331 float pausefade = 1.0;
332
333 using namespace mkvparser;
334
335 MkvReader reader;
336
337 if (reader.Open(fileNumber)) {
338 warning(ERROR_MOVIE_ODDNESS);
339 return 0;
340 }
341
342 int64 pos = 0;
343
344 EBMLHeader ebmlHeader;
345
346 ebmlHeader.Parse(&reader, pos);
347
348 mkvparser::Segment *pSegment;
349
350 int64 ret = mkvparser::Segment::CreateInstance(&reader, pos, pSegment);
351 if (ret) {
352 fatal("Movie error: Segment::CreateInstance() failed.\n");
353 }
354
355 ret = pSegment->Load();
356 if (ret < 0) {
357 fatal("Movie error: Segment::Load() failed.\n");
358 }
359
360 //const SegmentInfo* const pSegmentInfo = pSegment->GetInfo();
361 //const int64 timeCodeScale = pSegmentInfo->GetTimeCodeScale();
362 //const int64 duration_ns = pSegmentInfo->GetDuration();
363 //const char* const pTitle = pSegmentInfo->GetTitleAsUTF8();
364 //const char* const pMuxingApp = pSegmentInfo->GetMuxingAppAsUTF8();
365 //const char* const pWritingApp = pSegmentInfo->GetWritingAppAsUTF8();
366
367 const mkvparser::Tracks *pTracks = pSegment->GetTracks();
368
369 uint32 i = 0;
370 const uint32 j = pTracks->GetTracksCount();
371
372 enum {VIDEO_TRACK = 1, AUDIO_TRACK = 2};
373 int videoTrack = -1;
374 int audioTrack = -1;
375 int64 audioBitDepth;
376 double audioSampleRate;
377 ogg_packet oggPacket;
378 vorbis_info vorbisInfo;
379 vorbis_comment vorbisComment;
380 vorbis_block vorbisBlock;
381
382 while (i != j) {
383 const Track *const pTrack = pTracks->GetTrackByIndex(i++);
384
385 if (pTrack == NULL)
386 continue;
387
388 const int64 trackType = pTrack->GetType();
389 //const unsigned int64 trackUid = pTrack->GetUid();
390 //const char* pTrackName = pTrack->GetNameAsUTF8();
391
392 if (trackType == VIDEO_TRACK && videoTrack < 0) {
393 videoTrack = pTrack->GetNumber();
394 const VideoTrack *const pVideoTrack =
395 static_cast<const VideoTrack *>(pTrack);
396
397 const int64 width = pVideoTrack->GetWidth();
398 const int64 height = pVideoTrack->GetHeight();
399
400 const double rate = pVideoTrack->GetFrameRate();
401
402 if (rate > 0)
403 Init_Special_Timer(rate);
404
405 movieAspect = (float)width / height;
406 }
407
408 if (trackType == AUDIO_TRACK && audioTrack < 0) {
409 audioTrack = pTrack->GetNumber();
410 const AudioTrack *const pAudioTrack =
411 static_cast<const AudioTrack *>(pTrack);
412
413 audioChannels = pAudioTrack->GetChannels();
414 audioBitDepth = pAudioTrack->GetBitDepth();
415 audioSampleRate = pAudioTrack->GetSamplingRate();
416
417 uint audioHeaderSize;
418 const byte *audioHeader = pAudioTrack->GetCodecPrivate(audioHeaderSize);
419
420 if (audioHeaderSize < 1) {
421 warning("Strange audio track in movie.");
422 audioTrack = -1;
423 continue;
424 }
425
426 byte *p = (byte *)audioHeader;
427
428 uint count = *p++ + 1;
429 if (count != 3) {
430 warning("Strange audio track in movie.");
431 audioTrack = -1;
432 continue;
433 }
434
435 uint64_t sizes[3], total;
436
437 int i = 0;
438 total = 0;
439 while (--count) {
440 sizes[i] = xiph_lace_value(&p);
441 total += sizes[i];
442 i += 1;
443 }
444 sizes[i] = audioHeaderSize - total - (p - audioHeader);
445
446 // initialize vorbis
447 vorbis_info_init(&vorbisInfo);
448 vorbis_comment_init(&vorbisComment);
449 memset(&vorbisDspState, 0, sizeof(vorbisDspState));
450 memset(&vorbisBlock, 0, sizeof(vorbisBlock));
451
452 oggPacket.e_o_s = false;
453 oggPacket.granulepos = 0;
454 oggPacket.packetno = 0;
455 int r;
456 for (int i = 0; i < 3; i++) {
457 oggPacket.packet = p;
458 oggPacket.bytes = sizes[i];
459 oggPacket.b_o_s = oggPacket.packetno == 0;
460 r = vorbis_synthesis_headerin(&vorbisInfo, &vorbisComment, &oggPacket);
461 if (r)
462 fprintf(stderr, "vorbis_synthesis_headerin failed, error: %d", r);
463 oggPacket.packetno++;
464 p += sizes[i];
465 }
466
467 r = vorbis_synthesis_init(&vorbisDspState, &vorbisInfo);
468 if (r)
469 fprintf(stderr, "vorbis_synthesis_init failed, error: %d", r);
470 r = vorbis_block_init(&vorbisDspState, &vorbisBlock);
471 if (r)
472 fprintf(stderr, "vorbis_block_init failed, error: %d", r);
473
474 ALenum audioFormat = alureGetSampleFormat(audioChannels, 16, 0);
475 movieAudioIndex = initMovieSound(fileNumber, audioFormat, audioChannels, (ALuint) audioSampleRate, feedAudio);
476
477 fprintf(stderr, "Movie sound inited.\n");
478 audio_queue_init(&audioQ);
479 audioNsPerByte = (1000000000 / audioSampleRate) / (audioChannels * 2);
480 audioNsBuffered = 0;
481 audioBufferLen = audioChannels * audioSampleRate;
482 }
483 }
484
485 if (videoTrack < 0)
486 fatal("Movie error: No video in movie file.");
487
488 if (audioTrack < 0)
489 fatal("Movie error: No sound found.");
490
491 video_queue_init(&videoQ);
492
493 const unsigned long clusterCount = pSegment->GetCount();
494
495 if (clusterCount == 0) {
496 fatal("Movie error: Segment has no clusters.\n");
497 }
498
499 /* Initialize video codec */
500 if (vpx_codec_dec_init(&codec, interface, NULL, 0))
501 die_codec(&codec, "Failed to initialize decoder for movie.");
502
503 byte *frame = new byte[256 * 1024];
504 if (! checkNew(frame)) return false;
505
506 const mkvparser::Cluster *pCluster = pSegment->GetFirst();
507
508 setMovieViewport();
509
510 movieIsPlaying = playing;
511 movieIsEnding = 0;
512
513 glDepthMask(GL_FALSE);
514 glDisable(GL_DEPTH_TEST);
515
516 //const int64 timeCode = pCluster->GetTimeCode();
517 int64 time_ns = pCluster->GetTime();
518
519 const BlockEntry *pBlockEntry = pCluster->GetFirst();
520
521 if ((pBlockEntry == NULL) || pBlockEntry->EOS()) {
522 pCluster = pSegment->GetNext(pCluster);
523 if ((pCluster == NULL) || pCluster->EOS()) {
524 fatal("Error: No movie found in the movie file.");
525 }
526 pBlockEntry = pCluster->GetFirst();
527 }
528 const Block *pBlock = pBlockEntry->GetBlock();
529 int64 trackNum = pBlock->GetTrackNumber();
530 unsigned long tn = static_cast<unsigned long>(trackNum);
531 const Track *pTrack = pTracks->GetTrackByNumber(tn);
532 int64 trackType = pTrack->GetType();
533 int frameCount = pBlock->GetFrameCount();
534 time_ns = pBlock->GetTime(pCluster);
535
536 const GLfloat texCoords[] = {
537 0.0, 0.0,
538 1.0, 0.0,
539 0.0, 1.0,
540 1.0, 1.0
541 };
542
543 const GLfloat vertices[] = {
544 0.0, 0.0, 0.1,
545 640.0, 0.0, 0.1,
546 0.0, 400.0, 0.1,
547 640.0, 400.0, 0.1
548 };
549
550 const GLfloat vertices1[] = {
551 7.0, 7.0, 0.1,
552 17.0, 7.0, 0.1,
553 7.0, 29.0, 0.1,
554 17.0, 29.0, 0.1
555 };
556
557 const GLfloat vertices2[] = {
558 27.0, 7.0, 0.1,
559 37.0, 7.0, 0.1,
560 27.0, 29.0, 0.1,
561 37.0, 29.0, 0.1
562 };
563
564 const GLfloat vertices3[] = {
565 5.0, 5.0, 0.1,
566 15.0, 5.0, 0.1,
567 5.0, 27.0, 0.1,
568 15.0, 27.0, 0.1
569 };
570
571 const GLfloat vertices4[] = {
572 25.0, 5.0, 0.1,
573 35.0, 5.0, 0.1,
574 25.0, 27.0, 0.1,
575 35.0, 27.0, 0.1
576 };
577
578 int frameCounter = 0;
579
580 movieStartTick = SDL_GetTicks();
581
582 while (movieIsPlaying) {
583
584 checkInput();
585 if (weAreDoneSoQuit)
586 break;
587 handleInput();
588
589 if (movieIsPlaying && (! movieIsEnding) && (videoQ.size < 100 || audioQ.size < 100)) {
590 // Decode a frame!
591
592 if ((pCluster != NULL) && !pCluster->EOS()) {
593
594 if (frameCounter >= frameCount) {
595
596 pBlockEntry = pCluster->GetNext(pBlockEntry);
597 if ((pBlockEntry == NULL) || pBlockEntry->EOS()) {
598 pCluster = pSegment->GetNext(pCluster);
599 if ((pCluster == NULL) || pCluster->EOS()) {
600 goto movieHasEnded;
601 }
602 pBlockEntry = pCluster->GetFirst();
603 }
604 pBlock = pBlockEntry->GetBlock();
605 trackNum = pBlock->GetTrackNumber();
606 tn = static_cast<unsigned long>(trackNum);
607 pTrack = pTracks->GetTrackByNumber(tn);
608 trackType = pTrack->GetType();
609 frameCount = pBlock->GetFrameCount();
610 time_ns = pBlock->GetTime(pCluster);
611
612 frameCounter = 0;
613 }
614
615 const Block::Frame &theFrame = pBlock->GetFrame(frameCounter);
616 const long size = theFrame.len;
617 // const int64 offset = theFrame.pos;
618
619 if (size > sizeof(frame)) {
620 if (frame) delete [] frame;
621 frame = new byte[size];
622 if (! checkNew(frame)) return 0;
623 }
624 /*
625 fprintf (stderr, "Block :%s,%s,%15lld\n",
626 (trackType == VIDEO_TRACK) ? "V" : "A",
627 pBlock->IsKey() ? "I" : "P",
628 time_ns);
629 */
630
631 if (trackNum == videoTrack) {
632
633 theFrame.Read(&reader, frame);
634
635 /* Decode the frame */
636 if (vpx_codec_decode(&codec, frame, size, NULL, 0))
637 die_codec(&codec, "Failed to decode frame");
638
639 // Let's decode an image frame!
640 vpx_codec_iter_t iter = NULL;
641 vpx_image_t *img;
642 /* Get frame data */
643 while ((img = vpx_codec_get_frame(&codec, &iter))) {
644 if (img->fmt != VPX_IMG_FMT_I420)
645 fatal("Movie error. The movie is not in I420 colour format, which is the only one I can hanlde at the moment.");
646
647 uint y;
648
649 GLubyte *ytex = NULL;
650 GLubyte *utex = NULL;
651 GLubyte *vtex = NULL;
652
653 if (! ytex) {
654 ytex = new GLubyte [img->d_w * img->d_h];
655 utex = new GLubyte [(img->d_w >> 1) * (img->d_h >> 1)];
656 vtex = new GLubyte [(img->d_w >> 1) * (img->d_h >> 1)];
657 if (!ytex || !utex || !vtex)
658 fatal(ERROR_OUT_OF_MEMORY);
659
660 }
661
662 byte *buf = img->planes[0];
663 for (y = 0; y < img->d_h; y++) {
664 memcpy(ytex + y * img->d_w, buf, img->d_w);
665 buf += img->stride[0];
666 }
667 buf = img->planes[1];
668 for (y = 0; y < img->d_h >> 1; y++) {
669 memcpy(utex + y * (img->d_w >> 1), buf, img->d_w >> 1);
670 buf += img->stride[1];
671 }
672 buf = img->planes[2];
673 for (y = 0; y < img->d_h >> 1; y++) {
674 memcpy(vtex + y * (img->d_w >> 1), buf, img->d_w >> 1);
675 buf += img->stride[2];
676 }
677
678 video_queue_put(&videoQ, ytex, utex, vtex,
679 img->d_w, img->d_h, time_ns / 1000000);
680
681 }
682
683 } else if (trackNum == audioTrack) {
684 // Use this Audio Track
685 if (size > 0) {
686 theFrame.Read(&reader, frame);
687 oggPacket.packet = frame;
688 oggPacket.bytes = size;
689 oggPacket.b_o_s = false;
690 oggPacket.packetno++;
691 oggPacket.granulepos = -1;
692 if (! vorbis_synthesis(&vorbisBlock, &oggPacket)) {
693 if (vorbis_synthesis_blockin(&vorbisDspState, &vorbisBlock))
694 fprintf(stderr, "Vorbis Synthesis block in error.\n");
695
696 } else {
697 fprintf(stderr, "Vorbis Synthesis error.\n");
698 }
699
700 float **pcm;
701
702 int numSamples = vorbis_synthesis_pcmout(&vorbisDspState, &pcm);
703
704 if (numSamples > 0) {
705 int word = 2;
706 int sgned = 1;
707 int i, j;
708 long bytespersample = audioChannels * word;
709 vorbis_fpu_control fpu;
710
711 char *buffer = new char[bytespersample * numSamples];
712 if (! checkNew(buffer)) return false;
713
714 /* a tight loop to pack each size */
715 {
716 int val;
717 if (word == 1) {
718 int off = (sgned ? 0 : 128);
719 vorbis_fpu_setround(&fpu);
720 for (j = 0; j < numSamples; j++)
721 for (i = 0; i < audioChannels; i++) {
722 val = vorbis_ftoi(pcm[i][j] * 128.f);
723 if (val > 127)val = 127;
724 else if (val < -128)val = -128;
725 *buffer++ = val + off;
726 }
727 vorbis_fpu_restore(fpu);
728 } else {
729 int off = (sgned ? 0 : 32768);
730
731 if (sgned) {
732
733 vorbis_fpu_setround(&fpu);
734 for (i = 0; i < audioChannels; i++) { /* It's faster in this order */
735 float *src = pcm[i];
736 int16 *dest = ((int16 *)buffer) + i;
737 for (j = 0; j < numSamples; j++) {
738 val = vorbis_ftoi(src[j] * 32768.f);
739 if (val > 32767)val = 32767;
740 else if (val < -32768)val = -32768;
741 *dest = val;
742 dest += audioChannels;
743 }
744 }
745 vorbis_fpu_restore(fpu);
746
747 } else {
748
749 vorbis_fpu_setround(&fpu);
750 for (i = 0; i < audioChannels; i++) {
751 float *src = pcm[i];
752 int16 *dest = ((int16 *)buffer) + i;
753 for (j = 0; j < numSamples; j++) {
754 val = vorbis_ftoi(src[j] * 32768.f);
755 if (val > 32767)val = 32767;
756 else if (val < -32768)val = -32768;
757 *dest = val + off;
758 dest += audioChannels;
759 }
760 }
761 vorbis_fpu_restore(fpu);
762
763 }
764
765 }
766 }
767
768 vorbis_synthesis_read(&vorbisDspState, numSamples);
769 audioBufferLen = bytespersample * numSamples;
770 audio_queue_put(&audioQ, buffer, audioBufferLen, time_ns / 1000000);
771
772 //fprintf (stderr, "Audio buffered: %lld byte %lld ns\n",audioBufferLen, audioNsPerByte*audioBufferLen);
773
774 if (! movieSoundPlaying && size > 1) {
775 fprintf(stderr, "** starting sound ** \n");
776 playMovieStream(movieAudioIndex);
777 movieSoundPlaying = true;
778 }
779 }
780 }
781 }
782 frameCounter++;
783
784 } else {
785 movieHasEnded:
786 movieIsEnding = 1;
787 }
788 }
789
790 bool videoUpdated = false;
791 // Get a video frame.
792 if (movieIsPlaying == playing) {
793
794 videoBuffers *vB;
795 // Do we have decoded video waiting?
796 if (vB = videoQ.first) {
797 Uint32 tick = SDL_GetTicks() - movieStartTick;
798
799 // Is it time to display the frame yet?
800 if ((tick + 1) < vB->time_ms) {
801 SDL_Delay(1);
802 } else {
803 GLubyte *ytex = NULL;
804 GLubyte *utex = NULL;
805 GLubyte *vtex = NULL;
806 GLsizei w, h;
807
808 if (video_queue_get(&videoQ, &ytex, &utex, &vtex, &w, &h)) {
809
810 if (! yTextureName) glGenTextures(1, &yTextureName);
811 if (! uTextureName) glGenTextures(1, &uTextureName);
812 if (! vTextureName) glGenTextures(1, &vTextureName);
813 glBindTexture(GL_TEXTURE_2D, yTextureName);
814 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0,
815 GL_ALPHA, GL_UNSIGNED_BYTE, ytex);
816 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
817 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
818 glBindTexture(GL_TEXTURE_2D, uTextureName);
819 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w >> 1, h >> 1, 0,
820 GL_ALPHA, GL_UNSIGNED_BYTE, utex);
821 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
822 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
823 glBindTexture(GL_TEXTURE_2D, vTextureName);
824 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w >> 1, h >> 1, 0,
825 GL_ALPHA, GL_UNSIGNED_BYTE, vtex);
826 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
827 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
828
829 glBindTexture(GL_TEXTURE_2D, yTextureName);
830 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h,
831 GL_ALPHA, GL_UNSIGNED_BYTE, ytex);
832 glBindTexture(GL_TEXTURE_2D, uTextureName);
833 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w >> 1, h >> 1,
834 GL_ALPHA, GL_UNSIGNED_BYTE, utex);
835 glBindTexture(GL_TEXTURE_2D, vTextureName);
836 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w >> 1, h >> 1,
837 GL_ALPHA, GL_UNSIGNED_BYTE, vtex);
838
839 delete [] ytex;
840 delete [] utex;
841 delete [] vtex;
842 ytex = utex = vtex = NULL;
843 videoUpdated = true;
844
845 }
846 }
847 } else if (movieIsEnding) {
848 // We have reached the end of the movie.
849 movieIsPlaying = nothing;
850 }
851 }
852
853 // Update the screen if there's new video, or if we're paused
854 if (videoUpdated || movieIsPlaying == paused) {
855 // Clear The Screen
856 glClear(GL_COLOR_BUFFER_BIT);
857
858 // Display the current frame here
859 if (shader.yuv) {
860 glUseProgram(shader.yuv);
861 glActiveTexture(GL_TEXTURE1);
862 glBindTexture(GL_TEXTURE_2D, uTextureName);
863 glActiveTexture(GL_TEXTURE2);
864 glBindTexture(GL_TEXTURE_2D, vTextureName);
865 glActiveTexture(GL_TEXTURE0);
866 }
867 glBindTexture(GL_TEXTURE_2D, yTextureName);
868 glEnable(GL_BLEND);
869 //glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
870
871 setPMVMatrix(shader.yuv);
872 drawQuad(shader.yuv, vertices, 1, texCoords);
873
874 glUseProgram(0);
875
876 if (movieIsPlaying == paused) {
877 pausefade -= 1.0 / 24;
878 if (pausefade < -1.0) pausefade = 1.0;
879
880 // Paused.
881 glEnable(GL_BLEND);
882
883 glUseProgram(shader.color);
884
885 setPMVMatrix(shader.color);
886 setPrimaryColor(0.0f, 0.0f, 0.0f, fabs(pausefade));
887 drawQuad(shader.color, vertices1, 0);
888 drawQuad(shader.color, vertices2, 0);
889 setPrimaryColor(1.0f, 1.0f, 1.0f, fabs(pausefade));
890 drawQuad(shader.color, vertices3, 0);
891 drawQuad(shader.color, vertices4, 0);
892
893 glUseProgram(0);
894
895 glDisable(GL_BLEND);
896
897 Wait_Frame();
898 }
899
900 glFlush();
901
902 EGL_SwapBuffers();
903
904 }
905 videoUpdated = false;
906 }
907
908 // Cleanup
909 glBindFramebuffer(GL_FRAMEBUFFER, old_fbo);
910
911 movieIsPlaying = nothing;
912 for (int i = 0; i < 10; i++)
913 Wait_Frame();
914 huntKillFreeSound(fileNumber);
915
916 if (vpx_codec_destroy(&codec))
917 die_codec(&codec, "Failed to destroy codec");
918
919 vorbis_dsp_clear(&vorbisDspState);
920 vorbis_block_clear(&vorbisBlock);
921 vorbis_comment_clear(&vorbisComment);
922 vorbis_info_clear(&vorbisInfo);
923 delete pSegment;
924 deleteTextures(1, &yTextureName);
925 deleteTextures(1, &uTextureName);
926 deleteTextures(1, &vTextureName);
927 yTextureName = uTextureName = vTextureName = 0;
928
929 // Delete any remaining buffers
930 videoBuffers *vB = videoQ.first;
931 while (vB = videoQ.first) {
932 videoQ.first = vB->next;
933 delete [] vB->ytex;
934 delete [] vB->utex;
935 delete [] vB->vtex;
936 delete vB;
937 }
938 videoQ.size = 0;
939
940 audioBuffers *aB = audioQ.first;
941 while (aB = audioQ.first) {
942 audioQ.first = aB->next;
943 delete [] aB->buffer;
944 delete aB;
945 }
946 audioQ.size = 0;
947
948 Init_Timer();
949
950 glViewport(viewportOffsetX, viewportOffsetY, viewportWidth, viewportHeight);
951
952 setPixelCoords(false);
953 #endif
954 return 0;
955 }
956
stopMovie()957 int stopMovie() {
958 int r = movieIsPlaying;
959 movieIsPlaying = nothing;
960 return r;
961 }
962
pauseMovie()963 int pauseMovie() {
964 #if 0
965 if (movieIsPlaying == playing) {
966 ALuint source = getSoundSource(movieAudioIndex);
967 if (source) {
968
969 alurePauseSource(source);
970
971 }
972 movieIsPlaying = paused;
973 fprintf(stderr, "** Pausing **\n");
974 } else if (movieIsPlaying == paused) {
975 ALuint source = getSoundSource(movieAudioIndex);
976 if (source) {
977
978 alureResumeSource(source);
979
980 }
981 fprintf(stderr, "** Restarted movie ** sound: %d source: %d\n", movieSoundPlaying, source);
982 movieIsPlaying = playing;
983 }
984 #endif
985 return movieIsPlaying;
986 }
987
988 } // End of namespace Sludge
989