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 12:02:08 浏览: 59
好的,下面是程序实现及Makefile文件:
```c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/time.h>
#include <unistd.h>
#include <semaphore.h>
#include <jpeglib.h>
#define MAX_QUEUE_SIZE 5
#define MAX_IMG_COUNT 10
typedef struct {
unsigned char* buffer;
size_t size;
} YuvData;
typedef struct {
YuvData data[MAX_QUEUE_SIZE];
int head;
int tail;
sem_t empty;
sem_t full;
pthread_mutex_t mutex;
} YuvQueue;
int encodeJPEG(unsigned char* yuvData, int width, int height, int quality, char* filename) {
struct timeval tv;
gettimeofday(&tv, NULL);
char jpegFilename[128];
sprintf(jpegFilename, "%ld.jpeg", tv.tv_usec / 1000 + tv.tv_sec * 1000);
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE* fptr;
JSAMPROW row_pointer[1];
int row_stride;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
if ((fptr = fopen(jpegFilename, "wb")) == NULL) {
fprintf(stderr, "Error opening file %s\n", jpegFilename);
return -1;
}
jpeg_stdio_dest(&cinfo, fptr);
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_YCbCr;
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, quality, TRUE);
jpeg_start_compress(&cinfo, TRUE);
row_stride = width * 3;
while (cinfo.next_scanline < cinfo.image_height) {
row_pointer[0] = &yuvData[cinfo.next_scanline * row_stride];
jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
jpeg_finish_compress(&cinfo);
fclose(fptr);
jpeg_destroy_compress(&cinfo);
return 0;
}
void* threadA(void* arg) {
YuvQueue* queue = (YuvQueue*)arg;
int imgCount = 0;
while (imgCount < MAX_IMG_COUNT) {
sem_wait(&queue->empty);
pthread_mutex_lock(&queue->mutex);
if (queue->tail < MAX_QUEUE_SIZE) {
YuvData* data = &queue->data[queue->tail];
char filename[32];
sprintf(filename, "yuv%d.yuv", imgCount);
FILE* fptr = fopen(filename, "rb");
fseek(fptr, 0, SEEK_END);
long size = ftell(fptr);
fseek(fptr, 0, SEEK_SET);
data->buffer = malloc(size);
data->size = fread(data->buffer, 1, size, fptr);
fclose(fptr);
queue->tail++;
imgCount++;
}
pthread_mutex_unlock(&queue->mutex);
sem_post(&queue->full);
if (queue->tail == MAX_QUEUE_SIZE) {
break;
}
}
printf("Thread A finished reading %d images.\n", imgCount);
sem_post(&queue->full);
return NULL;
}
void* threadB(void* arg) {
YuvQueue* queue = (YuvQueue*)arg;
while (1) {
sem_wait(&queue->full);
pthread_mutex_lock(&queue->mutex);
if (queue->head == queue->tail) {
pthread_mutex_unlock(&queue->mutex);
break;
}
YuvData* data = &queue->data[queue->head];
queue->head++;
pthread_mutex_unlock(&queue->mutex);
sem_post(&queue->empty);
int width = 1280;
int height = 720;
int quality = 90;
unsigned char* yuvData = data->buffer;
printf("Encoding image %d ...\n", queue->head);
encodeJPEG(yuvData, width, height, quality, NULL);
free(yuvData);
}
printf("Thread B finished encoding images.\n");
return NULL;
}
int main() {
YuvQueue queue;
queue.head = 0;
queue.tail = 0;
sem_init(&queue.empty, 0, MAX_QUEUE_SIZE);
sem_init(&queue.full, 0, 0);
pthread_mutex_init(&queue.mutex, NULL);
pthread_t threadIdA, threadIdB;
pthread_create(&threadIdA, NULL, threadA, &queue);
pthread_create(&threadIdB, NULL, threadB, &queue);
pthread_join(threadIdA, NULL);
pthread_join(threadIdB, NULL);
sem_destroy(&queue.empty);
sem_destroy(&queue.full);
pthread_mutex_destroy(&queue.mutex);
return 0;
}
```
Makefile文件如下:
```makefile
CC = gcc
CFLAGS = -Wall -Wextra -Werror -std=c99 -pedantic -pthread
all: yuv2jpeg
yuv2jpeg: yuv2jpeg.c
$(CC) $(CFLAGS) $< -o $@
clean:
rm -f yuv2jpeg *.jpeg
```
编译命令为:
```
make
```
运行命令为:
```
./yuv2jpeg
```
阅读全文