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) :
|
AUD_FFMPEGReader::AUD_FFMPEGReader(std::string filename) :
|
||||||
m_pkgbuf(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1),
|
m_pkgbuf(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1),
|
||||||
m_byteiocontext(NULL)
|
m_byteiocontext(NULL),
|
||||||
|
m_membuf(NULL)
|
||||||
{
|
{
|
||||||
// open file
|
// open file
|
||||||
if(av_open_input_file(&m_formatCtx, filename.c_str(), NULL, 0, NULL)!=0)
|
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) :
|
AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer) :
|
||||||
m_pkgbuf(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1),
|
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(),
|
m_byteiocontext = av_alloc_put_byte(m_membuf, FF_MIN_BUFFER_SIZE, 0, this,
|
||||||
buffer.get()->getSize(), 0, NULL, NULL, NULL, NULL) != 0)
|
read_packet, NULL, seek_packet);
|
||||||
|
|
||||||
|
if(!m_byteiocontext)
|
||||||
{
|
{
|
||||||
av_free(m_byteiocontext);
|
av_free(m_byteiocontext);
|
||||||
AUD_THROW(AUD_ERROR_FILE, fileopen_error);
|
AUD_THROW(AUD_ERROR_FILE, fileopen_error);
|
||||||
@ -207,7 +211,7 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer) :
|
|||||||
|
|
||||||
AVProbeData probe_data;
|
AVProbeData probe_data;
|
||||||
probe_data.filename = "";
|
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();
|
probe_data.buf_size = buffer.get()->getSize();
|
||||||
AVInputFormat* fmt = av_probe_input_format(&probe_data, 1);
|
AVInputFormat* fmt = av_probe_input_format(&probe_data, 1);
|
||||||
|
|
||||||
@ -243,6 +247,40 @@ AUD_FFMPEGReader::~AUD_FFMPEGReader()
|
|||||||
av_close_input_file(m_formatCtx);
|
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
|
bool AUD_FFMPEGReader::isSeekable() const
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
@ -106,10 +106,20 @@ private:
|
|||||||
AUD_convert_f m_convert;
|
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;
|
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.
|
* Decodes a packet into the given buffer.
|
||||||
* \param packet The AVPacket to decode.
|
* \param packet The AVPacket to decode.
|
||||||
@ -149,6 +159,9 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual ~AUD_FFMPEGReader();
|
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 bool isSeekable() const;
|
||||||
virtual void seek(int position);
|
virtual void seek(int position);
|
||||||
virtual int getLength() const;
|
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)
|
if(G.fileflags & G_AUTOPACK)
|
||||||
BKE_report(op->reports, RPT_WARNING, "AutoPack is enabled, so image will be packed again on file save.");
|
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;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user