Skip to content

Commit 463c0fc

Browse files
committed
fix memory leak
especially in swr conversion
1 parent 2a4dead commit 463c0fc

File tree

4 files changed

+57
-56
lines changed

4 files changed

+57
-56
lines changed
Binary file not shown.
0 Bytes
Binary file not shown.

Extensions/_3rdLib/FFMpeg.h

Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,6 +1043,7 @@ class FFMpeg {
10431043
#ifdef _DEBUG
10441044
auto err = GetErrorStr(response);
10451045
#endif // _DEBUG
1046+
av_packet_unref(frames.pPacket);
10461047

10471048
break;
10481049
}
@@ -1069,6 +1070,8 @@ class FFMpeg {
10691070
this->bSeeking = false;
10701071
convert_frame(frames.pLastFrame, callBack);
10711072

1073+
av_packet_unref(frames.pPacket);
1074+
10721075
return response;
10731076
}
10741077

@@ -1100,13 +1103,15 @@ class FFMpeg {
11001103
bReadFinish = (response == AVERROR_EOF);
11011104

11021105
const bool bStop = videoQueue.readFinish() && audioQueue.readFinish();
1103-
11041106
if (bReadFinish && !bStop) {
11051107
videoQueue.stopBlock();
11061108
audioQueue.stopBlock();
11071109
}
11081110

1109-
if (response < 0) { return response; }
1111+
if (response < 0) {
1112+
av_packet_unref(pPacket);
1113+
return response;
1114+
}
11101115

11111116
do {
11121117
if (pPacket->stream_index == video_stream_index) {
@@ -1126,9 +1131,6 @@ class FFMpeg {
11261131
}
11271132

11281133
inline void convert_frame(AVFrame* pFrame, const frameDataCallBack& callBack) {
1129-
// data invalid, do not trigger callback, in case of get a black frame
1130-
if (!pFrame->data[0]) { return; }
1131-
11321134
#ifdef HW_DECODE
11331135
if (bHWDecode) {
11341136
av_frame_unref(pSWFrame);
@@ -1140,11 +1142,15 @@ class FFMpeg {
11401142
throw FFMpegException(FFMpegException_HWDecodeFailed);
11411143
}
11421144

1143-
pFrame = pSWFrame;
1145+
av_frame_unref(pFrame);
1146+
av_frame_move_ref(pFrame, pSWFrame);
11441147
}
11451148
}
11461149
#endif // HW_DECODE
11471150

1151+
// data invalid, do not trigger callback, in case of get a black frame
1152+
if (!pFrame->data[0]) { return; }
1153+
11481154
// Convert data to Bitmap data
11491155
// https://zhuanlan.zhihu.com/p/53305541
11501156

@@ -1172,29 +1178,29 @@ class FFMpeg {
11721178

11731179
sws_scale(swsContext, pFrame->data, pFrame->linesize, 0, pFrame->height, bgr_buffer, linesize);
11741180

1175-
//bgr_buffer[0] is the BGR raw data
1181+
//bgr_buffer[0] is the BGR raw data, aka p_global_bgr_buffer
11761182
callBack(bgr_buffer[0], linesize[0], pFrame->height);
1183+
1184+
av_frame_unref(pFrame);
11771185
}
11781186

11791187
inline int decode_frame(const frameDataCallBack& callBack) {
11801188
SyncState syncState;
11811189

11821190
do {
11831191
// calc delay
1184-
syncState = get_syncState();
1185-
1186-
//syncState = SyncState::SYNC_SYNC;
1192+
syncState = get_syncState();
11871193

11881194
// decode
11891195
switch (syncState) {
11901196
// video is faster, wait
1191-
case FFMpeg::SyncState::SYNC_VIDEOFASTER:
1197+
case SyncState::SYNC_VIDEOFASTER:
11921198
return 0;
11931199
// decode new video frame
1194-
case FFMpeg::SyncState::SYNC_CLOCKFASTER:
1195-
case FFMpeg::SyncState::SYNC_SYNC:
1200+
case SyncState::SYNC_CLOCKFASTER:
1201+
case SyncState::SYNC_SYNC:
11961202
int response = fill_decode([&]() {
1197-
return decode_videoFrame(pVLastFrame);
1203+
return decode_videoFrame(pVLastFrame);
11981204
});
11991205

12001206
if (response < 0) {
@@ -1226,6 +1232,7 @@ class FFMpeg {
12261232

12271233
// pFrame: frame to receive data
12281234
// pLastFrame: frame to ref latest updated pFrame
1235+
// This function will handle the av_packet_unref
12291236
inline int decode_frameCore(bool& bFinishState, bool& bSendEAgain,
12301237
const bool& bBlockState, PacketQueue& queue,
12311238
AVCodecContext* pCodecContext, AVPacket* pPacket, AVFrame* pFrame, AVFrame* pLastFrame,
@@ -1249,6 +1256,7 @@ class FFMpeg {
12491256
bSendEAgain = (response == AVERROR(EAGAIN));
12501257

12511258
if (response < 0 && !bSendEAgain && response != AVERROR_EOF) {
1259+
av_packet_unref(pPacket);
12521260
return response;
12531261
}
12541262

@@ -1258,9 +1266,7 @@ class FFMpeg {
12581266

12591267
// won't release if current packed didn't use
12601268
if (!bSendEAgain) {
1261-
if (pPacket && pPacket->data) {
1262-
av_packet_unref(pPacket);
1263-
}
1269+
av_packet_unref(pPacket);
12641270
}
12651271

12661272
if (bFinishState) {
@@ -1284,27 +1290,24 @@ class FFMpeg {
12841290
&FFMpeg::decode_apacket);
12851291
}
12861292

1293+
// This function will handle the av_frame_unref
1294+
// av_packet_unref is handled by caller
12871295
inline int decode_vpacket(AVCodecContext* pVCodecContext, const AVPacket* pVPacket,
12881296
AVFrame* pFrame, AVFrame* pLastFrame) {
12891297
// Return decoded output data (into a frame) from a decoder
12901298
// https://ffmpeg.org/doxygen/trunk/group__lavc__decoding.html#ga11e6542c4e66d3028668788a1a74217c
12911299
int response = avcodec_receive_frame(pVCodecContext, pFrame);
12921300

1293-
#ifdef _DEBUG
1294-
auto err = GetErrorStr(response);
1295-
#endif
1296-
12971301
if (response == AVERROR(EAGAIN) || response == AVERROR_EOF) {
1302+
av_frame_unref(pFrame);
12981303
return response;
12991304
}
13001305

13011306
if (response < 0) {
13021307
av_frame_unref(pFrame);
1303-
13041308
return response;
13051309
}
13061310

1307-
//videoPts = 0;
13081311
videoPts = static_cast<double>(pFrame->best_effort_timestamp);
13091312

13101313
if (pVPacket != nullptr) {
@@ -1339,23 +1342,26 @@ class FFMpeg {
13391342
}
13401343
#endif
13411344

1342-
if (!bSeeking
1343-
|| (bSeeking && (videoClock >= seekingTargetPts))) {
1345+
// update laset frame by moving ref
1346+
if (!bSeeking || (bSeeking && (videoClock >= seekingTargetPts))) {
13441347
av_frame_unref(pLastFrame);
1345-
av_frame_ref(pLastFrame, pFrame);
1348+
av_frame_move_ref(pLastFrame, pFrame);
13461349
}
13471350

13481351
av_frame_unref(pFrame);
13491352

13501353
return response;
13511354
}
13521355

1356+
// This function will handle the av_frame_unref
1357+
// av_packet_unref is handled by caller
13531358
//https://github.com/brookicv/FFMPEG-study/blob/master/FFmpeg-playAudio.cpp
13541359
inline int decode_apacket(AVCodecContext* pACodecContext, const AVPacket* pAPacket,
13551360
AVFrame* pFrame, AVFrame* pLastFrame) {
13561361
int response = avcodec_receive_frame(pACodecContext, pFrame);
13571362

13581363
if (response == AVERROR(EAGAIN) || response == AVERROR_EOF) {
1364+
av_frame_unref(pFrame);
13591365
return response;
13601366
}
13611367

@@ -1364,10 +1370,18 @@ class FFMpeg {
13641370
return response;
13651371
}
13661372

1373+
// frame to process
1374+
auto pBaseFrame = pFrame;
1375+
1376+
// a while loop is wrapped in, `av_buffersink_get_frame` to get filtered frame
13671377
#ifdef AUDIO_TEMPO
1378+
pBaseFrame = pAFilterFrame;
13681379
response = av_buffersrc_add_frame_flags(buffersrc_ctx, pFrame, AV_BUFFERSRC_FLAG_KEEP_REF);
13691380

1370-
if (response < 0) { return response; }
1381+
if (response < 0) {
1382+
av_frame_unref(pFrame);
1383+
return response;
1384+
}
13711385

13721386
while (true) {
13731387
response = av_buffersink_get_frame(buffersink_ctx, pAFilterFrame);
@@ -1376,8 +1390,8 @@ class FFMpeg {
13761390
}
13771391

13781392
if (response < 0) {
1379-
av_frame_unref(pFrame);
13801393
av_frame_unref(pAFilterFrame);
1394+
av_frame_unref(pFrame);
13811395
}
13821396
#endif // AUDIO_TEMPO
13831397

@@ -1390,12 +1404,6 @@ class FFMpeg {
13901404
#endif
13911405
}
13921406

1393-
#ifdef AUDIO_TEMPO
1394-
auto pBaseFrame = pAFilterFrame;
1395-
#else
1396-
auto pBaseFrame = pFrame;
1397-
#endif // AUDIO_TEMPO
1398-
13991407
// update context to avoid crash
14001408
if (bUpdateSwr) {
14011409
init_SwrContext(&pBaseFrame->ch_layout,
@@ -1421,15 +1429,23 @@ class FFMpeg {
14211429
audioPts = audioClock;
14221430
audioClock += static_cast<double>(audioSize) / (static_cast<double>(pcm_bytes) * static_cast<double>(pACodecContext->sample_rate));
14231431

1432+
#ifdef AUDIO_TEMPO
1433+
av_frame_unref(pAFilterFrame);
1434+
#endif // AUDIO_TEMPO
1435+
1436+
av_frame_unref(pFrame);
1437+
14241438
return audioSize;
14251439

14261440
#ifdef AUDIO_TEMPO
14271441
}
14281442

1429-
av_frame_unref(pAFrame);
1443+
av_frame_unref(pAFilterFrame);
1444+
#endif // AUDIO_TEMPO
1445+
1446+
av_frame_unref(pFrame);
14301447

14311448
return -1;
1432-
#endif // AUDIO_TEMPO
14331449
}
14341450

14351451
// ------------------------------------

Extensions/_3rdLib/PacketQueue.h

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -265,26 +265,17 @@ class PacketQueue {
265265
}
266266

267267
inline bool put(AVPacket* pPacket) {
268-
//AVPacket pkt;
269-
270-
//if (av_packet_ref(&pkt, pPacket) < 0) {
271-
// return false;
272-
//}
273-
274-
const AVPacket pkt = *pPacket;
275-
*pPacket = *pEmptyPacket;
276-
277268
#ifdef QUEUE_SPINLOCK
278269
SDL_AtomicLock(&audioLock);
279270
#else
280271
SDL_LockMutex(mutex);
281272
#endif
273+
AVPacket pkt = *pEmptyPacket;
274+
av_packet_move_ref(&pkt, pPacket);
282275

283276
queue.emplace(pkt);
284-
285277
dataSize += pkt.size;
286-
//nb_packets++;
287-
278+
288279
#ifdef QUEUE_SPINLOCK
289280
#else
290281
SDL_CondSignal(cond);
@@ -317,16 +308,10 @@ class PacketQueue {
317308
}
318309

319310
if (!queue.empty()) {
320-
//if (av_packet_ref(pPacket, &queue.front()) < 0) {
321-
// ret = false;
322-
323-
// break;
324-
//}
325-
326-
*pPacket = queue.front();
311+
av_packet_unref(pPacket);
312+
av_packet_move_ref(pPacket, &queue.front());
327313

328314
queue.pop();
329-
//nb_packets--;
330315
dataSize -= pPacket->size;
331316

332317
ret = true;

0 commit comments

Comments
 (0)