forked from bartvdbraak/blender
Fix for [#26990] Loading file w packed audio crashes
FFMPEG was reallocating buffers it didn't own and wasn't allowed to. This workaround should work now flawlessly. Also fixing a bug regarding unpacking sounds, the UI stated unpacking to //audio/filename while it was unpacking to //sounds/filename
This commit is contained in:
parent
54f3167270
commit
5f08bfd46c
@ -172,7 +172,8 @@ static const char* fileopen_error = "AUD_FFMPEGReader: File couldn't be "
|
||||
|
||||
AUD_FFMPEGReader::AUD_FFMPEGReader(std::string filename) :
|
||||
m_pkgbuf(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1),
|
||||
m_byteiocontext(NULL)
|
||||
m_byteiocontext(NULL),
|
||||
m_membuf(NULL)
|
||||
{
|
||||
// open file
|
||||
if(av_open_input_file(&m_formatCtx, filename.c_str(), NULL, 0, NULL)!=0)
|
||||
@ -194,12 +195,15 @@ static const char* streamopen_error = "AUD_FFMPEGReader: Stream couldn't be "
|
||||
|
||||
AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer) :
|
||||
m_pkgbuf(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1),
|
||||
m_membuffer(buffer)
|
||||
m_membuffer(buffer),
|
||||
m_membufferpos(0)
|
||||
{
|
||||
m_byteiocontext = (ByteIOContext*)av_mallocz(sizeof(ByteIOContext));
|
||||
m_membuf = reinterpret_cast<data_t*>(av_malloc(FF_MIN_BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE));
|
||||
|
||||
if(init_put_byte(m_byteiocontext, (data_t*)buffer.get()->getBuffer(),
|
||||
buffer.get()->getSize(), 0, NULL, NULL, NULL, NULL) != 0)
|
||||
m_byteiocontext = av_alloc_put_byte(m_membuf, FF_MIN_BUFFER_SIZE, 0, this,
|
||||
read_packet, NULL, seek_packet);
|
||||
|
||||
if(!m_byteiocontext)
|
||||
{
|
||||
av_free(m_byteiocontext);
|
||||
AUD_THROW(AUD_ERROR_FILE, fileopen_error);
|
||||
@ -207,7 +211,7 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer) :
|
||||
|
||||
AVProbeData probe_data;
|
||||
probe_data.filename = "";
|
||||
probe_data.buf = (data_t*)buffer.get()->getBuffer();
|
||||
probe_data.buf = reinterpret_cast<data_t*>(buffer.get()->getBuffer());
|
||||
probe_data.buf_size = buffer.get()->getSize();
|
||||
AVInputFormat* fmt = av_probe_input_format(&probe_data, 1);
|
||||
|
||||
@ -243,6 +247,40 @@ AUD_FFMPEGReader::~AUD_FFMPEGReader()
|
||||
av_close_input_file(m_formatCtx);
|
||||
}
|
||||
|
||||
int AUD_FFMPEGReader::read_packet(void* opaque, uint8_t* buf, int buf_size)
|
||||
{
|
||||
AUD_FFMPEGReader* reader = reinterpret_cast<AUD_FFMPEGReader*>(opaque);
|
||||
|
||||
int size = AUD_MIN(buf_size, reader->m_membuffer.get()->getSize() - reader->m_membufferpos);
|
||||
|
||||
if(size < 0)
|
||||
return -1;
|
||||
|
||||
memcpy(buf, ((data_t*)reader->m_membuffer.get()->getBuffer()) + reader->m_membufferpos, size);
|
||||
reader->m_membufferpos += size;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int64_t AUD_FFMPEGReader::seek_packet(void* opaque, int64_t offset, int whence)
|
||||
{
|
||||
AUD_FFMPEGReader* reader = reinterpret_cast<AUD_FFMPEGReader*>(opaque);
|
||||
|
||||
switch(whence)
|
||||
{
|
||||
case SEEK_SET:
|
||||
reader->m_membufferpos = 0;
|
||||
break;
|
||||
case SEEK_END:
|
||||
reader->m_membufferpos = reader->m_membuffer.get()->getSize();
|
||||
break;
|
||||
case AVSEEK_SIZE:
|
||||
return reader->m_membuffer.get()->getSize();
|
||||
}
|
||||
|
||||
return (reader->m_membufferpos += offset);
|
||||
}
|
||||
|
||||
bool AUD_FFMPEGReader::isSeekable() const
|
||||
{
|
||||
return true;
|
||||
|
@ -106,10 +106,20 @@ private:
|
||||
AUD_convert_f m_convert;
|
||||
|
||||
/**
|
||||
* The memory file to read from, only saved to keep the buffer alive.
|
||||
* The memory file to read from.
|
||||
*/
|
||||
AUD_Reference<AUD_Buffer> m_membuffer;
|
||||
|
||||
/**
|
||||
* The buffer to read with.
|
||||
*/
|
||||
data_t* m_membuf;
|
||||
|
||||
/**
|
||||
* Reading position of the buffer.
|
||||
*/
|
||||
int64_t m_membufferpos;
|
||||
|
||||
/**
|
||||
* Decodes a packet into the given buffer.
|
||||
* \param packet The AVPacket to decode.
|
||||
@ -149,6 +159,9 @@ public:
|
||||
*/
|
||||
virtual ~AUD_FFMPEGReader();
|
||||
|
||||
static int read_packet(void* opaque, uint8_t* buf, int buf_size);
|
||||
static int64_t seek_packet(void* opaque, int64_t offset, int whence);
|
||||
|
||||
virtual bool isSeekable() const;
|
||||
virtual void seek(int position);
|
||||
virtual int getLength() const;
|
||||
|
@ -254,7 +254,7 @@ static int sound_unpack_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(even
|
||||
if(G.fileflags & G_AUTOPACK)
|
||||
BKE_report(op->reports, RPT_WARNING, "AutoPack is enabled, so image will be packed again on file save.");
|
||||
|
||||
unpack_menu(C, "SOUND_OT_unpack", sound->id.name+2, sound->name, "audio", sound->packedfile);
|
||||
unpack_menu(C, "SOUND_OT_unpack", sound->id.name+2, sound->name, "sounds", sound->packedfile);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user