Lorsqu'il est converti en code compilable en ajoutant suffisamment de pseudo-infrastructure pour simuler le système GST, GCC affiche un avertissement qui est presque certainement la source de votre problème :
gstq.c: In function ‘dequeue_gstbuffer’:
gstq.c:73:12: warning: ‘nextPtr’ is used uninitialized in this function [-Wuninitialized]
Les lignes sont :
72 GstBufferQueue **nextPtr;
73 *nextPtr = (*head)->next;
Sur ces lignes, vous avez besoin :
GstBufferQueue *nextPtr = (*head)->next;
Vous devez également utiliser :
(*head)->next = nextPtr;
Faites attention aux avertissements de votre compilateur. Si votre compilateur n'avertit pas, faites en sorte qu'il le fasse. Si vous ne pouvez pas le faire, trouvez un meilleur compilateur.
SSCCE
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#define GST_BUFFER_SIZE(x) sizeof(x)
#define GST_WARNING(x) fprintf(stderr, "%s\n", x)
typedef struct GstBuffer { int value; } GstBuffer;
typedef unsigned int guint;
static GstBuffer *gst_buffer_try_new_and_alloc(int size)
{
GstBuffer *buf = malloc(sizeof(GstBuffer));
assert(buf != 0);
buf->value = size;
return buf;
}
static GstBuffer *gst_buffer_copy(const GstBuffer *buf)
{
GstBuffer *new_buf = malloc(sizeof(GstBuffer));
assert(new_buf != 0);
new_buf->value = buf->value;
return new_buf;
}
static void gst_buffer_unref(GstBuffer *buf)
{
buf->value = -1;
}
typedef struct _GstBUFFERQUEUE GstBufferQueue;
struct _GstBUFFERQUEUE {
GstBuffer *buf;
guint buf_size;
struct _GstBUFFERQUEUE *next;
};
extern void enqueue_gstbuffer(GstBufferQueue **head, GstBufferQueue **tail, guint *queue_size, GstBuffer *buf);
extern void dequeue_gstbuffer(GstBufferQueue **head, GstBufferQueue **tail, guint *queue_size, GstBuffer **buf);
void enqueue_gstbuffer(GstBufferQueue **head, GstBufferQueue **tail, guint *queue_size, GstBuffer *buf)
{
if (*queue_size == 0)
{
*head = malloc(sizeof(GstBufferQueue));
(*head)->buf = gst_buffer_try_new_and_alloc(GST_BUFFER_SIZE(buf));
(*head)->buf = gst_buffer_copy(buf);
*tail = *head;
}
else
{
if (((*tail)->next = malloc(sizeof(GstBufferQueue))) != 0)
{
(*tail)->next->buf = gst_buffer_try_new_and_alloc(GST_BUFFER_SIZE(buf));
(*tail)->next->buf = gst_buffer_copy(buf);
(*tail) = (*tail)->next;
}
else
{
GST_WARNING("Error allocating memory for new buffer in queue");
}
}
(*tail)->next = NULL;
(*queue_size)++;
}
void dequeue_gstbuffer(GstBufferQueue **head, GstBufferQueue **tail, guint *queue_size, GstBuffer **buf)
{
GstBufferQueue **tmpPtr = head;
GstBufferQueue *nextPtr;
nextPtr = (*head)->next;
*buf = gst_buffer_try_new_and_alloc (GST_BUFFER_SIZE((*tmpPtr)->buf));
*buf = gst_buffer_copy((*tmpPtr)->buf);
gst_buffer_unref((*tmpPtr)->buf);
free((*tmpPtr));
*head = nextPtr;
if ((*head) == NULL)
(*tail) = NULL;
(*queue_size)--;
}
int main(void)
{
GstBufferQueue *q_head = 0;
GstBufferQueue *q_tail = 0;
guint q_size = 0;
for (int i = 0; i < 10; i++)
{
GstBuffer *buf = gst_buffer_try_new_and_alloc(i + 100);
enqueue_gstbuffer(&q_head, &q_tail, &q_size, buf);
printf("EQ: %d\n", buf->value);
free(buf);
if (i % 2 == 1)
{
GstBuffer *buf;
dequeue_gstbuffer(&q_head, &q_tail, &q_size, &buf);
printf("DQ: %d\n", buf->value);
free(buf);
}
}
while (q_size > 0)
{
GstBuffer *buf;
dequeue_gstbuffer(&q_head, &q_tail, &q_size, &buf);
printf("DQ: %d\n", buf->value);
free(buf);
}
printf("All done\n");
return(0);
}
Sortie
EQ: 100
EQ: 101
DQ: 100
EQ: 102
EQ: 103
DQ: 101
EQ: 104
EQ: 105
DQ: 102
EQ: 106
EQ: 107
DQ: 103
EQ: 108
EQ: 109
DQ: 104
DQ: 105
DQ: 106
DQ: 107
DQ: 108
DQ: 109
All done
Notez que le code SSCCE ci-dessus fuit plus qu'un tamis. Je n'ai pas l'intention de corriger ces fuites car elles se trouvent dans le code qui simule la gestion des tampons de la TPS. Vérifiez bien que votre code ne souffre pas de ces fuites de mémoire.
Je pense que vous devriez emballer votre "file d'attente" différemment. Ce que vous appelez une GstBufferQueue
devrait vraiment être un GstBufferQueueItem
et votre réel GstBufferQueue
doit contenir les pointeurs de tête et de queue, ainsi que la taille. Vous passeriez un pointeur vers le fichier (révisé) GstBufferQueue
au enqueue_gstbuffer()
y dequeue_gstbuffer()
au lieu de passer 3 paramètres distincts.
typedef struct GstBufferQueueItem GstBufferQueueItem;
struct GstBufferQueueItem
{
GstBuffer *buf;
guint buf_size;
GstBufferQueueItem *next;
};
typedef struct GstBufferQueue GstBufferQueue;
struct GstBufferQueue
{
GstBufferQueueItem *head;
GstBufferQueueItem *tail;
guint size;
};
// Uncompiled - but to give you an idea
void dequeue_gstbuffer(GstBufferQueue *q, GstBuffer **buf)
{
GstBufferQueueItem *item = q->head;
GstBufferQueueItem *next = item->next;
*buf = gst_buffer_try_new_and_alloc(GST_BUFFER_SIZE(item->buf));
*buf = gst_buffer_copy(item->buf);
gst_buffer_unref(item->buf);
free(item);
q->head = next;
if (q->head == NULL)
q->tail = NULL;
q->size--;
}
Notez que ces noms ne comportent pas de trait de soulignement en tête. De tels noms sont dangereux. Les noms avec un trait de soulignement et une lettre majuscule sont réservés à l'implémentation pour n'importe quel usage. Les noms avec un trait de soulignement et une lettre minuscule sont réservés à des mots différents, mais l'utilisation de l'un ou l'autre est douteuse (et bien que les normes ne disent pas grand-chose sur le trait de soulignement et le chiffre, ne jouez pas avec eux - considérez le trait de soulignement principal comme "réservé au système" à moins que vous n'écriviez "le système").
ISO/IEC 9899:2011 §7.1.3 Identifiants réservés
- Tous les identifiants qui commencent par un trait de soulignement et une lettre majuscule ou un autre caractère trait de soulignement sont toujours réservés à un usage quelconque.
- Tous les identifiants qui commencent par un trait de soulignement sont toujours réservés pour être utilisés comme identifiants. avec une portée de fichier dans les espaces de noms ordinaires et de balises.