diff options
author | Benoit Bolsee <benoit.bolsee@online.be> | 2008-11-10 00:42:30 +0300 |
---|---|---|
committer | Benoit Bolsee <benoit.bolsee@online.be> | 2008-11-10 00:42:30 +0300 |
commit | 2de476c88f4268f2dcfccfe6c9ce55a8697ac83e (patch) | |
tree | 86e8f63f7a20ff4d4fde6a2f898130f2cf1b927f /source/gameengine/VideoTexture/VideoFFmpeg.cpp | |
parent | 0a8e8c8c9ea6e5acf65c2a4ee0c392328f5f96b8 (diff) |
VideoTexture: Preserve alpha channel if present in video, images and sequences. Better detection of end of video.
Diffstat (limited to 'source/gameengine/VideoTexture/VideoFFmpeg.cpp')
-rw-r--r-- | source/gameengine/VideoTexture/VideoFFmpeg.cpp | 86 |
1 files changed, 60 insertions, 26 deletions
diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp index af6dfec8e87..02798c7e596 100644 --- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp +++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp @@ -54,7 +54,7 @@ VideoFFmpeg::VideoFFmpeg (HRESULT * hRslt) : VideoBase(), m_codec(NULL), m_formatCtx(NULL), m_codecCtx(NULL), m_frame(NULL), m_frameDeinterlaced(NULL), m_frameRGB(NULL), m_imgConvertCtx(NULL), m_deinterlace(false), m_preseek(0), m_videoStream(-1), m_baseFrameRate(25.0), -m_lastFrame(-1), m_curPosition(-1), m_startTime(0), +m_lastFrame(-1), m_eof(false), m_curPosition(-1), m_startTime(0), m_captWidth(0), m_captHeight(0), m_captRate(0.f), m_isImage(false) { // set video format @@ -191,7 +191,6 @@ int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AV m_frameDeinterlaced = avcodec_alloc_frame(); m_frameRGB = avcodec_alloc_frame(); - // allocate buffer if deinterlacing is required avpicture_fill((AVPicture*)m_frameDeinterlaced, (uint8_t*)MEM_callocN(avpicture_get_size( @@ -200,24 +199,51 @@ int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AV "ffmpeg deinterlace"), m_codecCtx->pix_fmt, m_codecCtx->width, m_codecCtx->height); - // allocate buffer to store final decoded frame - avpicture_fill((AVPicture*)m_frameRGB, - (uint8_t*)MEM_callocN(avpicture_get_size( - PIX_FMT_RGB24, - m_codecCtx->width, m_codecCtx->height), - "ffmpeg rgb"), - PIX_FMT_RGB24, m_codecCtx->width, m_codecCtx->height); - // allocate sws context - m_imgConvertCtx = sws_getContext( - m_codecCtx->width, - m_codecCtx->height, - m_codecCtx->pix_fmt, - m_codecCtx->width, - m_codecCtx->height, - PIX_FMT_RGB24, - SWS_FAST_BILINEAR, - NULL, NULL, NULL); - + // check if the pixel format supports Alpha + if (m_codecCtx->pix_fmt == PIX_FMT_RGB32 || + m_codecCtx->pix_fmt == PIX_FMT_BGR32 || + m_codecCtx->pix_fmt == PIX_FMT_RGB32_1 || + m_codecCtx->pix_fmt == PIX_FMT_BGR32_1) + { + // allocate buffer to store final decoded frame + m_format = RGBA32; + avpicture_fill((AVPicture*)m_frameRGB, + (uint8_t*)MEM_callocN(avpicture_get_size( + PIX_FMT_RGBA, + m_codecCtx->width, m_codecCtx->height), + "ffmpeg rgba"), + PIX_FMT_RGBA, m_codecCtx->width, m_codecCtx->height); + // allocate sws context + m_imgConvertCtx = sws_getContext( + m_codecCtx->width, + m_codecCtx->height, + m_codecCtx->pix_fmt, + m_codecCtx->width, + m_codecCtx->height, + PIX_FMT_RGBA, + SWS_FAST_BILINEAR, + NULL, NULL, NULL); + } else + { + // allocate buffer to store final decoded frame + m_format = RGB24; + avpicture_fill((AVPicture*)m_frameRGB, + (uint8_t*)MEM_callocN(avpicture_get_size( + PIX_FMT_RGB24, + m_codecCtx->width, m_codecCtx->height), + "ffmpeg rgb"), + PIX_FMT_RGB24, m_codecCtx->width, m_codecCtx->height); + // allocate sws context + m_imgConvertCtx = sws_getContext( + m_codecCtx->width, + m_codecCtx->height, + m_codecCtx->pix_fmt, + m_codecCtx->width, + m_codecCtx->height, + PIX_FMT_RGB24, + SWS_FAST_BILINEAR, + NULL, NULL, NULL); + } if (!m_imgConvertCtx) { avcodec_close(m_codecCtx); av_close_input_file(m_formatCtx); @@ -481,7 +507,7 @@ void VideoFFmpeg::setPositions (void) // set video start time m_startTime = PIL_check_seconds_timer(); // if file is played and actual position is before end position - if (m_isFile && m_lastFrame >= 0 && m_lastFrame < m_range[1] * actFrameRate()) + if (m_isFile && !m_eof && m_lastFrame >= 0 && m_lastFrame < m_range[1] * actFrameRate()) // continue from actual position m_startTime -= double(m_lastFrame) / actFrameRate(); else @@ -520,7 +546,8 @@ bool VideoFFmpeg::grabFrame(long position) } } // if the position is not in preseek, do a direct jump - if (position != m_curPosition + 1) { + if (position != m_curPosition + 1) + { double timeBase = av_q2d(m_formatCtx->streams[m_videoStream]->time_base); long long pos = (long long) ((long long) (position - m_preseek) * AV_TIME_BASE / m_baseFrameRate); @@ -532,10 +559,16 @@ bool VideoFFmpeg::grabFrame(long position) if (startTs != AV_NOPTS_VALUE) pos += (long long)(startTs * AV_TIME_BASE * timeBase); - av_seek_frame(m_formatCtx, -1, pos, AVSEEK_FLAG_BACKWARD); - // current position is now lost, guess a value. - // It's not important because it will be set at this end of this function - m_curPosition = position - m_preseek - 1; + if (position <= m_curPosition || !m_eof) + { + // no need to seek past the end of the file + if (av_seek_frame(m_formatCtx, -1, pos, AVSEEK_FLAG_BACKWARD) >= 0) + { + // current position is now lost, guess a value. + // It's not important because it will be set at this end of this function + m_curPosition = position - m_preseek - 1; + } + } // this is the timestamp of the frame we're looking for targetTs = (long long)(((double) position) / m_baseFrameRate / timeBase); if (startTs != AV_NOPTS_VALUE) @@ -599,6 +632,7 @@ bool VideoFFmpeg::grabFrame(long position) } av_free_packet(&packet); } + m_eof = !frameLoaded; if (frameLoaded) m_curPosition = position; return frameLoaded; |