mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-21 12:23:51 +00:00
audio codec is opened, some cleanup
This commit is contained in:
parent
c4facc233e
commit
a77d910aaf
2 changed files with 61 additions and 28 deletions
|
@ -72,6 +72,7 @@ namespace MWRender
|
||||||
VideoPlayer::VideoPlayer(Ogre::SceneManager *sceneMgr)
|
VideoPlayer::VideoPlayer(Ogre::SceneManager *sceneMgr)
|
||||||
: mAvContext(NULL)
|
: mAvContext(NULL)
|
||||||
, mVideoStreamId(-1)
|
, mVideoStreamId(-1)
|
||||||
|
, mAudioStreamId(-1)
|
||||||
{
|
{
|
||||||
Ogre::MaterialPtr videoMaterial = Ogre::MaterialManager::getSingleton ().create("VideoMaterial", "General");
|
Ogre::MaterialPtr videoMaterial = Ogre::MaterialManager::getSingleton ().create("VideoMaterial", "General");
|
||||||
videoMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
|
videoMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
|
||||||
|
@ -108,6 +109,7 @@ namespace MWRender
|
||||||
|
|
||||||
|
|
||||||
mVideoStreamId = -1;
|
mVideoStreamId = -1;
|
||||||
|
mAudioStreamId = -1;
|
||||||
mEOF = false;
|
mEOF = false;
|
||||||
mDisplayedFrameCount = 0;
|
mDisplayedFrameCount = 0;
|
||||||
|
|
||||||
|
@ -150,36 +152,60 @@ namespace MWRender
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// INIT VIDEO
|
|
||||||
|
|
||||||
// Find the video stream among the different streams
|
// Find the video stream among the different streams
|
||||||
for (unsigned int i = 0; i < mAvContext->nb_streams; i++)
|
for (unsigned int i = 0; i < mAvContext->nb_streams; i++)
|
||||||
{
|
{
|
||||||
if (mAvContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
|
if (mAvContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
|
||||||
{
|
{
|
||||||
mVideoStreamId = i;
|
mVideoStreamId = i;
|
||||||
|
mVideoStream = mAvContext->streams[i];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-1 == mVideoStreamId)
|
if (mVideoStreamId < 0)
|
||||||
throw std::runtime_error("No video stream found in the video");
|
throw std::runtime_error("No video stream found in the video");
|
||||||
|
|
||||||
// Get the video codec
|
|
||||||
mVideoCodecContext = mAvContext->streams[mVideoStreamId]->codec;
|
|
||||||
if (!mVideoCodecContext)
|
|
||||||
throw std::runtime_error("Stream doesn't have a codec");
|
|
||||||
|
|
||||||
// Get the video decoder
|
// Get the video decoder
|
||||||
mVideoCodec = avcodec_find_decoder(mVideoCodecContext->codec_id);
|
mVideoCodec = avcodec_find_decoder(mVideoStream->codec->codec_id);
|
||||||
if (NULL == mVideoCodec)
|
if (NULL == mVideoCodec)
|
||||||
throw std::runtime_error("No decoder found");
|
throw std::runtime_error("No video decoder found");
|
||||||
|
|
||||||
// Load the video codec
|
// Load the video codec
|
||||||
err = avcodec_open2(mVideoCodecContext, mVideoCodec, 0);
|
err = avcodec_open2(mVideoStream->codec, mVideoCodec, 0);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
throwError (err);
|
throwError (err);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Find the audio stream among the different streams
|
||||||
|
for (unsigned int i = 0; i < mAvContext->nb_streams; i++)
|
||||||
|
{
|
||||||
|
if (mAvContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
|
||||||
|
{
|
||||||
|
mAudioStreamId = i;
|
||||||
|
mAudioStream = mAvContext->streams[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-1 == mAudioStreamId)
|
||||||
|
throw std::runtime_error("No audio stream found in the video");
|
||||||
|
|
||||||
|
// Get the audio decoder
|
||||||
|
mAudioCodec = avcodec_find_decoder(mAudioStream->codec->codec_id);
|
||||||
|
if (mAudioCodec == NULL)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Stream doesn't have an audio codec");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the audio codec
|
||||||
|
err = avcodec_open2(mAudioStream->codec, mAudioCodec, 0);
|
||||||
|
if (err < 0)
|
||||||
|
throwError (err);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Create the frame buffers
|
// Create the frame buffers
|
||||||
mRawFrame = avcodec_alloc_frame();
|
mRawFrame = avcodec_alloc_frame();
|
||||||
mRGBAFrame = avcodec_alloc_frame();
|
mRGBAFrame = avcodec_alloc_frame();
|
||||||
|
@ -189,23 +215,23 @@ namespace MWRender
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
avpicture_alloc ((AVPicture *)mRGBAFrame, PIX_FMT_RGBA, mVideoCodecContext->width, mVideoCodecContext->height);
|
avpicture_alloc ((AVPicture *)mRGBAFrame, PIX_FMT_RGBA, mVideoStream->codec->width, mVideoStream->codec->height);
|
||||||
|
|
||||||
|
|
||||||
// Setup the image scaler
|
// Setup the image scaler
|
||||||
// All this does is convert from YUV to RGB - note it would be faster to do this in a shader,
|
// All this does is convert from YUV to RGB - note it would be faster to do this in a shader,
|
||||||
// but i'm not worried about performance just yet
|
// but i'm not worried about performance just yet
|
||||||
mSwsContext = sws_getContext(mVideoCodecContext->width, mVideoCodecContext->height,
|
mSwsContext = sws_getContext(mVideoStream->codec->width, mVideoStream->codec->height,
|
||||||
mVideoCodecContext->pix_fmt,
|
mVideoStream->codec->pix_fmt,
|
||||||
mVideoCodecContext->width, mVideoCodecContext->height,
|
mVideoStream->codec->width, mVideoStream->codec->height,
|
||||||
PIX_FMT_RGBA,
|
PIX_FMT_RGBA,
|
||||||
SWS_BICUBIC, NULL, NULL, NULL);
|
SWS_BICUBIC, NULL, NULL, NULL);
|
||||||
if (!mSwsContext)
|
if (!mSwsContext)
|
||||||
throw std::runtime_error("Can't create SWS Context");
|
throw std::runtime_error("Can't create SWS Context");
|
||||||
|
|
||||||
// Get the frame time we need for this video
|
// Get the frame time we need for this video
|
||||||
AVRational r = mAvContext->streams[mVideoStreamId]->avg_frame_rate;
|
AVRational r = mVideoStream->avg_frame_rate;
|
||||||
AVRational r2 = mAvContext->streams[mVideoStreamId]->r_frame_rate;
|
AVRational r2 = mVideoStream->r_frame_rate;
|
||||||
if ((!r.num || !r.den) &&
|
if ((!r.num || !r.den) &&
|
||||||
(!r2.num || !r2.den))
|
(!r2.num || !r2.den))
|
||||||
{
|
{
|
||||||
|
@ -230,19 +256,19 @@ namespace MWRender
|
||||||
"VideoTexture",
|
"VideoTexture",
|
||||||
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||||
Ogre::TEX_TYPE_2D,
|
Ogre::TEX_TYPE_2D,
|
||||||
mVideoCodecContext->width, mVideoCodecContext->height,
|
mVideoStream->codec->width, mVideoStream->codec->height,
|
||||||
0,
|
0,
|
||||||
Ogre::PF_BYTE_RGBA,
|
Ogre::PF_BYTE_RGBA,
|
||||||
Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
|
Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
|
||||||
|
|
||||||
// initialize to (0, 0, 0, 1)
|
// initialize to (0, 0, 0, 1)
|
||||||
std::vector<Ogre::uint32> buffer;
|
std::vector<Ogre::uint32> buffer;
|
||||||
buffer.resize(mVideoCodecContext->width * mVideoCodecContext->height);
|
buffer.resize(mVideoStream->codec->width * mVideoStream->codec->height);
|
||||||
for (int p=0; p<mVideoCodecContext->width * mVideoCodecContext->height; ++p)
|
for (int p=0; p<mVideoStream->codec->width * mVideoStream->codec->height; ++p)
|
||||||
{
|
{
|
||||||
buffer[p] = (255 << 24);
|
buffer[p] = (255 << 24);
|
||||||
}
|
}
|
||||||
memcpy(mVideoTexture->getBuffer()->lock(Ogre::HardwareBuffer::HBL_DISCARD), &buffer[0], mVideoCodecContext->width*mVideoCodecContext->height*4);
|
memcpy(mVideoTexture->getBuffer()->lock(Ogre::HardwareBuffer::HBL_DISCARD), &buffer[0], mVideoStream->codec->width*mVideoStream->codec->height*4);
|
||||||
mVideoTexture->getBuffer()->unlock();
|
mVideoTexture->getBuffer()->unlock();
|
||||||
|
|
||||||
mTextureUnit->setTextureName ("VideoTexture");
|
mTextureUnit->setTextureName ("VideoTexture");
|
||||||
|
@ -358,7 +384,7 @@ namespace MWRender
|
||||||
// Get the front frame and decode it
|
// Get the front frame and decode it
|
||||||
AVPacket *videoPacket = mVideoPacketQueue.front();
|
AVPacket *videoPacket = mVideoPacketQueue.front();
|
||||||
int res;
|
int res;
|
||||||
res = avcodec_decode_video2(mVideoCodecContext, mRawFrame, &didDecodeFrame, videoPacket);
|
res = avcodec_decode_video2(mVideoStream->codec, mRawFrame, &didDecodeFrame, videoPacket);
|
||||||
|
|
||||||
if (res < 0 || !didDecodeFrame)
|
if (res < 0 || !didDecodeFrame)
|
||||||
throw std::runtime_error ("an error occured while decoding the video frame");
|
throw std::runtime_error ("an error occured while decoding the video frame");
|
||||||
|
@ -366,12 +392,12 @@ namespace MWRender
|
||||||
// Convert the frame to RGB
|
// Convert the frame to RGB
|
||||||
sws_scale(mSwsContext,
|
sws_scale(mSwsContext,
|
||||||
mRawFrame->data, mRawFrame->linesize,
|
mRawFrame->data, mRawFrame->linesize,
|
||||||
0, mVideoCodecContext->height,
|
0, mVideoStream->codec->height,
|
||||||
mRGBAFrame->data, mRGBAFrame->linesize);
|
mRGBAFrame->data, mRGBAFrame->linesize);
|
||||||
|
|
||||||
|
|
||||||
Ogre::HardwarePixelBufferSharedPtr pixelBuffer = mVideoTexture->getBuffer();
|
Ogre::HardwarePixelBufferSharedPtr pixelBuffer = mVideoTexture->getBuffer();
|
||||||
Ogre::PixelBox pb(mVideoCodecContext->width, mVideoCodecContext->height, 1, Ogre::PF_BYTE_RGBA, mRGBAFrame->data[0]);
|
Ogre::PixelBox pb(mVideoStream->codec->width, mVideoStream->codec->height, 1, Ogre::PF_BYTE_RGBA, mRGBAFrame->data[0]);
|
||||||
pixelBuffer->blitFromMemory(pb);
|
pixelBuffer->blitFromMemory(pb);
|
||||||
|
|
||||||
av_free_packet(mVideoPacketQueue.front());
|
av_free_packet(mVideoPacketQueue.front());
|
||||||
|
@ -397,7 +423,8 @@ namespace MWRender
|
||||||
mVideoPacketQueue.pop();
|
mVideoPacketQueue.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
avcodec_close(mVideoCodecContext);
|
if (mVideoStream && mVideoStream->codec != NULL) avcodec_close(mVideoStream->codec);
|
||||||
|
if (mAudioStream && mAudioStream->codec != NULL) avcodec_close(mAudioStream->codec);
|
||||||
|
|
||||||
avpicture_free((AVPicture *)mRGBAFrame);
|
avpicture_free((AVPicture *)mRGBAFrame);
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ namespace Ogre
|
||||||
struct AVFormatContext;
|
struct AVFormatContext;
|
||||||
struct AVCodecContext;
|
struct AVCodecContext;
|
||||||
struct AVCodec;
|
struct AVCodec;
|
||||||
|
struct AVStream;
|
||||||
struct AVFrame;
|
struct AVFrame;
|
||||||
struct SwsContext;
|
struct SwsContext;
|
||||||
struct AVPacket;
|
struct AVPacket;
|
||||||
|
@ -56,10 +57,14 @@ namespace MWRender
|
||||||
|
|
||||||
Ogre::Timer mTimer;
|
Ogre::Timer mTimer;
|
||||||
|
|
||||||
// VIDEO
|
|
||||||
AVCodecContext* mVideoCodecContext;
|
|
||||||
AVCodec* mVideoCodec;
|
AVCodec* mVideoCodec;
|
||||||
int mVideoStreamId;
|
AVCodec* mAudioCodec;
|
||||||
|
|
||||||
|
AVStream* mVideoStream;
|
||||||
|
AVStream* mAudioStream;
|
||||||
|
int mVideoStreamId; ///< ID of the first video stream
|
||||||
|
int mAudioStreamId; ///< ID of the first audio stream
|
||||||
|
|
||||||
AVFrame* mRawFrame;
|
AVFrame* mRawFrame;
|
||||||
AVFrame* mRGBAFrame;
|
AVFrame* mRGBAFrame;
|
||||||
SwsContext* mSwsContext;
|
SwsContext* mSwsContext;
|
||||||
|
@ -67,6 +72,7 @@ namespace MWRender
|
||||||
float mDecodingTime;
|
float mDecodingTime;
|
||||||
std::queue <AVPacket *> mVideoPacketQueue;
|
std::queue <AVPacket *> mVideoPacketQueue;
|
||||||
|
|
||||||
|
|
||||||
int mDisplayedFrameCount;
|
int mDisplayedFrameCount;
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue