CVideoHandler.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815
  1. #include "../stdafx.h"
  2. #include <iostream>
  3. #include "CSndHandler.h"
  4. #include "CVideoHandler.h"
  5. #include <SDL.h>
  6. #include "../client/SDL_Extensions.h"
  7. //reads events and returns true on key down
  8. static bool keyDown()
  9. {
  10. SDL_Event ev;
  11. while(SDL_PollEvent(&ev))
  12. {
  13. if(ev.type == SDL_KEYDOWN || ev.type == SDL_MOUSEBUTTONDOWN)
  14. return true;
  15. }
  16. return false;
  17. }
  18. #ifdef _WIN32
  19. #include <boost/algorithm/string/predicate.hpp>
  20. void checkForError(bool throwing = true)
  21. {
  22. #ifdef _WIN32
  23. int error = GetLastError();
  24. if(!error)
  25. return;
  26. tlog1 << "Error " << error << " encountered!\n";
  27. std::string msg;
  28. char* pTemp = NULL;
  29. FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
  30. NULL, error, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), (LPSTR)&pTemp, 1, NULL );
  31. tlog1 << "Error: " << pTemp << std::endl;
  32. msg = pTemp;
  33. LocalFree( pTemp );
  34. pTemp = NULL;
  35. if(throwing)
  36. throw msg;
  37. #endif
  38. }
  39. void blitBuffer(char *buffer, int x, int y, int w, int h, SDL_Surface *dst)
  40. {
  41. const int bpp = dst->format->BytesPerPixel;
  42. char *dest;
  43. for(int i = h; i > 0; i--)
  44. {
  45. dest = (char*)dst->pixels + dst->pitch*(y+h-i) + x*dst->format->BytesPerPixel;
  46. memcpy(dest, buffer, bpp*w);
  47. buffer += bpp*w;
  48. }
  49. }
  50. void DLLHandler::Instantiate(const char *filename)
  51. {
  52. name = filename;
  53. #ifdef _WIN32
  54. dll = LoadLibraryA(filename);
  55. if(!dll)
  56. {
  57. tlog1 << "Failed loading " << filename << std::endl;
  58. checkForError();
  59. }
  60. #else
  61. dll = dlopen(filename,RTLD_LOCAL | RTLD_LAZY);
  62. #endif
  63. }
  64. void *DLLHandler::FindAddress(const char *symbol)
  65. {
  66. void *ret;
  67. #ifdef _WIN32
  68. ret = (void*) GetProcAddress(dll,symbol);
  69. if(!ret)
  70. {
  71. tlog1 << "Failed to find " << symbol << " in " << name << std::endl;
  72. checkForError();
  73. }
  74. #else
  75. ret = (void *)dlsym(dll, symbol);
  76. #endif
  77. return ret;
  78. }
  79. DLLHandler::~DLLHandler()
  80. {
  81. if(dll)
  82. {
  83. #ifdef _WIN32
  84. if(!FreeLibrary(dll))
  85. {
  86. tlog1 << "Failed to free " << name << std::endl;
  87. checkForError();
  88. }
  89. #else
  90. dlclose(dll);
  91. #endif
  92. }
  93. }
  94. DLLHandler::DLLHandler()
  95. {
  96. dll = NULL;
  97. }
  98. CBIKHandler::CBIKHandler()
  99. {
  100. Instantiate("BINKW32.DLL");
  101. //binkGetError = FindAddress("_BinkGetError@0");
  102. binkOpen = (BinkOpen)FindAddress("_BinkOpen@8");
  103. binkSetSoundSystem = (BinkSetSoundSystem)FindAddress("_BinkSetSoundSystem@8");
  104. //getPalette = (BinkGetPalette)FindAddress("_BinkGetPalette@4");
  105. binkNextFrame = (BinkNextFrame)FindAddress("_BinkNextFrame@4");
  106. binkDoFrame = (BinkDoFrame)FindAddress("_BinkDoFrame@4");
  107. binkCopyToBuffer = (BinkCopyToBuffer)FindAddress("_BinkCopyToBuffer@28");
  108. binkWait = (BinkWait)FindAddress("_BinkWait@4");
  109. binkClose = (BinkClose)FindAddress("_BinkClose@4");
  110. hBinkFile = NULL;
  111. hBink = NULL;
  112. }
  113. void CBIKHandler::open(std::string name)
  114. {
  115. hBinkFile = CreateFileA
  116. (
  117. name.c_str(), // file name
  118. GENERIC_READ, // access mode
  119. FILE_SHARE_READ, // share mode
  120. NULL, // Security Descriptor
  121. OPEN_EXISTING, // how to create
  122. FILE_ATTRIBUTE_NORMAL,//FILE_FLAG_SEQUENTIAL_SCAN, // file attributes
  123. 0 // handle to template file
  124. );
  125. if(hBinkFile == INVALID_HANDLE_VALUE)
  126. {
  127. tlog1 << "BIK handler: failed to open " << name << std::endl;
  128. checkForError();
  129. return;
  130. }
  131. void *waveout = GetProcAddress(dll,"_BinkOpenWaveOut@4");
  132. if(waveout)
  133. binkSetSoundSystem(waveout,NULL);
  134. hBink = binkOpen(hBinkFile, 0x8a800000);
  135. buffer = new char[hBink->width * hBink->width * 3];
  136. }
  137. void CBIKHandler::show( int x, int y, SDL_Surface *dst, bool update )
  138. {
  139. int w = hBink->width, h = hBink->height;
  140. binkDoFrame(hBink);
  141. binkCopyToBuffer(hBink, buffer, w*3, h, 0, 0, 0);
  142. blitBuffer(buffer, x, y, w, h, dst);
  143. if(update)
  144. SDL_UpdateRect(dst, x, y, w, h);
  145. }
  146. void CBIKHandler::nextFrame()
  147. {
  148. binkNextFrame(hBink);
  149. }
  150. void CBIKHandler::close()
  151. {
  152. binkClose(hBink);
  153. hBink = NULL;
  154. CloseHandle(hBinkFile);
  155. hBinkFile = NULL;
  156. delete [] buffer;
  157. }
  158. bool CBIKHandler::wait()
  159. {
  160. return binkWait(hBink);
  161. }
  162. int CBIKHandler::curFrame() const
  163. {
  164. return hBink->currentFrame;
  165. }
  166. int CBIKHandler::frameCount() const
  167. {
  168. return hBink->frameCount;
  169. }
  170. void CBIKHandler::redraw( int x, int y, SDL_Surface *dst, bool update )
  171. {
  172. int w = hBink->width, h = hBink->height;
  173. blitBuffer(buffer, x, y, w, h, dst);
  174. if(update)
  175. SDL_UpdateRect(dst, x, y, w, h);
  176. }
  177. void CSmackPlayer::nextFrame()
  178. {
  179. ptrSmackNextFrame(data);
  180. }
  181. bool CSmackPlayer::wait()
  182. {
  183. return ptrSmackWait(data);
  184. }
  185. CSmackPlayer::CSmackPlayer()
  186. {
  187. Instantiate("smackw32.dll");
  188. ptrSmackNextFrame = (SmackNextFrame)FindAddress("_SmackNextFrame@4");
  189. ptrSmackWait = (SmackWait)FindAddress("_SmackWait@4");
  190. ptrSmackDoFrame = (SmackDoFrame)FindAddress("_SmackDoFrame@4");
  191. ptrSmackToBuffer = (SmackToBuffer)FindAddress("_SmackToBuffer@28");
  192. ptrSmackOpen = (SmackOpen)FindAddress("_SmackOpen@12");
  193. ptrSmackSoundOnOff = (SmackSoundOnOff)FindAddress("_SmackSoundOnOff@8");
  194. ptrSmackClose = (SmackClose)FindAddress("_SmackClose@4");
  195. }
  196. CSmackPlayer::~CSmackPlayer()
  197. {
  198. if(data)
  199. close();
  200. }
  201. void CSmackPlayer::close()
  202. {
  203. ptrSmackClose(data);
  204. data = NULL;
  205. delete [] buffer;
  206. buffer = NULL;
  207. }
  208. void CSmackPlayer::open( std::string name )
  209. {
  210. Uint32 flags[2] = {0xff400, 0xfe400};
  211. data = ptrSmackOpen( (void*)name.c_str(), flags[1], -1);
  212. if (!data)
  213. {
  214. tlog1 << "Smack cannot open " << name << std::endl;
  215. return;
  216. }
  217. buffer = new char[data->width*data->height*2];
  218. buf = buffer+data->width*(data->height-1)*2; // adjust pointer position for later use by 'SmackToBuffer'
  219. }
  220. void CSmackPlayer::show( int x, int y, SDL_Surface *dst, bool update)
  221. {
  222. int w = data->width, h = data->height;
  223. int stripe = (-w*2) & (~3);
  224. //put frame to the buffer
  225. ptrSmackToBuffer(data, 0, 0, stripe, w, buf, 0x80000000);
  226. ptrSmackDoFrame(data);
  227. redraw(x, y, dst, update);
  228. }
  229. int CSmackPlayer::curFrame() const
  230. {
  231. return data->currentFrame;
  232. }
  233. int CSmackPlayer::frameCount() const
  234. {
  235. return data->frameCount;
  236. }
  237. void CSmackPlayer::redraw( int x, int y, SDL_Surface *dst, bool update )
  238. {
  239. int w = data->width, h = data->height;
  240. /* Lock the screen for direct access to the pixels */
  241. if ( SDL_MUSTLOCK(dst) )
  242. {
  243. if ( SDL_LockSurface(dst) < 0 )
  244. {
  245. fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError());
  246. return;
  247. }
  248. }
  249. // draw the frame
  250. Uint16* addr = (Uint16*) (buffer+w*(h-1)*2-2);
  251. for( int j=0; j<h-1; j++) // why -1 ?
  252. {
  253. for ( int i=w-1; i>=0; i--)
  254. {
  255. Uint16 pixel = *addr;
  256. Uint8 *p = (Uint8 *)dst->pixels + (j+y) * dst->pitch + (i + x) * dst->format->BytesPerPixel;
  257. p[2] = ((pixel & 0x7c00) >> 10) * 8;
  258. p[1] = ((pixel & 0x3e0) >> 5) * 8;
  259. p[0] = ((pixel & 0x1F)) * 8;
  260. addr--;
  261. }
  262. }
  263. if ( SDL_MUSTLOCK(dst) )
  264. {
  265. SDL_UnlockSurface(dst);
  266. }
  267. if(update)
  268. SDL_UpdateRect(dst, x, y, w, h);
  269. }
  270. CVideoPlayer::CVideoPlayer()
  271. {
  272. vidh = new CVidHandler(std::string(DATA_DIR "Data" PATHSEPARATOR "VIDEO.VID"));
  273. current = NULL;
  274. }
  275. CVideoPlayer::~CVideoPlayer()
  276. {
  277. delete vidh;
  278. }
  279. void CVideoPlayer::open(std::string name)
  280. {
  281. if(boost::algorithm::ends_with(name, ".BIK"))
  282. current = &bikPlayer;
  283. else
  284. current = &smkPlayer;
  285. fname = name;
  286. first = true;
  287. //extract video from video.vid so we can play it
  288. vidh->extract(name, name);
  289. current->open(name);
  290. }
  291. void CVideoPlayer::close()
  292. {
  293. if(!current)
  294. {
  295. tlog2 << "Closing no opened player...?" << std::endl;
  296. return;
  297. }
  298. current->close();
  299. current = NULL;
  300. if(!DeleteFileA(fname.c_str()))
  301. {
  302. tlog1 << "Cannot remove temporarily extracted video file: " << fname;
  303. checkForError(false);
  304. }
  305. fname.clear();
  306. }
  307. void CVideoPlayer::nextFrame()
  308. {
  309. current->nextFrame();
  310. }
  311. void CVideoPlayer::show(int x, int y, SDL_Surface *dst, bool update)
  312. {
  313. current->show(x, y, dst, update);
  314. }
  315. bool CVideoPlayer::wait()
  316. {
  317. return current->wait();
  318. }
  319. int CVideoPlayer::curFrame() const
  320. {
  321. return current->curFrame();
  322. }
  323. int CVideoPlayer::frameCount() const
  324. {
  325. return current->frameCount();
  326. }
  327. bool CVideoPlayer::openAndPlayVideo(std::string name, int x, int y, SDL_Surface *dst, bool stopOnKey)
  328. {
  329. open(name);
  330. bool ret = playVideo(x, y, dst, stopOnKey);
  331. close();
  332. return ret;
  333. }
  334. void CVideoPlayer::update( int x, int y, SDL_Surface *dst, bool forceRedraw, bool update )
  335. {
  336. bool w = false;
  337. if(!first)
  338. {
  339. w = wait(); //check if should keep current frame
  340. if(!w)
  341. nextFrame();
  342. }
  343. else
  344. {
  345. first = false;
  346. }
  347. if(!w)
  348. {
  349. show(x,y,dst,update);
  350. }
  351. else if (forceRedraw)
  352. {
  353. redraw(x, y, dst, update);
  354. }
  355. }
  356. void CVideoPlayer::redraw( int x, int y, SDL_Surface *dst, bool update )
  357. {
  358. current->redraw(x, y, dst, update);
  359. }
  360. bool CVideoPlayer::playVideo(int x, int y, SDL_Surface *dst, bool stopOnKey)
  361. {
  362. int frame = 0;
  363. while(frame < frameCount()) //play all frames
  364. {
  365. if(stopOnKey && keyDown())
  366. return false;
  367. if(!wait())
  368. {
  369. show(x, y, dst);
  370. nextFrame();
  371. frame++;
  372. }
  373. SDL_Delay(20);
  374. }
  375. return true;
  376. }
  377. #else
  378. #include <../client/SDL_framerate.h>
  379. extern "C" {
  380. #include <libavformat/avformat.h>
  381. #include <libswscale/swscale.h>
  382. }
  383. static const char *protocol_name = "lod";
  384. // Open a pseudo file. Name is something like 'lod:0x56432ab6c43df8fe'
  385. static int lod_open(URLContext *context, const char *filename, int flags)
  386. {
  387. CVideoPlayer *video;
  388. // Retrieve pointer to CVideoPlayer object
  389. filename += strlen(protocol_name) + 1;
  390. video = (CVideoPlayer *)(uintptr_t)strtoull(filename, NULL, 16);
  391. // TODO: check flags ?
  392. context->priv_data = video;
  393. return 0;
  394. }
  395. static int lod_close(URLContext* h)
  396. {
  397. return 0;
  398. }
  399. // Define a set of functions to read data
  400. static int lod_read(URLContext *context, unsigned char *buf, int size)
  401. {
  402. CVideoPlayer *video = (CVideoPlayer *)context->priv_data;
  403. amin(size, video->length - video->offset);
  404. if (size < 0)
  405. return -1;
  406. // TODO: can we avoid that copy ?
  407. memcpy(buf, video->data + video->offset, size);
  408. video->offset += size;
  409. return size;
  410. }
  411. static int64_t lod_seek(URLContext *context, int64_t pos, int whence)
  412. {
  413. CVideoPlayer *video = (CVideoPlayer *)context->priv_data;
  414. // Not sure what the parameter whence is. Assuming it always
  415. // indicates an absolute value;
  416. video->offset = pos;
  417. amin(video->offset, video->length);
  418. return -1;//video->offset;
  419. }
  420. static URLProtocol lod_protocol = {
  421. protocol_name,
  422. lod_open,
  423. lod_read,
  424. NULL, // no write
  425. lod_seek,
  426. lod_close
  427. };
  428. CVideoPlayer::CVideoPlayer()
  429. {
  430. format = NULL;
  431. frame = NULL;
  432. codec = NULL;
  433. sws = NULL;
  434. overlay = NULL;
  435. dest = NULL;
  436. // Register codecs. TODO: May be overkill. Should call a
  437. // combination of av_register_input_format() /
  438. // av_register_output_format() / av_register_protocol() instead.
  439. av_register_all();
  440. // Register our protocol 'lod' so we can directly read from mmaped memory
  441. av_register_protocol(&lod_protocol);
  442. vidh = new CVidHandler(std::string(DATA_DIR "Data" PATHSEPARATOR "VIDEO.VID"));
  443. }
  444. // loop = to loop through the video
  445. // useOverlay = directly write to the screen.
  446. bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay)
  447. {
  448. close();
  449. offset = 0;
  450. refreshWait = 3;
  451. refreshCount = -1;
  452. doLoop = loop;
  453. data = vidh->extract(fname, length);
  454. if (data) {
  455. // Create our URL name with the 'lod' protocol as a prefix and a
  456. // back pointer to our object. Should be 32 and 64 bits compatible.
  457. char url[100];
  458. sprintf(url, "%s:0x%016llx", protocol_name, (unsigned long long)(uintptr_t)this);
  459. if (av_open_input_file(&format, url, NULL, 0, NULL)!=0) {
  460. return false;
  461. }
  462. } else {
  463. // File is not in a container
  464. if (av_open_input_file(&format, (DATA_DIR "Data/video/" + fname).c_str(), NULL, 0, NULL)!=0) {
  465. // tlog1 << "Video file not found: " DATA_DIR "Data/video/" + fname << std::endl;
  466. return false;
  467. }
  468. }
  469. // Retrieve stream information
  470. if (av_find_stream_info(format) < 0)
  471. return false;
  472. // Find the first video stream
  473. stream = -1;
  474. for(unsigned int i=0; i<format->nb_streams; i++) {
  475. if (format->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) {
  476. stream = i;
  477. break;
  478. }
  479. }
  480. if (stream < 0)
  481. // No video stream in that file
  482. return false;
  483. // Get a pointer to the codec context for the video stream
  484. codecContext = format->streams[stream]->codec;
  485. // Find the decoder for the video stream
  486. codec = avcodec_find_decoder(codecContext->codec_id);
  487. if (codec == NULL) {
  488. // Unsupported codec
  489. return false;
  490. }
  491. // Open codec
  492. if (avcodec_open(codecContext, codec) <0 ) {
  493. // Could not open codec
  494. codec = NULL;
  495. return false;
  496. }
  497. // Allocate video frame
  498. frame = avcodec_alloc_frame();
  499. // Allocate a place to put our YUV image on that screen
  500. if (useOverlay) {
  501. overlay = SDL_CreateYUVOverlay(codecContext->width, codecContext->height,
  502. SDL_YV12_OVERLAY, screen);
  503. } else {
  504. dest = CSDL_Ext::newSurface(codecContext->width, codecContext->height);
  505. destRect.x = destRect.y = 0;
  506. destRect.w = codecContext->width;
  507. destRect.h = codecContext->height;
  508. }
  509. if (overlay == NULL && dest == NULL)
  510. return false;
  511. // Convert the image into YUV format that SDL uses
  512. if (overlay) {
  513. sws = sws_getContext(codecContext->width, codecContext->height,
  514. codecContext->pix_fmt, codecContext->width, codecContext->height,
  515. PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
  516. } else {
  517. sws = sws_getContext(codecContext->width, codecContext->height,
  518. codecContext->pix_fmt, codecContext->width, codecContext->height,
  519. PIX_FMT_RGB32, SWS_BICUBIC, NULL, NULL, NULL);
  520. }
  521. if (sws == NULL)
  522. return false;
  523. pos.w = codecContext->width;
  524. pos.h = codecContext->height;
  525. return true;
  526. }
  527. // Read the next frame. Return false on error/end of file.
  528. bool CVideoPlayer::nextFrame()
  529. {
  530. AVPacket packet;
  531. int frameFinished = 0;
  532. bool gotError = false;
  533. if (sws == NULL)
  534. return false;
  535. while(!frameFinished) {
  536. int ret = av_read_frame(format, &packet);
  537. if (ret < 0) {
  538. // Error. It's probably an end of file.
  539. if (doLoop && !gotError) {
  540. // Rewind
  541. if (av_seek_frame(format, stream, 0, 0) < 0)
  542. break;
  543. gotError = true;
  544. } else {
  545. break;
  546. }
  547. } else {
  548. // Is this a packet from the video stream?
  549. if (packet.stream_index == stream) {
  550. // Decode video frame
  551. avcodec_decode_video(codecContext, frame, &frameFinished,
  552. packet.data, packet.size);
  553. // Did we get a video frame?
  554. if (frameFinished) {
  555. AVPicture pict;
  556. if (overlay) {
  557. SDL_LockYUVOverlay(overlay);
  558. pict.data[0] = overlay->pixels[0];
  559. pict.data[1] = overlay->pixels[2];
  560. pict.data[2] = overlay->pixels[1];
  561. pict.linesize[0] = overlay->pitches[0];
  562. pict.linesize[1] = overlay->pitches[2];
  563. pict.linesize[2] = overlay->pitches[1];
  564. sws_scale(sws, frame->data, frame->linesize,
  565. 0, codecContext->height, pict.data, pict.linesize);
  566. SDL_UnlockYUVOverlay(overlay);
  567. } else {
  568. pict.data[0] = (uint8_t *)dest->pixels;
  569. pict.linesize[0] = dest->pitch;
  570. sws_scale(sws, frame->data, frame->linesize,
  571. 0, codecContext->height, pict.data, pict.linesize);
  572. }
  573. }
  574. }
  575. av_free_packet(&packet);
  576. }
  577. }
  578. return frameFinished != 0;
  579. }
  580. void CVideoPlayer::show( int x, int y, SDL_Surface *dst, bool update )
  581. {
  582. if (sws == NULL)
  583. return;
  584. pos.x = x;
  585. pos.y = y;
  586. SDL_BlitSurface(dest, &destRect, dst, &pos);
  587. if (update)
  588. SDL_UpdateRect(dst, pos.x, pos.y, pos.w, pos.h);
  589. }
  590. void CVideoPlayer::redraw( int x, int y, SDL_Surface *dst, bool update )
  591. {
  592. show(x, y, dst, update);
  593. }
  594. void CVideoPlayer::update( int x, int y, SDL_Surface *dst, bool forceRedraw, bool update )
  595. {
  596. if (sws == NULL)
  597. return;
  598. if (refreshCount <= 0)
  599. {
  600. refreshCount = refreshWait;
  601. if (nextFrame())
  602. show(x,y,dst,update);
  603. } else {
  604. redraw(x, y, dst, update);
  605. }
  606. refreshCount --;
  607. }
  608. void CVideoPlayer::close()
  609. {
  610. if (sws) {
  611. sws_freeContext(sws);
  612. sws = NULL;
  613. }
  614. if (overlay) {
  615. SDL_FreeYUVOverlay(overlay);
  616. overlay = NULL;
  617. }
  618. if (dest) {
  619. SDL_FreeSurface(dest);
  620. dest = NULL;
  621. }
  622. if (frame) {
  623. av_free(frame);
  624. frame = NULL;
  625. }
  626. if (codec) {
  627. avcodec_close(codecContext);
  628. codec = NULL;
  629. codecContext = NULL;
  630. }
  631. if (format) {
  632. av_close_input_file(format);
  633. format = NULL;
  634. }
  635. }
  636. // Plays a video. Only works for overlays.
  637. bool CVideoPlayer::playVideo(int x, int y, SDL_Surface *dst, bool stopOnKey)
  638. {
  639. // Note: either the windows player or the linux player is
  640. // broken. Compensate here until the bug is found.
  641. y--;
  642. pos.x = x;
  643. pos.y = y;
  644. FPSmanager mainFPSmng;
  645. SDL_initFramerate(&mainFPSmng);
  646. SDL_setFramerate(&mainFPSmng, 48);
  647. while(nextFrame()) {
  648. if(stopOnKey && keyDown())
  649. return false;
  650. SDL_DisplayYUVOverlay(overlay, &pos);
  651. // Wait 3 frames
  652. SDL_framerateDelay(&mainFPSmng);
  653. SDL_framerateDelay(&mainFPSmng);
  654. SDL_framerateDelay(&mainFPSmng);
  655. }
  656. return true;
  657. }
  658. bool CVideoPlayer::openAndPlayVideo(std::string name, int x, int y, SDL_Surface *dst, bool stopOnKey)
  659. {
  660. open(name, false, true);
  661. bool ret = playVideo(x, y, dst, stopOnKey);
  662. close();
  663. return ret;
  664. }
  665. CVideoPlayer::~CVideoPlayer()
  666. {
  667. close();
  668. }
  669. #endif