linuxC写一个程序实现以下要求 (1)创建两个线程A, B (2)自定义一个队列YuvQueue,队列最多5张图片 (3)线程A循环读取10个yuv格式的图片,放入YuvQueue中,若队列满则停止读取指导YuvQueue有空余位置,读取100次之后,通知B线程发送完成 (4)线程B依次从YuvQueue中读取YUV数据,并调用libjpeg-turbo的函数进行编码,编码成jpeg,jpeg文件名为毫秒级系统时间(2022-06-02-11:11:11.056.jpeg) (5)线程B收到A的发送完成消息后,继续读完YuvQueue队列中所有文件并编码完成之后退出 (6)采用Makefile管理编译和链接过程
时间: 2024-01-22 18:02:08 浏览: 29
好的,下面是实现要求的代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <jpeglib.h>
#define YUV_QUEUE_SIZE 5
#define YUV_FILE_COUNT 10
typedef struct YuvQueue {
char** data;
int front;
int rear;
int count;
int size;
pthread_mutex_t lock;
pthread_cond_t not_full;
pthread_cond_t not_empty;
} YuvQueue;
YuvQueue* create_queue(int size) {
YuvQueue* queue = (YuvQueue*)malloc(sizeof(YuvQueue));
queue->data = (char**)malloc(sizeof(char*) * size);
queue->front = 0;
queue->rear = -1;
queue->count = 0;
queue->size = size;
pthread_mutex_init(&queue->lock, NULL);
pthread_cond_init(&queue->not_full, NULL);
pthread_cond_init(&queue->not_empty, NULL);
return queue;
}
void destroy_queue(YuvQueue* queue) {
free(queue->data);
pthread_mutex_destroy(&queue->lock);
pthread_cond_destroy(&queue->not_full);
pthread_cond_destroy(&queue->not_empty);
free(queue);
}
int is_full(YuvQueue* queue) {
return queue->count == queue->size;
}
int is_empty(YuvQueue* queue) {
return queue->count == 0;
}
void enqueue(YuvQueue* queue, char* item) {
pthread_mutex_lock(&queue->lock);
while (is_full(queue)) {
pthread_cond_wait(&queue->not_full, &queue->lock);
}
queue->rear = (queue->rear + 1) % queue->size;
queue->data[queue->rear] = item;
queue->count++;
pthread_mutex_unlock(&queue->lock);
pthread_cond_signal(&queue->not_empty);
}
char* dequeue(YuvQueue* queue) {
pthread_mutex_lock(&queue->lock);
while (is_empty(queue)) {
pthread_cond_wait(&queue->not_empty, &queue->lock);
}
char* item = queue->data[queue->front];
queue->front = (queue->front + 1) % queue->size;
queue->count--;
pthread_mutex_unlock(&queue->lock);
pthread_cond_signal(&queue->not_full);
return item;
}
void* read_thread(void* arg) {
YuvQueue* queue = (YuvQueue*)arg;
int read_count = 0;
while (read_count < YUV_FILE_COUNT) {
if (!is_full(queue)) {
char* filename = (char*)malloc(sizeof(char) * 100);
sprintf(filename, "yuv_%d.yuv", read_count);
enqueue(queue, filename);
read_count++;
}
}
pthread_cond_signal(&queue->not_empty);
return NULL;
}
void* encode_thread(void* arg) {
YuvQueue* queue = (YuvQueue*)arg;
char* filename;
struct timeval tv;
while (1) {
filename = dequeue(queue);
if (filename == NULL) {
break;
}
gettimeofday(&tv, NULL);
char* jpeg_filename = (char*)malloc(sizeof(char) * 100);
sprintf(jpeg_filename, "%d.jpeg", (int)tv.tv_usec);
FILE* fp = fopen(jpeg_filename, "wb");
if (fp == NULL) {
printf("Failed to open file %s\n", jpeg_filename);
break;
}
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
JSAMPROW row_pointer[1];
int image_height = 720;
int image_width = 1280;
unsigned char* yuv_buffer = (unsigned char*)malloc(sizeof(unsigned char) * image_width * image_height * 3 / 2);
unsigned char* jpeg_buffer = NULL;
memset(yuv_buffer, 0, sizeof(unsigned char) * image_width * image_height * 3 / 2);
memset(&cinfo, 0, sizeof(cinfo));
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
jpeg_stdio_dest(&cinfo, fp);
cinfo.image_width = image_width;
cinfo.image_height = image_height;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_YCbCr;
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, 80, TRUE);
jpeg_start_compress(&cinfo, TRUE);
int y_size = image_width * image_height;
int u_size = y_size / 4;
int v_size = u_size;
unsigned char* y = yuv_buffer;
unsigned char* u = y + y_size;
unsigned char* v = u + u_size;
FILE* yuv_fp = fopen(filename, "rb");
fread(y, 1, y_size, yuv_fp);
fread(u, 1, u_size, yuv_fp);
fread(v, 1, v_size, yuv_fp);
fclose(yuv_fp);
for (int row = 0; row < image_height; row++) {
row_pointer[0] = &yuv_buffer[row * image_width];
jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
fclose(fp);
free(jpeg_buffer);
free(jpeg_filename);
free(yuv_buffer);
free(filename);
}
return NULL;
}
int main() {
YuvQueue* queue = create_queue(YUV_QUEUE_SIZE);
pthread_t read_tid, encode_tid;
pthread_create(&read_tid, NULL, read_thread, queue);
pthread_create(&encode_tid, NULL, encode_thread, queue);
pthread_join(read_tid, NULL);
pthread_join(encode_tid, NULL);
destroy_queue(queue);
return 0;
}
```
使用Makefile进行编译和链接:
```makefile
CC = gcc
CFLAGS = -Wall -Werror -pthread
LIBS = -ljpeg
all: yuv2jpeg
yuv2jpeg: yuv2jpeg.o
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
yuv2jpeg.o: yuv2jpeg.c
$(CC) $(CFLAGS) -c $<
clean:
rm -f *.o yuv2jpeg
```
在终端中进入代码所在的文件夹,运行以下命令:
```
make
./yuv2jpeg
```
即可运行程序。