1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-31 20:45:34 +00:00

Only store one packet at a time

This commit is contained in:
Chris Robinson 2012-12-15 22:54:54 -08:00
parent 9d86890d9d
commit 5f4c33f896

View file

@ -15,23 +15,17 @@ static void fail(const std::string &msg)
{ throw std::runtime_error("FFmpeg exception: "+msg); } { throw std::runtime_error("FFmpeg exception: "+msg); }
struct PacketList {
AVPacket pkt;
PacketList *next;
};
struct FFmpeg_Decoder::MyStream { struct FFmpeg_Decoder::MyStream {
AVCodecContext *mCodecCtx; AVCodecContext *mCodecCtx;
int mStreamIdx; int mStreamIdx;
PacketList *mPackets; AVPacket mPacket;
char *mDecodedData; char *mDecodedData;
size_t mDecodedDataSize; size_t mDecodedDataSize;
FFmpeg_Decoder *mParent; FFmpeg_Decoder *mParent;
void clearPackets();
void *getAVAudioData(size_t *length); void *getAVAudioData(size_t *length);
size_t readAVAudioData(void *data, size_t length); size_t readAVAudioData(void *data, size_t length);
}; };
@ -77,104 +71,47 @@ bool FFmpeg_Decoder::getNextPacket()
if(!mStream.get()) if(!mStream.get())
return false; return false;
PacketList *packet = (PacketList*)av_malloc(sizeof(*packet)); while(av_read_frame(mFormatCtx, &mStream->mPacket) >= 0)
packet->next = NULL;
while(av_read_frame(mFormatCtx, &packet->pkt) >= 0)
{ {
/* Check if the packet belongs to this stream */ /* Check if the packet belongs to this stream */
if(mStream->mStreamIdx == packet->pkt.stream_index) if(mStream->mStreamIdx == mStream->mPacket.stream_index)
{
PacketList **last;
last = &mStream->mPackets;
while(*last != NULL)
last = &(*last)->next;
*last = packet;
return true; return true;
}
/* Free the packet and look for another */ /* Free the packet and look for another */
av_free_packet(&packet->pkt); av_free_packet(&mStream->mPacket);
} }
av_free(packet);
return false; return false;
} }
void FFmpeg_Decoder::MyStream::clearPackets()
{
while(mPackets)
{
PacketList *self = mPackets;
mPackets = self->next;
av_free_packet(&self->pkt);
av_free(self);
}
}
void *FFmpeg_Decoder::MyStream::getAVAudioData(size_t *length) void *FFmpeg_Decoder::MyStream::getAVAudioData(size_t *length)
{ {
int size; int size, len;
int len;
if(length) *length = 0; if(length) *length = 0;
if(mCodecCtx->codec_type != AVMEDIA_TYPE_AUDIO) if(mCodecCtx->codec_type != AVMEDIA_TYPE_AUDIO)
return NULL; return NULL;
mDecodedDataSize = 0; mDecodedDataSize = 0;
do {
if(mPacket.size == 0 && !mParent->getNextPacket())
return NULL;
next_packet: /* Decode some data, and check for errors */
if(!mPackets && !mParent->getNextPacket())
return NULL;
/* Decode some data, and check for errors */
size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
while((len=avcodec_decode_audio3(mCodecCtx, (int16_t*)mDecodedData, &size,
&mPackets->pkt)) == 0)
{
PacketList *self;
if(size > 0)
break;
/* Packet went unread and no data was given? Drop it and try the next,
* I guess... */
self = mPackets;
mPackets = self->next;
av_free_packet(&self->pkt);
av_free(self);
if(!mPackets)
goto next_packet;
size = AVCODEC_MAX_AUDIO_FRAME_SIZE; size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
} if((len=avcodec_decode_audio3(mCodecCtx, (int16_t*)mDecodedData, &size, &mPacket)) < 0)
return NULL;
if(len < 0)
return NULL;
if(len < mPackets->pkt.size)
{
/* 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 = mPackets->pkt.size - len; int remaining = mPacket.size - len;
memmove(mPackets->pkt.data, &mPackets->pkt.data[len], remaining); if(remaining <= 0)
av_shrink_packet(&mPackets->pkt, remaining); av_free_packet(&mPacket);
} else
else {
{ memmove(mPacket.data, &mPacket.data[len], remaining);
PacketList *self; av_shrink_packet(&mPacket, remaining);
}
self = mPackets; } while(size == 0);
mPackets = self->next;
av_free_packet(&self->pkt);
av_free(self);
}
if(size == 0)
goto next_packet;
/* Set the output buffer size */ /* Set the output buffer size */
mDecodedDataSize = size; mDecodedDataSize = size;
@ -262,7 +199,7 @@ void FFmpeg_Decoder::open(const std::string &fname)
std::auto_ptr<MyStream> stream(new MyStream); std::auto_ptr<MyStream> stream(new MyStream);
stream->mCodecCtx = mFormatCtx->streams[audio_idx]->codec; stream->mCodecCtx = mFormatCtx->streams[audio_idx]->codec;
stream->mStreamIdx = audio_idx; stream->mStreamIdx = audio_idx;
stream->mPackets = NULL; memset(&stream->mPacket, 0, sizeof(stream->mPacket));
AVCodec *codec = avcodec_find_decoder(stream->mCodecCtx->codec_id); AVCodec *codec = avcodec_find_decoder(stream->mCodecCtx->codec_id);
if(!codec) if(!codec)
@ -292,7 +229,7 @@ void FFmpeg_Decoder::close()
{ {
if(mStream.get()) if(mStream.get())
{ {
mStream->clearPackets(); av_free_packet(&mStream->mPacket);
avcodec_close(mStream->mCodecCtx); avcodec_close(mStream->mCodecCtx);
av_free(mStream->mDecodedData); av_free(mStream->mDecodedData);
} }
@ -392,7 +329,7 @@ void FFmpeg_Decoder::rewind()
{ {
av_seek_frame(mFormatCtx, -1, 0, 0); av_seek_frame(mFormatCtx, -1, 0, 0);
if(mStream.get()) if(mStream.get())
mStream->clearPackets(); av_free_packet(&mStream->mPacket);
mSamplesRead = 0; mSamplesRead = 0;
} }