mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-27 03:35:27 +00:00
Update the ffmpeg decoder to use avcodec_decode_audio4
This commit is contained in:
parent
5f4c33f896
commit
5fff1c4e47
@ -20,13 +20,14 @@ struct FFmpeg_Decoder::MyStream {
|
|||||||
int mStreamIdx;
|
int mStreamIdx;
|
||||||
|
|
||||||
AVPacket mPacket;
|
AVPacket mPacket;
|
||||||
|
AVFrame *mFrame;
|
||||||
|
|
||||||
char *mDecodedData;
|
int mFrameSize;
|
||||||
size_t mDecodedDataSize;
|
int mFramePos;
|
||||||
|
|
||||||
FFmpeg_Decoder *mParent;
|
FFmpeg_Decoder *mParent;
|
||||||
|
|
||||||
void *getAVAudioData(size_t *length);
|
bool getAVAudioData();
|
||||||
size_t readAVAudioData(void *data, size_t length);
|
size_t readAVAudioData(void *data, size_t length);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -84,23 +85,20 @@ bool FFmpeg_Decoder::getNextPacket()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *FFmpeg_Decoder::MyStream::getAVAudioData(size_t *length)
|
bool FFmpeg_Decoder::MyStream::getAVAudioData()
|
||||||
{
|
{
|
||||||
int size, len;
|
int got_frame, len;
|
||||||
|
|
||||||
if(length) *length = 0;
|
|
||||||
if(mCodecCtx->codec_type != AVMEDIA_TYPE_AUDIO)
|
if(mCodecCtx->codec_type != AVMEDIA_TYPE_AUDIO)
|
||||||
return NULL;
|
return false;
|
||||||
|
|
||||||
mDecodedDataSize = 0;
|
|
||||||
do {
|
do {
|
||||||
if(mPacket.size == 0 && !mParent->getNextPacket())
|
if(mPacket.size == 0 && !mParent->getNextPacket())
|
||||||
return NULL;
|
return false;
|
||||||
|
|
||||||
/* Decode some data, and check for errors */
|
/* Decode some data, and check for errors */
|
||||||
size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
|
if((len=avcodec_decode_audio4(mCodecCtx, mFrame, &got_frame, &mPacket)) < 0)
|
||||||
if((len=avcodec_decode_audio3(mCodecCtx, (int16_t*)mDecodedData, &size, &mPacket)) < 0)
|
return false;
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* Move the unread data to the front and clear the end bits */
|
/* Move the unread data to the front and clear the end bits */
|
||||||
int remaining = mPacket.size - len;
|
int remaining = mPacket.size - len;
|
||||||
@ -111,13 +109,9 @@ void *FFmpeg_Decoder::MyStream::getAVAudioData(size_t *length)
|
|||||||
memmove(mPacket.data, &mPacket.data[len], remaining);
|
memmove(mPacket.data, &mPacket.data[len], remaining);
|
||||||
av_shrink_packet(&mPacket, remaining);
|
av_shrink_packet(&mPacket, remaining);
|
||||||
}
|
}
|
||||||
} while(size == 0);
|
} while(got_frame == 0 || mFrame->nb_samples == 0);
|
||||||
|
|
||||||
/* Set the output buffer size */
|
return true;
|
||||||
mDecodedDataSize = size;
|
|
||||||
if(length) *length = mDecodedDataSize;
|
|
||||||
|
|
||||||
return mDecodedData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t FFmpeg_Decoder::MyStream::readAVAudioData(void *data, size_t length)
|
size_t FFmpeg_Decoder::MyStream::readAVAudioData(void *data, size_t length)
|
||||||
@ -127,34 +121,24 @@ size_t FFmpeg_Decoder::MyStream::readAVAudioData(void *data, size_t length)
|
|||||||
while(dec < length)
|
while(dec < length)
|
||||||
{
|
{
|
||||||
/* If there's no decoded data, find some */
|
/* If there's no decoded data, find some */
|
||||||
if(mDecodedDataSize == 0)
|
if(mFramePos >= mFrameSize)
|
||||||
{
|
{
|
||||||
if(getAVAudioData(NULL) == NULL)
|
if(!getAVAudioData())
|
||||||
break;
|
break;
|
||||||
|
mFramePos = 0;
|
||||||
|
mFrameSize = mFrame->nb_samples * mCodecCtx->channels *
|
||||||
|
av_get_bytes_per_sample(mCodecCtx->sample_fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mDecodedDataSize > 0)
|
|
||||||
{
|
|
||||||
/* Get the amount of bytes remaining to be written, and clamp to
|
/* Get the amount of bytes remaining to be written, and clamp to
|
||||||
* the amount of decoded data we have */
|
* the amount of decoded data we have */
|
||||||
size_t rem = length-dec;
|
size_t rem = std::min<size_t>(length-dec, mFrameSize-mFramePos);
|
||||||
if(rem > mDecodedDataSize)
|
|
||||||
rem = mDecodedDataSize;
|
|
||||||
|
|
||||||
/* Copy the data to the app's buffer and increment */
|
/* Copy the data to the app's buffer and increment */
|
||||||
if(data != NULL)
|
memcpy(data, mFrame->data[0]+mFramePos, rem);
|
||||||
{
|
|
||||||
memcpy(data, mDecodedData, rem);
|
|
||||||
data = (char*)data + rem;
|
data = (char*)data + rem;
|
||||||
}
|
|
||||||
dec += rem;
|
dec += rem;
|
||||||
|
mFramePos += rem;
|
||||||
/* If there's any decoded data left, move it to the front of the
|
|
||||||
* buffer for next time */
|
|
||||||
if(rem < mDecodedDataSize)
|
|
||||||
memmove(mDecodedData, &mDecodedData[rem], mDecodedDataSize - rem);
|
|
||||||
mDecodedDataSize -= rem;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the number of bytes we were able to get */
|
/* Return the number of bytes we were able to get */
|
||||||
@ -162,7 +146,6 @@ size_t FFmpeg_Decoder::MyStream::readAVAudioData(void *data, size_t length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void FFmpeg_Decoder::open(const std::string &fname)
|
void FFmpeg_Decoder::open(const std::string &fname)
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
@ -211,8 +194,7 @@ void FFmpeg_Decoder::open(const std::string &fname)
|
|||||||
if(avcodec_open2(stream->mCodecCtx, codec, NULL) < 0)
|
if(avcodec_open2(stream->mCodecCtx, codec, NULL) < 0)
|
||||||
fail("Failed to open audio codec " + std::string(codec->long_name));
|
fail("Failed to open audio codec " + std::string(codec->long_name));
|
||||||
|
|
||||||
stream->mDecodedData = (char*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
|
stream->mFrame = avcodec_alloc_frame();
|
||||||
stream->mDecodedDataSize = 0;
|
|
||||||
|
|
||||||
stream->mParent = this;
|
stream->mParent = this;
|
||||||
mStream = stream;
|
mStream = stream;
|
||||||
@ -231,7 +213,7 @@ void FFmpeg_Decoder::close()
|
|||||||
{
|
{
|
||||||
av_free_packet(&mStream->mPacket);
|
av_free_packet(&mStream->mPacket);
|
||||||
avcodec_close(mStream->mCodecCtx);
|
avcodec_close(mStream->mCodecCtx);
|
||||||
av_free(mStream->mDecodedData);
|
av_free(mStream->mFrame);
|
||||||
}
|
}
|
||||||
mStream.reset();
|
mStream.reset();
|
||||||
|
|
||||||
@ -315,13 +297,13 @@ void FFmpeg_Decoder::readAll(std::vector<char> &output)
|
|||||||
if(!mStream.get())
|
if(!mStream.get())
|
||||||
fail("No audio stream");
|
fail("No audio stream");
|
||||||
|
|
||||||
char *inbuf;
|
while(mStream->getAVAudioData())
|
||||||
size_t got;
|
|
||||||
while((inbuf=(char*)mStream->getAVAudioData(&got)) != NULL && got > 0)
|
|
||||||
{
|
{
|
||||||
output.insert(output.end(), inbuf, inbuf+got);
|
size_t got = mStream->mFrame->nb_samples * mStream->mCodecCtx->channels *
|
||||||
mSamplesRead += got / mStream->mCodecCtx->channels /
|
|
||||||
av_get_bytes_per_sample(mStream->mCodecCtx->sample_fmt);
|
av_get_bytes_per_sample(mStream->mCodecCtx->sample_fmt);
|
||||||
|
const char *inbuf = reinterpret_cast<char*>(mStream->mFrame->data[0]);
|
||||||
|
output.insert(output.end(), inbuf, inbuf+got);
|
||||||
|
mSamplesRead += mStream->mFrame->nb_samples;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user