svvitch
digital signage player
D:/vs_workspace/switch_sf/src/svvitch/FFMovieContent.cpp
Go to the documentation of this file.
00001 #ifdef USE_FFMPEG
00002 
00003 #include "FFMovieContent.h"
00004 #include "Utils.h"
00005 
00006 
00007 FFMovieContent::FFMovieContent(Renderer& renderer, int splitType):
00008     Content(renderer, splitType), _ic(NULL), _fps(0), _audioDecoder(NULL), _videoDecoder(NULL), _vf(NULL), _prepareVF(NULL),
00009     _starting(false), _frameOddEven(0), _finished(true), _seeking(false)
00010 {
00011     initialize();
00012 }
00013 
00014 FFMovieContent::‾FFMovieContent() {
00015     Poco::ScopedLock<Poco::FastMutex> lock(_openLock);
00016     initialize();
00017 }
00018 
00019 
00020 void FFMovieContent::initialize() {
00021     close();
00022     _fpsCounter.start();
00023     _avgTime = 0;
00024     if (_vf) {
00025         Poco::ScopedLock<Poco::FastMutex> lock(_frameLock);
00026         SAFE_DELETE(_vf);
00027     }
00028 }
00029 
00031 bool FFMovieContent::open(const MediaItemPtr media, const int offset) {
00032     Poco::ScopedLock<Poco::FastMutex> lock(_openLock);
00033     initialize();
00034 
00035     if (media->files().empty() || media->files().size() <= offset) return false;
00036     MediaItemFile mif = media->files()[offset];
00037     //for (vector<MediaItemFile>::const_iterator it = media->files().begin(); it != media->files().end(); it++) {
00038     //  switch (it->type()) {
00039     //  case MediaTypeMovie:
00040     //      mif = *it;
00041     //      break;
00042     //  }
00043     //}
00044 
00045     AVInputFormat* format = NULL;
00046     if (mif.file().find(string("vfwcap")) == 0) {
00047         _log.information(Poco::format("capture device: %s", mif.file()));
00048         format = av_find_input_format("vfwcap");
00049         if (format) _log.information(Poco::format("input format: %s", string(format->long_name)));
00050         // AVOutputFormat* outf = guess_format("vfwcap", mbfile.c_str(), NULL);
00051         // if (outf) _log.information(Poco::format("output format: [%s]", string(outf->long_name)));
00052 
00053         AVFormatParameters ap = {0};
00054         // ap.prealloced_context = 1;
00055         ap.width = 640;
00056         ap.height = 480;
00057         ap.pix_fmt = PIX_FMT_RGB24; //PIX_FMT_NONE;
00058         ap.time_base.num = 1;
00059         ap.time_base.den = 30;
00060         ap.channel = 0;
00061         //  ap.standard = NULL;
00062         //  ap.video_codec_id = CODEC_ID_NONE;
00063         //  ap.audio_codec_id = CODEC_ID_NONE;
00064 
00065         // ap->sample_rate = audio_sample_rate;
00066         // ap->channels = audio_channels;
00067         // ap->time_base.den = frame_rate.num;
00068         // ap->time_base.num = frame_rate.den;
00069         // ap->width = frame_width + frame_padleft + frame_padright;
00070         // ap->height = frame_height + frame_padtop + frame_padbottom;
00071         // ap->pix_fmt = frame_pix_fmt;
00072         // ap->sample_fmt = audio_sample_fmt; //FIXME:not implemented in libavformat
00073         // ap->channel = video_channel;
00074         // ap->standard = video_standard;
00075         // ap->video_codec_id = find_codec_or_die(video_codec_name, CODEC_TYPE_VIDEO, 0);
00076         // ap->audio_codec_id = find_codec_or_die(audio_codec_name, CODEC_TYPE_AUDIO, 0);
00077 
00078         if (av_open_input_file(&_ic, mif.file().substr(6).c_str(), format, 0, &ap) != 0) {
00079             _log.warning(Poco::format("failed open capture device: [%s]", mif.file()));
00080             return false;
00081         }
00082     } else {
00083         string file = Path(config().dataRoot, Path(mif.file())).absolute().toString();
00084         string mbfile;
00085         svvitch::utf8_sjis(file, mbfile);
00086         if (av_open_input_file(&_ic, mbfile.c_str(), format, 0,NULL) != 0) {
00087             _log.warning(Poco::format("failed open file: [%s]", file));
00088             return false;
00089         }
00090     }
00091     // _log.information(Poco::format("opened: %s", file));
00092 
00093     if (av_find_stream_info(_ic) < 0 || !_ic) {
00094         _log.warning(Poco::format("failed find stream info: %s", mif.file()));
00095         close();
00096         return false;
00097     }
00098     int64_t start = media->start() / F(1000) * AV_TIME_BASE;
00099     if (media->start() > 0 && av_seek_frame(_ic, -1, start, AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_FRAME) != 0) {
00100         _log.warning(Poco::format("failed set start time: %d", media->start()));
00101         close();
00102         return false;
00103     }
00104 
00105     //_log.information(Poco::format("find stream information: %s streams: %u", string(_ic->title), _ic->nb_streams));
00106     for (int i = 0; i < _ic->nb_streams; i++) {
00107         AVStream* stream = _ic->streams[i];
00108         AVCodecContext* avctx = stream->codec;
00109         if (!avctx) {
00110             _log.warning(Poco::format("failed stream codec[%d]: %s", i, mif.file()));
00111             continue;
00112         }
00113         if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
00114             //IDirectXVideoDecoderService* service = NULL;
00115             //DXVA2CreateVideoService(_renderer.get3DDevice(), IID_PPV_ARGS(&service));
00116             //UINT resetToken = 0;
00117             //IDirect3DDeviceManager9* d3dManager = NULL;
00118             //HRESULT hr = DXVA2CreateDirect3DDeviceManager9(&resetToken, &d3dManager);
00119             //if SUCCEEDED(hr) {
00120             //  hr = d3dManager->ResetDevice(_renderer.get3DDevice(), resetToken);
00121             //  if SUCCEEDED(hr) {
00122             //  } else {
00123             //      _log.warning("failed ResetDevice()");
00124             //  }
00125             //} else {
00126             //  _log.warning("failed DXVA2CreateDirect3DDeviceManager9()");
00127             //}
00128             //SAFE_RELEASE(d3dManager);
00129 
00130             //dxva_context* dxva = (dxva_context*)av_malloc(sizeof(dxva_context));
00131         //  AVHWAccel* hwaccel = av_hwaccel_next(NULL);
00132         //  if (hwaccel) {
00133         //      avctx->hwaccel_context = hwaccel;
00134         //      avctx->codec_id = hwaccel->id;
00135         //      _log.information(Poco::format("set hardware accelerator: %s %d", string(hwaccel->name), ((int)hwaccel->pix_fmt)));
00136         //  }
00137         }
00138 
00139         AVCodec* avcodec = avcodec_find_decoder(avctx->codec_id);
00140         if (!avcodec) {
00141             _log.warning(Poco::format("not found decoder[%d]: %s", i, mif.file()));
00142             continue;
00143         }
00144 
00145         float rate = 0;
00146         switch (avctx->codec_type) {
00147             case AVMEDIA_TYPE_VIDEO:
00148                 {
00149                     //string name(avcodec->long_name);
00150                     //if (name.find("H.264") != string::npos) {
00151                     //  AVHWAccel* hwaccel = av_hwaccel_next(NULL);
00152                     //  if (hwaccel) {
00153                     //      avctx->hwaccel_context = hwaccel;
00154                     //      _log.information(Poco::format("set hardware accelerator: %s %d", string(hwaccel->name), ((int)hwaccel->pix_fmt)));
00155                     //  }
00156                     //}
00157                 }
00158                 if (_video < 0 && avcodec_open(avctx, avcodec) < 0) {
00159                     _log.warning(Poco::format("failed open codec: %s", mif.file()));
00160                 } else {
00161                     // codecがopenできた
00162                     float rate = F(stream->r_frame_rate.num) / stream->r_frame_rate.den;
00163                     if (rate < 24.5f) {
00164                         _fps = 24;
00165                     } else if (rate < 26.0f) {
00166                         _fps = 25;
00167                     } else if (rate < 31.0f) {
00168                         _fps = 30;
00169                     } else if (rate < 51.0f) {
00170                         _fps = (int)rate;
00171                     } else {
00172                         _fps = 60;
00173                     }
00174                     if (_fps <= 30) {
00175                         _duration = L((stream->duration * F(stream->time_base.num) / stream->time_base.den) * 60);
00176                     } else {
00177                         _duration = stream->duration * stream->time_base.num * stream->r_frame_rate.num / stream->time_base.den / stream->r_frame_rate.den;
00178                     }
00179 
00180                     _log.information(Poco::format("open decoder: %s %d(%d/%d) %dkbps", string(avcodec->long_name), _fps, stream->r_frame_rate.num, stream->r_frame_rate.den, avctx->bit_rate / 1024));
00181                     _video = i;
00182                     _videoDecoder = new FFVideoDecoder(_renderer, _ic, _video);
00183                     _videoDecoder->start();
00184                     _w = avctx->width;
00185                     _h = avctx->height;
00186                 }
00187                 break;
00188 
00189             case AVMEDIA_TYPE_AUDIO:
00190                 if (_renderer.getSoundDevice() && config().splitType != 21) {
00191                     if (_audio < 0 && avcodec_open(avctx, avcodec) < 0) {
00192                         _log.warning(Poco::format("failed open codec: %s", mif.file()));
00193                     } else {
00194                         // codecがopenできた
00195                         _log.information(Poco::format("open decoder: %s %dkbps", string(avcodec->long_name), avctx->bit_rate / 1024));
00196                         _audio = i;
00197                         _audioDecoder = new FFAudioDecoder(_renderer, _ic, _audio);
00198                         _audioDecoder->start();
00199                     }
00200                 }
00201                 break;
00202         }
00203     }
00204     if (_audioDecoder && !_audioDecoder->isReady()) return false;
00205     if (_videoDecoder && !_videoDecoder->isReady()) return false;
00206 
00207     _worker = this;
00208     _thread.start(*_worker);
00209 
00210     _log.information(Poco::format("opened: %s", mif.file()));
00211     _mediaID = media->id();
00212     _current = media->start() * 60 / 1000;
00213     if (media->duration() > 0) _duration = media->duration() * 60 / 1000;
00214     set("alpha", 1.0f);
00215     _starting = false;
00216     _finished = false;
00217     return true;
00218 }
00219 
00220 void FFMovieContent::run() {
00221     _log.information("movie thread start");
00222     long count = 0;
00223     AVPacket packet;
00224     while (_worker) {
00225         Poco::Thread::sleep(0);
00226         if (!_playing) {
00227             // 停止中はウェイトを増やし負荷を下げる
00228             Poco::Thread::sleep(50);
00229         }
00230         if (_seeking) {
00231             // シーク中
00232             Poco::Thread::sleep(10);
00233             continue;
00234         }
00235         if (_audioDecoder) {
00236             // audioデコード処理
00237             _audioDecoder->decode();
00238             _audioDecoder->writeData();
00239         }
00240         if (_videoDecoder) {
00241             // videoデコード処理
00242             if (_videoDecoder->bufferedPackets() > 200) {
00243                 Poco::Thread::sleep(10);
00244                 continue;
00245             }
00246         }
00247 
00248         if (av_read_frame(_ic, &packet) < 0) {
00249             // パケット終了 or 異常
00250             if (!_finished && _audioDecoder) _audioDecoder->finishedPacket();
00251             _finished = true;
00252             Poco::Thread::sleep(10);
00253             continue;
00254         }
00255 
00256         if (packet.stream_index == _video && _videoDecoder) {
00257             // 映像
00258             _videoDecoder->pushPacket(&packet);
00259 
00260         } else if (packet.stream_index == _audio && _audioDecoder) {
00261             // 音声
00262             _audioDecoder->pushPacket(&packet);
00263 
00264         } else {
00265             av_free_packet(&packet);
00266         }
00267         count++;
00268     }
00269     _log.information(Poco::format("movie thread end %ldpackets", count));
00270 }
00271 
00275 void FFMovieContent::play() {
00276     _playing = true;
00277     _starting = true;
00278     _playTimer.start();
00279 }
00280 
00281 void FFMovieContent::pause() {
00282     if (_audioDecoder) _audioDecoder->stop();
00283 }
00284 
00288 void FFMovieContent::stop() {
00289     if (_audioDecoder) _audioDecoder->stop();
00290     _playing = false;
00291 }
00292 
00304 const bool FFMovieContent::seek(const int64_t timestamp) {
00305     Poco::ScopedLock<Poco::FastMutex> lock(_lock);
00306     _seeking = true;
00307     Poco::Thread::sleep(10);
00308     // if (!_ic || av_seek_frame(_ic, _video, timestamp, 0) < 0) {
00309     if (!_ic || av_seek_frame(_ic, -1, timestamp, 0) < 0) {
00310         _log.warning("failed seek frame");
00311         return false;
00312     }
00313     _seeking = false;
00314     return true;
00315 }
00316 
00317 const bool FFMovieContent::finished() {
00318     Poco::ScopedLock<Poco::FastMutex> lock(_lock);
00319     if (_playing) {
00320         if (_finished) {
00321             if (_videoDecoder) {
00322                 if (_videoDecoder->bufferedFrames() == 0) {
00323                     if (_audioDecoder && _audioDecoder->playing()) _audioDecoder->stop();
00324                     return true;
00325                 }
00326                 return false;
00327             }
00328             return _mediaID.empty();
00329         }
00330     } else {
00331         return true;
00332     }
00333     return false;
00334 }
00335 
00337 void FFMovieContent::close() {
00338     _mediaID.clear();
00339     if (_ic) {
00340         stop();
00341         {
00342             Poco::ScopedLock<Poco::FastMutex> lock(_frameLock);
00343             SAFE_DELETE(_vf);
00344         }
00345         if (_worker) {
00346             _worker = NULL;
00347             _thread.join();
00348         }
00349         {
00350             Poco::ScopedLock<Poco::FastMutex> lock(_lock);
00351             SAFE_DELETE(_audioDecoder);
00352             SAFE_DELETE(_videoDecoder);
00353             // SAFE_DELETE(_vf); // 本来はここが良さそうだがフレーム描画だと落ちるので_videoDecoderが無くなったらdraw()の方でdelete
00354         }
00355         for (int i = 0; i < _ic->nb_streams; i++) {
00356             AVCodecContext* avctx = _ic->streams[i]->codec;
00357             if (avctx) {
00358                 if (avctx->codec) {
00359                     avcodec_flush_buffers(avctx);
00360                     // avcodec_default_free_buffers(avctx);
00361                     _log.information(Poco::format("release codec: %s", string(avctx->codec->long_name)));
00362                     avcodec_close(avctx);
00363                 }
00364             }
00365         }
00366         av_close_input_file(_ic);
00367         _ic = NULL;
00368     }
00369     _current = 0;
00370     _duration = 0;
00371     _video = -1;
00372     _audio = -1;
00373     _finished = true;
00374 }
00375 
00376 void FFMovieContent::process(const DWORD& frame) {
00377     if (!_mediaID.empty() && _videoDecoder) {
00378 
00379         Poco::ScopedLock<Poco::FastMutex> lock(_lock);
00380         int vbufs = 0;
00381         int abufs = 0;
00382         if (_playing) {
00383             if (_starting) {
00384                 _frameOddEven = frame % 2;
00385                 if (_audioDecoder) _audioDecoder->play();
00386                 _starting = false;
00387             }
00388 
00389             bool popFrame = false;
00390             switch (config().splitType) {
00391             case 21:
00392                 break;
00393             default:
00394                 switch (_fps) {
00395                 case 24:
00396                     {
00397                         // 2-3pulldown
00398                         int p = (frame % 5);
00399                         popFrame = p < 4 && _frameOddEven == (p % 2);
00400                     }
00401                     break;
00402                 case 25:
00403                     {
00404                         int p = (frame % 12);
00405                         popFrame = p == 0 || p == 2 || p == 5 || p == 7 || p == 9;
00406                     }
00407                     break;
00408                 case 30:
00409                     popFrame = _frameOddEven == (frame % 2);
00410                     break;
00411                 case 60:
00412                     popFrame = true;
00413                     break;
00414                 default:
00415                     popFrame = (frame % (60 / (60 - _fps))) != 0;
00416                     break;
00417                 }
00418                 if (popFrame) {
00419                     VideoFrame* vf = _videoDecoder->popFrame();
00420                     if (vf) {
00421                         if (_vf) _videoDecoder->pushUsedFrame(_vf);
00422                         _vf = vf;
00423                         _fpsCounter.count();
00424                     }
00425                 }
00426                 _current++;
00427             }
00428             if (_videoDecoder) vbufs = _videoDecoder->bufferedFrames();
00429             if (_audioDecoder) abufs = _audioDecoder->bufferedFrames();
00430             _avgTime = _videoDecoder->getAvgTime();
00431 
00432         } else {
00433             _fpsCounter.start();
00434             if (get("prepare") == "true") {
00435                 VideoFrame* vf = _videoDecoder->viewFrame();
00436                 if (vf) _prepareVF = vf;
00437             }
00438         }
00439         unsigned long cu = _current / 60;
00440         int remain = _duration - _current;
00441         if (remain < 0) remain = 0;
00442         unsigned long re = remain / 60;
00443         string t1 = Poco::format("%02lu:%02lu:%02lu.%02d", cu / 3600, cu / 60, cu % 60, (_current / 2) % 30);
00444         string t2 = Poco::format("%02lu:%02lu:%02lu.%02d", re / 3600, re / 60, re % 60, (remain / 2) % 30);
00445         set("time", Poco::format("%s %s", t1, t2));
00446         set("time_current", t1);
00447         set("time_remain", t2);
00448         //set("time_fps", Poco::format("%d(%0.2hf)", fps, _rate));
00449 
00450         set("status", Poco::format("%dp(%02lufps-%03.2hfms) %02d:%02d", _fps, _fpsCounter.getFPS(), _avgTime, vbufs, abufs));
00451     }
00452 }
00453 
00454 void FFMovieContent::draw(const DWORD& frame) {
00455     if (!_mediaID.empty()) {
00456         Poco::ScopedLock<Poco::FastMutex> lock(_frameLock);
00457         if (_vf && _playing) {
00458             LPDIRECT3DDEVICE9 device = _renderer.get3DDevice();
00459             const float alpha = getF("alpha");
00460             const int cw = config().splitSize.cx;
00461             const int ch = config().splitSize.cy;
00462             DWORD col = ((DWORD)(0xff * alpha) << 24) | 0xffffff;
00463             switch (_splitType) {
00464             case 1:
00465                 {
00466                     int sx = 0, sy = 0, dx = 0, dy = 0;
00467                     int cww = 0;
00468                     int chh = ch;
00469                     while (dx < config().mainRect.right) {
00470                         int ix = dx * config().splitCycles + dy / ch * cw;
00471                         if (ix >= config().stageRect.right) break;
00472                         if ((sx + cw) >= _vf->width()) {
00473                             // はみ出る
00474                             cww = _vf->width() - sx;
00475                             if (ix + cww > config().stageRect.right) {
00476                                 cww = config().stageRect.right - ix;
00477                             }
00478                             _vf->draw(dx, dy, cww, chh, 0, col, sx, sy, cww, chh);
00479                             sx = 0;
00480                             sy += ch;
00481                             if (ix + cww >= config().stageRect.right) break;
00482                             if (sy >= _vf->height()) {
00483                                 sy = 0;
00484                                 chh = ch;
00485                                 _vf->draw(dx + cww, dy, cw - cww, chh, 0, col, sx, sy, cw - cww, chh);
00486                                 sx += (cw - cww);
00487                             } else {
00488                                 if (_vf->height() - sy < ch) chh = _vf->height() - sy;
00489                                 // クイの分
00490                                 _vf->draw(dx + cww, dy, cw - cww, chh, 0, col, sx, sy, cw - cww, chh);
00491                                 sx += (cw - cww);
00492                             }
00493                         } else {
00494                             cww = config().stageRect.right - ix;
00495                             if (cw > cww) {
00496                                 _vf->draw(dx, dy, cww, chh, 0, col, sx, sy, cww, chh);
00497                                 break;
00498                             } else {
00499                                 _vf->draw(dx, dy, cw, chh, 0, col, sx, sy, cw, chh);
00500                                 sx += cw;
00501                             }
00502                         }
00503                         // _log.information(Poco::format("split dst: %04d,%03d src: %04d,%03d", dx, dy, sx, sy));
00504                         dy += ch;
00505                         if (dy >= config().stageRect.bottom * config().splitCycles) {
00506                             dx += cw;
00507                             dy = 0;
00508                         }
00509                     }
00510                 }
00511                 break;
00512 
00513             case 2:
00514                 {
00515 //                  device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
00516 //                  RECT scissorRect;
00517 //                  device->GetScissorRect(&scissorRect);
00518 //                  device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
00519 //                  device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
00520 //                  device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
00521 //                  device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
00522                     int sw = L(_w / cw);
00523                     if (sw <= 0) sw = 1;
00524                     int sh = L(_h / ch);
00525                     if (sh <= 0) sh = 1;
00526                     for (int sy = 0; sy < sh; sy++) {
00527                         int ox = (sy % 2) * cw * 8 + config().stageRect.left;
00528                         int oy = (sy / 2) * ch * config().splitCycles + config().stageRect.top;
00529                         // int ox = (sy % 2) * cw * 8;
00530                         // int oy = (sy / 2) * ch * 4;
00531                         for (int sx = 0; sx < sw; sx++) {
00532                             int dx = (sx / config().splitCycles) * cw;
00533                             int dy = ch * (config().splitCycles - 1) - (sx % config().splitCycles) * ch;
00534                             _vf->draw(ox + dx, oy + dy, cw, ch, 0, col, sx * cw, sy * ch, cw, ch);
00535 //                          _renderer.drawTexture(ox + dx, oy + dy, cw, ch, sx * cw, sy * ch, cw, ch, _target, col, col, col, col);
00536                         }
00537                     }
00538 //                  device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
00539 //                  device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
00540 //                  device->SetScissorRect(&scissorRect);
00541                 }
00542                 break;
00543 
00544             case 11:
00545                 {
00546                     if (_vf->height() == 120) {
00547                         _vf->draw(0, 360, 320, 120, 0, col, 2880, 0, 320, 120);
00548                         _vf->draw(0, 240, 960, 120, 0, col, 1920, 0, 960, 120);
00549                         _vf->draw(0, 120, 960, 120, 0, col,  960, 0, 960, 120);
00550                         _vf->draw(0,   0, 960, 120, 0, col,    0, 0, 960, 120);
00551                     } else {
00552                         int w = config().mainRect.right;
00553                         int h = config().mainRect.bottom;
00554                         if (_vf->width() > w || _vf->height() > h) {
00555                             device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
00556                             device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
00557                             _vf->draw( 0, 0, w, h, 1, col);
00558                             device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
00559                             device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
00560                         } else {
00561 //                          _vf->draw(0, 0);
00562                             _vf->draw(0, 0, -1, -1, 0, col);
00563                         }
00564                     }
00565                 }
00566                 break;
00567 
00568             default:
00569                 {
00570                     RECT rect = config().stageRect;
00571                     string aspectMode = get("aspect-mode");
00572                     if (aspectMode == "fit") {
00573                         device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
00574                         device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
00575                         _vf->draw(L(_x), L(_y), L(_w), L(_h), 0, col);
00576                         device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
00577                         device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
00578 
00579                     } else {
00580                         device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
00581                         device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
00582                         if (alpha > 0.0f) {
00583                             DWORD base = ((DWORD)(0xff * alpha) << 24) | 0x000000;
00584                             _renderer.drawTexture(_x, _y, _w, _h, NULL, 0, base, base, base, base);
00585                             float dar = _videoDecoder->getDisplayAspectRatio();
00586                             if (_h * dar > _w) {
00587                                 // 画角よりディスプレイサイズは横長
00588                                 long h = _w / dar;
00589                                 long dy = (_h - h) / 2;
00590                                 _vf->draw(L(_x), L(_y + dy), L(_w), h, 0, col);
00591                             } else {
00592                                 long w = _h * dar;
00593                                 long dx = (_w - w) / 2;
00594                                 _vf->draw(L(_x + dx), L(_y), w, L(_h), 0, col);
00595                             }
00596                         }
00597 
00598                         device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
00599                         device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
00600                     }
00601                 }
00602                 break;
00603             }
00604 
00605         } else if (_playing && config().splitType == 21) {
00606             LPDIRECT3DDEVICE9 device = _renderer.get3DDevice();
00607             float alpha = getF("alpha");
00608             int cw = config().splitSize.cx;
00609             int ch = config().splitSize.cy;
00610             DWORD col = ((DWORD)(0xff * alpha) << 24) | 0xffffff;
00611 
00612             int remain = _duration - _current;
00613             if (_videoDecoder->bufferedFrames() >= ((remain > 8)?8:remain)) {
00614                 for (int y = 0; y < 2; y++) {
00615                     for (int x = 0; x < 4 && _current <= _duration; x++) {
00616                         VideoFrame* vf = _videoDecoder->popFrame();
00617                         if (vf) {
00618                             int w = vf->width();
00619                             int h = vf->height();
00620                             vf->draw(L(x * w), L(y * h), L(w), L(h), 0, 0xffffffff);
00621                             _videoDecoder->pushUsedFrame(vf);
00622                             _fpsCounter.count();
00623                             _current++;
00624                         }
00625                     }
00626                 }
00627                 _fpsCounter.count();
00628             }
00629 
00630         } else if (get("prepare") == "true" && _prepareVF) {
00631             int sy = L(getF("itemNo") * 20);
00632             _prepareVF->draw(700, 600 + sy, 324, 20, 1, 0x99ffffff);
00633         }
00634     }
00635 }
00636 
00640 const Uint32 FFMovieContent::getFPS() {
00641     return _fpsCounter.getFPS();
00642 }
00643 
00647 const float FFMovieContent::getAvgTime() const {
00648     return _avgTime;
00649 }
00650 
00654 const DWORD FFMovieContent::currentTime() {
00655     return _playTimer.getTime();
00656 }
00657 
00661 const DWORD FFMovieContent::timeLeft() {
00662     long left = (_duration * 1000 / 30) - currentTime();
00663     if (left < 0) left = 0;
00664     return left;
00665 }
00666 
00667 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines