On 11/8/11 2:10 PM, Evgeny Yakimov wrote:
Can you please advise which of these calls need to be protected with mutex
locks?

Could you check where helgrind complains? librtmp shouldn't have problems and libavformat in my experience has not as well.

You surely need to use something like a locked queue to feed the muxer side (a quite unpolished example using pthreads provided, once I have enough time to make it nicer I'll probably add it to avcodec, avplay has something close as well.

If you have a reduced testcase or an helgrind trace we could figure out better what's wrong.

lu
#ifndef AVPACKET_QUEUE_H
#define AVPACKET_QUEUE_H

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>

typedef struct AVPacketQueue {
    AVPacketList *first_pkt, *last_pkt;
    int nb_packets;
    int size;
    int abort_request;
    pthread_mutex_t mutex;
    pthread_cond_t cond;
} AVPacketQueue;

void avpacket_queue_init(AVPacketQueue *q);

void avpacket_queue_empty(AVPacketQueue *q);

void avpacket_queue_end(AVPacketQueue *q);

int avpacket_queue_put(AVPacketQueue *q, AVPacket *pkt);

int avpacket_queue_get(AVPacketQueue *q, AVPacket *pkt, int block);

int avpacket_queue_size(AVPacketQueue *q);

int avpacket_queue_flush(AVPacketQueue *q);

#endif /* AVPACKET_QUEUE_H */
#include "avpacket_queue.h"

static AVPacket flush_pkt;

void avpacket_queue_init(AVPacketQueue *q)
{
    memset(q, 0, sizeof(AVPacketQueue));
    pthread_mutex_init(&q->mutex, NULL);
    pthread_cond_init(&q->cond, NULL);
}

void avpacket_queue_empty(AVPacketQueue *q)
{
    AVPacketList *pkt, *pkt1;

    pthread_mutex_lock(&q->mutex);
    for(pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
        pkt1 = pkt->next;
        av_free_packet(&pkt->pkt);
        av_freep(&pkt);
    }
    q->last_pkt = NULL;
    q->first_pkt = NULL;
    q->nb_packets = 0;
    q->size = 0;
    pthread_mutex_unlock(&q->mutex);
}

void avpacket_queue_end(AVPacketQueue *q)
{
    avpacket_queue_empty(q);
    pthread_mutex_destroy(&q->mutex);
    pthread_cond_destroy(&q->cond);
}

int avpacket_queue_put(AVPacketQueue *q, AVPacket *pkt)
{
    AVPacketList *pkt1;

    /* duplicate the packet */
    if (pkt!=&flush_pkt && av_dup_packet(pkt) < 0)
        return -1;

    pkt1 = (AVPacketList *)av_malloc(sizeof(AVPacketList));
    if (!pkt1)
        return -1;
    pkt1->pkt = *pkt;
    pkt1->next = NULL;

    pthread_mutex_lock(&q->mutex);

    if (!q->last_pkt)

        q->first_pkt = pkt1;
    else
        q->last_pkt->next = pkt1;
    q->last_pkt = pkt1;
    q->nb_packets++;
    q->size += pkt1->pkt.size + sizeof(*pkt1);

    pthread_cond_signal(&q->cond);

    pthread_mutex_unlock(&q->mutex);
    return 0;
}

int avpacket_queue_get(AVPacketQueue *q, AVPacket *pkt, int block)
{
    AVPacketList *pkt1;
    int ret;

    pthread_mutex_lock(&q->mutex);

    for(;;) {
        pkt1 = q->first_pkt;
        if (pkt1) {
            if (pkt1->pkt.data == flush_pkt.data) {
                ret = 0;
                break;
            }
            q->first_pkt = pkt1->next;
            if (!q->first_pkt)
                q->last_pkt = NULL;
            q->nb_packets--;
            q->size -= pkt1->pkt.size + sizeof(*pkt1);
            *pkt = pkt1->pkt;
            av_free(pkt1);
            ret = 1;
            break;
        } else if (!block) {
            ret = 0;
            break;
        } else {
            pthread_cond_wait(&q->cond, &q->mutex);
        }
    }
    pthread_mutex_unlock(&q->mutex);
    return ret;
}

int avpacket_queue_size(AVPacketQueue *q)
{
    int size;
    pthread_mutex_lock(&q->mutex);
    size = q->size;
    pthread_mutex_unlock(&q->mutex);
    return size;
}

int avpacket_queue_flush(AVPacketQueue *q)
{
    return avpacket_queue_put(q, &flush_pkt);
}

_______________________________________________
libav-api mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-api

Reply via email to