CVideoHandler.cpp 18 KB

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