== FFMPEG ==
This fixes a memory leak caused by the last packet on stream EOF not freed. (Memory leak occurs on ffmpeg heap managed by av_malloc / av_free, so it is invisible to Blender) Also: clean up the code a little bit (anim->next_packet was never really used, so could be moved into a local variable)
This commit is contained in:
@@ -178,7 +178,6 @@ struct anim {
|
||||
struct ImBuf *last_frame;
|
||||
int64_t last_pts;
|
||||
int64_t next_pts;
|
||||
AVPacket next_packet;
|
||||
#endif
|
||||
|
||||
#ifdef WITH_REDCODE
|
||||
|
||||
@@ -557,7 +557,6 @@ static int startffmpeg(struct anim *anim)
|
||||
anim->last_frame = 0;
|
||||
anim->last_pts = -1;
|
||||
anim->next_pts = -1;
|
||||
anim->next_packet.stream_index = -1;
|
||||
|
||||
anim->pFormatCtx = pFormatCtx;
|
||||
anim->pCodecCtx = pCodecCtx;
|
||||
@@ -764,41 +763,39 @@ static void ffmpeg_postprocess(struct anim *anim)
|
||||
}
|
||||
}
|
||||
|
||||
/* decode one video frame also considering the packet read into next_packet */
|
||||
/* decode one video frame */
|
||||
|
||||
static int ffmpeg_decode_video_frame(struct anim *anim)
|
||||
{
|
||||
int rval = 0;
|
||||
AVPacket next_packet;
|
||||
|
||||
memset(&next_packet, 0, sizeof(AVPacket));
|
||||
|
||||
av_log(anim->pFormatCtx, AV_LOG_DEBUG, " DECODE VIDEO FRAME\n");
|
||||
|
||||
if (anim->next_packet.stream_index == anim->videoStream) {
|
||||
av_free_packet(&anim->next_packet);
|
||||
anim->next_packet.stream_index = -1;
|
||||
}
|
||||
|
||||
while ((rval = av_read_frame(anim->pFormatCtx, &anim->next_packet)) >= 0) {
|
||||
while ((rval = av_read_frame(anim->pFormatCtx, &next_packet)) >= 0) {
|
||||
av_log(anim->pFormatCtx,
|
||||
AV_LOG_DEBUG,
|
||||
"%sREAD: strID=%d (VID: %d) dts=%lld pts=%lld "
|
||||
"%s\n",
|
||||
(anim->next_packet.stream_index == anim->videoStream)
|
||||
(next_packet.stream_index == anim->videoStream)
|
||||
? "->" : " ",
|
||||
anim->next_packet.stream_index,
|
||||
next_packet.stream_index,
|
||||
anim->videoStream,
|
||||
(anim->next_packet.dts == AV_NOPTS_VALUE) ? -1 :
|
||||
(long long int)anim->next_packet.dts,
|
||||
(anim->next_packet.pts == AV_NOPTS_VALUE) ? -1 :
|
||||
(long long int)anim->next_packet.pts,
|
||||
(anim->next_packet.flags & AV_PKT_FLAG_KEY) ?
|
||||
(next_packet.dts == AV_NOPTS_VALUE) ? -1 :
|
||||
(long long int)next_packet.dts,
|
||||
(next_packet.pts == AV_NOPTS_VALUE) ? -1 :
|
||||
(long long int)next_packet.pts,
|
||||
(next_packet.flags & AV_PKT_FLAG_KEY) ?
|
||||
" KEY" : "");
|
||||
if (anim->next_packet.stream_index == anim->videoStream) {
|
||||
if (next_packet.stream_index == anim->videoStream) {
|
||||
anim->pFrameComplete = 0;
|
||||
|
||||
avcodec_decode_video2(
|
||||
anim->pCodecCtx,
|
||||
anim->pFrame, &anim->pFrameComplete,
|
||||
&anim->next_packet);
|
||||
&next_packet);
|
||||
|
||||
if (anim->pFrameComplete) {
|
||||
anim->next_pts = av_get_pts_from_frame(
|
||||
@@ -816,20 +813,24 @@ static int ffmpeg_decode_video_frame(struct anim *anim)
|
||||
break;
|
||||
}
|
||||
}
|
||||
av_free_packet(&anim->next_packet);
|
||||
anim->next_packet.stream_index = -1;
|
||||
av_free_packet(&next_packet);
|
||||
}
|
||||
|
||||
/* this sets size and data fields to zero,
|
||||
which is necessary to decode the remaining data
|
||||
in the decoder engine after EOF. It also prevents a memory
|
||||
leak, since av_read_frame spills out a full size packet even
|
||||
on EOF... (and: it's save to call on NULL packets) */
|
||||
|
||||
av_free_packet(&next_packet);
|
||||
|
||||
if (rval == AVERROR_EOF) {
|
||||
anim->next_packet.size = 0;
|
||||
anim->next_packet.data = 0;
|
||||
|
||||
anim->pFrameComplete = 0;
|
||||
|
||||
avcodec_decode_video2(
|
||||
anim->pCodecCtx,
|
||||
anim->pFrame, &anim->pFrameComplete,
|
||||
&anim->next_packet);
|
||||
&next_packet);
|
||||
|
||||
if (anim->pFrameComplete) {
|
||||
anim->next_pts = av_get_pts_from_frame(
|
||||
@@ -849,8 +850,6 @@ static int ffmpeg_decode_video_frame(struct anim *anim)
|
||||
}
|
||||
|
||||
if (rval < 0) {
|
||||
anim->next_packet.stream_index = -1;
|
||||
|
||||
av_log(anim->pFormatCtx,
|
||||
AV_LOG_ERROR, " DECODE READ FAILED: av_read_frame() "
|
||||
"returned error: %d\n", rval);
|
||||
@@ -1087,13 +1086,6 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position,
|
||||
|
||||
anim->next_pts = -1;
|
||||
|
||||
if (anim->next_packet.stream_index == anim->videoStream) {
|
||||
av_free_packet(&anim->next_packet);
|
||||
anim->next_packet.stream_index = -1;
|
||||
}
|
||||
|
||||
/* memset(anim->pFrame, ...) ?? */
|
||||
|
||||
if (ret >= 0) {
|
||||
ffmpeg_decode_video_frame_scan(anim, pts_to_search);
|
||||
}
|
||||
@@ -1140,9 +1132,6 @@ static void free_anim_ffmpeg(struct anim *anim)
|
||||
av_free(anim->pFrameDeinterlaced);
|
||||
sws_freeContext(anim->img_convert_ctx);
|
||||
IMB_freeImBuf(anim->last_frame);
|
||||
if (anim->next_packet.stream_index != -1) {
|
||||
av_free_packet(&anim->next_packet);
|
||||
}
|
||||
}
|
||||
anim->duration = 0;
|
||||
}
|
||||
|
||||
@@ -912,6 +912,8 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context,
|
||||
AVPacket next_packet;
|
||||
uint64_t stream_size;
|
||||
|
||||
memset(&next_packet, 0, sizeof(AVPacket));
|
||||
|
||||
in_frame = avcodec_alloc_frame();
|
||||
|
||||
stream_size = avio_size(context->iFormatCtx->pb);
|
||||
@@ -959,12 +961,13 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context,
|
||||
* according to ffmpeg docs using 0-size packets.
|
||||
*
|
||||
* At least, if we haven't already stopped... */
|
||||
|
||||
/* this creates the 0-size packet and prevents a memory leak. */
|
||||
av_free_packet(&next_packet);
|
||||
|
||||
if (!*stop) {
|
||||
int frame_finished;
|
||||
|
||||
next_packet.size = 0;
|
||||
next_packet.data = 0;
|
||||
|
||||
do {
|
||||
frame_finished = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user