[英]FFMpeg DVB Subtitles memory leak
當從mpegts udp mutlicast流解碼字幕軌道時,我使用avcodec_decode_subtitle2遇到內存泄漏。 音頻和視頻流很好。 通過預分配所有緩沖區,對這三個流進行手動內存管理。
關於的信息很少,但我確實相信某個地方有補丁。
我目前正在使用為armv7-a編譯的ffmpeg 2.0.4。
在此過程中,我發現視頻流具有不同的分辨率,即720x576或576x576,現在這無關緊要,因為我將字幕分別渲染為視頻的疊加層。 我原來的解碼功能(正在更改以渲染單獨的疊加層)是:
void ffProcessSubtitlePacket( AVPacket *pkt )
{
//LOGI("NATIVE FFMPEG SUBTITLE - Decoding subtitle packet");
int got = 0;
avcodec_decode_subtitle2(ffSubtitleContext, &ffSubtitleFrame, &got, pkt);
if ( got )
{
//LOGI("NATIVE FFMPEG SUBTITLE - Got subtitle frame");
//LOGI("NATIVE FFMPEG SUBTITLE - Format = %d, Start = %d, End = %d, Rects = %d, PTS = %llu, AudioPTS = %llu, PacketPTS = %llu",
// ffSubtitleFrame.format, ffSubtitleFrame.start_display_time,
// ffSubtitleFrame.end_display_time, ffSubtitleFrame.num_rects,
// ffSubtitleFrame.pts, ffAudioGetPTS(), pkt->pts);
// now add the subtitle data to the list ready
for ( int s = 0; s < ffSubtitleFrame.num_rects; s++ )
{
ffSubtitle *sub = (ffSubtitle*)mmAlloc(sizeof(ffSubtitle)); //new ffSubtitle;
if ( sub )
{
AVSubtitleRect *r = ffSubtitleFrame.rects[s];
AVPicture *p = &r->pict;
// set main data
sub->startPTS = pkt->pts + (uint64_t)ffSubtitleFrame.start_display_time;
sub->endPTS = pkt->pts + (uint64_t)ffSubtitleFrame.end_display_time * (uint64_t)500;
sub->nb_colors = r->nb_colors;
sub->xpos = r->x;
sub->ypos = r->y;
sub->width = r->w;
sub->height = r->h;
// allocate space for CLUT and image all in one chunk
sub->data = mmAlloc(r->nb_colors * 4 + r->w * r->h); //new char[r->nb_colors * 4 + r->w * r->h];
if ( sub->data )
{
// copy the CLUT data
memcpy(sub->data, p->data[1], r->nb_colors * 4);
// copy the bitmap onto the end
memcpy(sub->data + r->nb_colors * 4, p->data[0], r->w * r->h);
// check for duplicate subtitles and remove them as this
// one replaces it with a new bitmap data
int pos = ffSubtitles.size();
while ( pos-- )
{
ffSubtitle *s = ffSubtitles[pos];
if ( s->xpos == sub->xpos &&
s->ypos == sub->ypos &&
s->width == sub->width &&
s->height == sub->height )
{
//delete s;
ffSubtitles.erase( ffSubtitles.begin() + pos );
//LOGI("NATIVE FFMPEG SUBTITLE - Removed old duplicate subtitle, size %d", ffSubtitles.size());
}
}
// append to subtitles list
ffSubtitles.push_back( sub );
char *dat; // data pointer used for the CLUT table
//LOGI("NATIVE FFMPEG SUBTITLE - Added %d,%d - %d,%d, Queue %d, Length = %d",
// r->x, r->y, r->w, r->h, ffSubtitles.size(), ffSubtitleFrame.end_display_time);
// convert the CLUT (RGB) to YUV values
dat = sub->data;
for ( int c = 0; c < r->nb_colors; c++ )
{
int r = dat[0];
int g = dat[1];
int b = dat[2];
int y = ( ( 65 * r + 128 * g + 24 * b + 128) >> 8) + 16;
int u = ( ( -37 * r - 74 * g + 112 * b + 128) >> 8) + 128;
int v = ( ( 112 * r - 93 * g - 18 * b + 128) >> 8) + 128;
*dat++ = (char)y;
*dat++ = (char)u;
*dat++ = (char)v;
dat++; // skip the alpha channel
}
}
else
{
//delete sub;
sub = 0;
LOGI("NATIVE FFMPEG SUBTITLE - Memory allocation error CLUT and BITMAP");
}
}
else
{
LOGI("NATIVE FFMPEG SUBTITLE - Memory allocation error ffSubtitle struct");
mmGarbageCollect();
ffSubtitles.clear();
}
}
}
}
void ffSubtitleRenderCheck(int bpos)
{
if ( ffSubtitleID == -1 || !usingSubtitles )
{
// empty the list in case of memory leaks
ffSubtitles.clear();
mmGarbageCollect();
return;
}
uint64_t audioPTS = ffAudioGetPTS();
int pos = 0;
// draw the subtitle list to the YUV frames
char *yframe = ffVideoBuffers[bpos].yFrame;
char *uframe = ffVideoBuffers[bpos].uFrame;
char *vframe = ffVideoBuffers[bpos].vFrame;
int ywidth = fv.frameActualWidth; // actual width with padding
int uvwidth = fv.frameAWidthHalf; // and for uv frames
while ( pos < ffSubtitles.size() )
{
ffSubtitle *sub = ffSubtitles[pos];
if ( sub->startPTS >= audioPTS ) // okay to draw this one?
{
//LOGI("NATIVE FFMPEG SUBTITLE - Rendering subtitle bitmap %d", pos);
char *clut = sub->data; // colour table
char *dat = clut + sub->nb_colors * 4; // start of bitmap data
int w = sub->width;
int h = sub->height;
int x = sub->xpos;
int y = sub->ypos;
for ( int xpos = 0; xpos < w; xpos++ )
{
for ( int ypos = 0; ypos < h; ypos++ )
{
// get colour for pixel
char bcol = dat[ypos * w + xpos];
if ( bcol != 0 ) // ignore 0 pixels
{
char cluty = clut[bcol * 4 + 0]; // get colours from CLUT
char clutu = clut[bcol * 4 + 1];
char clutv = clut[bcol * 4 + 2];
// draw to Y frame
int newx = x + xpos;
int newy = y + ypos;
yframe[newy * ywidth + newx] = cluty;
// draw to uv frames if we have a quarter pixel only
if ( ( newy & 1 ) && ( newx & 1 ) )
{
uframe[(newy >> 1) * uvwidth + (newx >> 1)] = clutu;
vframe[(newy >> 1) * uvwidth + (newx >> 1)] = clutv;
}
}
}
}
}
pos++;
}
// Last thing is to erase timed out subtitles
pos = ffSubtitles.size();
while ( pos-- )
{
ffSubtitle *sub = ffSubtitles[pos];
if ( sub->endPTS < audioPTS )
{
//delete sub;
ffSubtitles.erase( ffSubtitles.begin() + pos );
//LOGI("NATIVE FFMPEG SUBTITLE - Removed timed out subtitle");
}
}
if ( ffSubtitles.size() == 0 )
{
// garbage collect the custom memory pool
mmGarbageCollect();
}
//LOGI("NATIVE FFMPEG SUBTITLE - Size of subtitle list = %d", ffSubtitles.size());
}
任何信息將不勝感激,還是我必須升級到ffmpeg的更高版本?
瀏覽完ffmpeg源代碼本身后,我發現了為什么內存泄漏。
事實證明,在解碼字幕幀時,在處理了獲得的幀中的信息之后,我所缺少的只是:
avsubtitle_free( &ffSubtitleFrame );
現在,我可以繼續進行項目的其余部分,並重寫字幕解碼器和渲染器。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.