Opened 5 years ago

Closed 5 years ago

Last modified 5 years ago

#8549 closed defect (fixed)

A memory leak in ffplay

Reported by: elite_jwp Owned by: Marton Balint
Priority: normal Component: ffplay
Version: unspecified Keywords: leak
Cc: Marton Balint Blocked By:
Blocking: Reproduced by developer: no
Analyzed by developer: no

Description

In ffplay.c:637, there is a code block as below:

       do {
            if (d->queue->nb_packets == 0)
                SDL_CondSignal(d->empty_queue_cond);
            if (d->packet_pending) {
                av_packet_move_ref(&pkt, &d->pkt);
                d->packet_pending = 0;
            } else {
                if (packet_queue_get(d->queue, &pkt, 1, &d->pkt_serial) < 0)
                    return -1;
            }
        } while (d->queue->serial != d->pkt_serial);

It seems that av_packet_unref is not done with pkt before doing next loop.

Change History (7)

comment:1 by elite_jwp, 5 years ago

Component: undeterminedffplay
Keywords: memory leak added
Version: unspecified4.2

comment:2 by Carl Eugen Hoyos, 5 years ago

Keywords: memory removed
Version: 4.2unspecified

Can you reproduce the issue with current FFmpeg git head?

comment:3 by Marton Balint, 5 years ago

Cc: Marton Balint added
Owner: set to Marton Balint
Status: newopen

comment:4 by Carl Eugen Hoyos, 5 years ago

Resolution: fixed
Status: openclosed

Should be fixed by Marton Balint in af7ec793d49e260aa4c5595d4947322fc91aa72d

comment:5 by elite_jwp, 5 years ago

Resolution: fixed
Status: closedreopened

The fixed code still exists a issue:
When using "av_packet_unref" to release memeory, it doesn't take the "flush_pkt" as a exception.

Based on the new fixed code, here gives a patch:

         do {
            if (d->queue->nb_packets == 0)
                 SDL_CondSignal(d->empty_queue_cond);
            if (d->packet_pending) {
                 av_packet_move_ref(&pkt, &d->pkt);
                 d->packet_pending = 0;
             } else {
                 if (packet_queue_get(d->queue, &pkt, 1, &d->pkt_serial) < 0)
                    return -1;
             }
             if (d->queue->serial == d->pkt_serial)
                break;
             if(pkt->data != flush_pkt.data)
                av_packet_unref(&pkt);
         } while (1);

Is it ok?

Last edited 5 years ago by elite_jwp (previous) (diff)

comment:6 by mkver, 5 years ago

Resolution: fixed
Status: reopenedclosed

av_packet_unref(&pkt) does not directly free pkt.data (pkt is not a pointer here, hence pkt->data would not even compile); instead it just unreferences the AVBufferRef pkt.buf (and the packet's side-data) and only if the reference counter of the underlying AVBuffer is zero will the actual resource owned by the AVBuffer be freed. But flush_pkt.buf is NULL, i.e. there is no underlying AVBuffer. The data field is used here only to say "I am a flush packet". Nothing will be freed in case pkt.data == flush_pkt.data.

comment:7 by elite_jwp, 5 years ago

I got it! Thanks!

Note: See TracTickets for help on using tickets.