mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 23:53:52 +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)
|
||||
: mAvContext(NULL)
|
||||
, mVideoStreamId(-1)
|
||||
, mAudioStreamId(-1)
|
||||
{
|
||||
Ogre::MaterialPtr videoMaterial = Ogre::MaterialManager::getSingleton ().create("VideoMaterial", "General");
|
||||
videoMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
|
||||
|
@ -108,6 +109,7 @@ namespace MWRender
|
|||
|
||||
|
||||
mVideoStreamId = -1;
|
||||
mAudioStreamId = -1;
|
||||
mEOF = false;
|
||||
mDisplayedFrameCount = 0;
|
||||
|
||||
|
@ -150,36 +152,60 @@ namespace MWRender
|
|||
|
||||
|
||||
|
||||
// INIT VIDEO
|
||||
|
||||
// Find the video stream among the different streams
|
||||
for (unsigned int i = 0; i < mAvContext->nb_streams; i++)
|
||||
{
|
||||
if (mAvContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
|
||||
{
|
||||
mVideoStreamId = i;
|
||||
mVideoStream = mAvContext->streams[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (-1 == mVideoStreamId)
|
||||
if (mVideoStreamId < 0)
|
||||
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
|
||||
mVideoCodec = avcodec_find_decoder(mVideoCodecContext->codec_id);
|
||||
mVideoCodec = avcodec_find_decoder(mVideoStream->codec->codec_id);
|
||||
if (NULL == mVideoCodec)
|
||||
throw std::runtime_error("No decoder found");
|
||||
throw std::runtime_error("No video decoder found");
|
||||
|
||||
// Load the video codec
|
||||
err = avcodec_open2(mVideoCodecContext, mVideoCodec, 0);
|
||||
err = avcodec_open2(mVideoStream->codec, mVideoCodec, 0);
|
||||
if (err < 0)
|
||||
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
|
||||
mRawFrame = 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
|
||||
// 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
|
||||
mSwsContext = sws_getContext(mVideoCodecContext->width, mVideoCodecContext->height,
|
||||
mVideoCodecContext->pix_fmt,
|
||||
mVideoCodecContext->width, mVideoCodecContext->height,
|
||||
mSwsContext = sws_getContext(mVideoStream->codec->width, mVideoStream->codec->height,
|
||||
mVideoStream->codec->pix_fmt,
|
||||
mVideoStream->codec->width, mVideoStream->codec->height,
|
||||
PIX_FMT_RGBA,
|
||||
SWS_BICUBIC, NULL, NULL, NULL);
|
||||
if (!mSwsContext)
|
||||
throw std::runtime_error("Can't create SWS Context");
|
||||
|
||||
// Get the frame time we need for this video
|
||||
AVRational r = mAvContext->streams[mVideoStreamId]->avg_frame_rate;
|
||||
AVRational r2 = mAvContext->streams[mVideoStreamId]->r_frame_rate;
|
||||
AVRational r = mVideoStream->avg_frame_rate;
|
||||
AVRational r2 = mVideoStream->r_frame_rate;
|
||||
if ((!r.num || !r.den) &&
|
||||
(!r2.num || !r2.den))
|
||||
{
|
||||
|
@ -230,19 +256,19 @@ namespace MWRender
|
|||
"VideoTexture",
|
||||
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
Ogre::TEX_TYPE_2D,
|
||||
mVideoCodecContext->width, mVideoCodecContext->height,
|
||||
mVideoStream->codec->width, mVideoStream->codec->height,
|
||||
0,
|
||||
Ogre::PF_BYTE_RGBA,
|
||||
Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
|
||||
|
||||
// initialize to (0, 0, 0, 1)
|
||||
std::vector<Ogre::uint32> buffer;
|
||||
buffer.resize(mVideoCodecContext->width * mVideoCodecContext->height);
|
||||
for (int p=0; p<mVideoCodecContext->width * mVideoCodecContext->height; ++p)
|
||||
buffer.resize(mVideoStream->codec->width * mVideoStream->codec->height);
|
||||
for (int p=0; p<mVideoStream->codec->width * mVideoStream->codec->height; ++p)
|
||||
{
|
||||
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();
|
||||
|
||||
mTextureUnit->setTextureName ("VideoTexture");
|
||||
|
@ -358,7 +384,7 @@ namespace MWRender
|
|||
// Get the front frame and decode it
|
||||
AVPacket *videoPacket = mVideoPacketQueue.front();
|
||||
int res;
|
||||
res = avcodec_decode_video2(mVideoCodecContext, mRawFrame, &didDecodeFrame, videoPacket);
|
||||
res = avcodec_decode_video2(mVideoStream->codec, mRawFrame, &didDecodeFrame, videoPacket);
|
||||
|
||||
if (res < 0 || !didDecodeFrame)
|
||||
throw std::runtime_error ("an error occured while decoding the video frame");
|
||||
|
@ -366,12 +392,12 @@ namespace MWRender
|
|||
// Convert the frame to RGB
|
||||
sws_scale(mSwsContext,
|
||||
mRawFrame->data, mRawFrame->linesize,
|
||||
0, mVideoCodecContext->height,
|
||||
0, mVideoStream->codec->height,
|
||||
mRGBAFrame->data, mRGBAFrame->linesize);
|
||||
|
||||
|
||||
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);
|
||||
|
||||
av_free_packet(mVideoPacketQueue.front());
|
||||
|
@ -397,7 +423,8 @@ namespace MWRender
|
|||
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);
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ namespace Ogre
|
|||
struct AVFormatContext;
|
||||
struct AVCodecContext;
|
||||
struct AVCodec;
|
||||
struct AVStream;
|
||||
struct AVFrame;
|
||||
struct SwsContext;
|
||||
struct AVPacket;
|
||||
|
@ -56,10 +57,14 @@ namespace MWRender
|
|||
|
||||
Ogre::Timer mTimer;
|
||||
|
||||
// VIDEO
|
||||
AVCodecContext* mVideoCodecContext;
|
||||
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* mRGBAFrame;
|
||||
SwsContext* mSwsContext;
|
||||
|
@ -67,6 +72,7 @@ namespace MWRender
|
|||
float mDecodingTime;
|
||||
std::queue <AVPacket *> mVideoPacketQueue;
|
||||
|
||||
|
||||
int mDisplayedFrameCount;
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue