dea*_*ake 2 c queue tail head gstreamer
我正在尝试为Gstreamer缓冲区实现自定义队列.问题是,当我试图出列时,似乎我正在失去队列的头部.每当我尝试两次出队时,我都会遇到分段错误.我也注意到头部总是等于头部 - >下一个.现在我不确定入队或出队是否有问题.请帮帮我.谢谢.
typedef struct _GstBUFFERQUEUE GstBufferQueue;
struct _GstBUFFERQUEUE {
GstBuffer *buf;
guint buf_size;
struct _GstBUFFERQUEUE *next;
};
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))) {
(*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)--;
}
Run Code Online (Sandbox Code Playgroud)
当通过添加足够的伪基础设施来模拟GST系统转换为可编译代码时,GCC会发出警告,几乎可以肯定是您的麻烦来源:
gstq.c: In function ‘dequeue_gstbuffer’:
gstq.c:73:12: warning: ‘nextPtr’ is used uninitialized in this function [-Wuninitialized]
Run Code Online (Sandbox Code Playgroud)
这些线是:
72 GstBufferQueue **nextPtr;
73 *nextPtr = (*head)->next;
Run Code Online (Sandbox Code Playgroud)
在这些方面,您需要:
GstBufferQueue *nextPtr = (*head)->next;
Run Code Online (Sandbox Code Playgroud)
您还需要使用:
(*head)->next = nextPtr;
Run Code Online (Sandbox Code Playgroud)
注意编译器警告.如果编译器没有发出警告,请执行此操作.如果您无法发出警告,请获得更好的编译器.
#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);
}
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
请注意,上面的SSCCE代码泄漏比筛子差.我没有计划修复泄漏,因为它们在模拟GST缓冲区管理的代码中.检查您的代码是否没有内存泄漏.
我认为你应该以不同方式打包你的'队列'.你所谓的a GstBufferQueue应该是a GstBufferQueueItem,你的实际GstBufferQueue应该包含头部和尾部指针以及大小.您将指向(修订的)指针传递GstBufferQueue给enqueue_gstbuffer()和dequeue_gstbuffer()函数,而不是传递3个单独的参数.
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--;
}
Run Code Online (Sandbox Code Playgroud)
请注意,这些名称避免使用前导下划线.这样的名字很危险.带有下划线和大写字母的名称保留用于任何目的的实现.带有下划线和小写字母的名字保留不同的单词,但使用其中任何一个是狡猾的(虽然标准对下划线和数字很少说,不要用它们玩游戏 - 将前导下划线视为'保留给系统'除非你写'系统').
- 所有以下划线开头的标识符以及大写字母或另一个下划线始终保留用于任何用途.
- 所有以下划线开头的标识符始终保留用作普通和标记名称空间中具有文件范围的标识符.