一份ffmpeg异步解码的代码
时间: 2023-04-06 11:04:57 浏览: 121
ffmpeg视频解码示例代码
我可以回答这个问题。以下是一份ffmpeg异步解码的代码示例:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#define MAX_AUDIO_FRAME_SIZE 192000
typedef struct PacketQueue {
AVPacketList *first_pkt, *last_pkt;
int nb_packets;
int size;
pthread_mutex_t mutex;
pthread_cond_t cond;
} PacketQueue;
PacketQueue audioq;
int quit = 0;
void packet_queue_init(PacketQueue *q) {
memset(q, 0, sizeof(PacketQueue));
pthread_mutex_init(&q->mutex, NULL);
pthread_cond_init(&q->cond, NULL);
}
int packet_queue_put(PacketQueue *q, AVPacket *pkt) {
AVPacketList *pkt1;
if (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;
pthread_cond_signal(&q->cond);
pthread_mutex_unlock(&q->mutex);
return 0;
}
int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block) {
AVPacketList *pkt1;
int ret;
pthread_mutex_lock(&q->mutex);
for (;;) {
if (quit) {
ret = -1;
break;
}
pkt1 = q->first_pkt;
if (pkt1) {
q->first_pkt = pkt1->next;
if (!q->first_pkt) {
q->last_pkt = NULL;
}
q->nb_packets--;
q->size -= pkt1->pkt.size;
*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;
}
void* audio_decode_thread(void* arg) {
AVCodecContext *codec_ctx = (AVCodecContext*)arg;
AVPacket pkt;
AVFrame *frame = av_frame_alloc();
uint8_t *out_buf = (uint8_t*)av_malloc(MAX_AUDIO_FRAME_SIZE);
int out_buf_size = MAX_AUDIO_FRAME_SIZE;
int out_buf_index = 0;
int ret;
while (!quit) {
ret = packet_queue_get(&audioq, &pkt, 1);
if (ret < 0) {
break;
}
if (pkt.stream_index == codec_ctx->audio_stream_index) {
ret = avcodec_send_packet(codec_ctx, &pkt);
if (ret < 0) {
break;
}
while (ret >= 0) {
ret = avcodec_receive_frame(codec_ctx, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
break;
} else if (ret < 0) {
break;
}
int data_size = av_samples_get_buffer_size(NULL, codec_ctx->channels, frame->nb_samples, codec_ctx->sample_fmt, 1);
if (out_buf_index + data_size > out_buf_size) {
out_buf_size = out_buf_index + data_size;
out_buf = (uint8_t*)av_realloc(out_buf, out_buf_size);
}
memcpy(out_buf + out_buf_index, frame->data[0], data_size);
out_buf_index += data_size;
}
}
av_packet_unref(&pkt);
}
av_frame_free(&frame);
av_free(out_buf);
pthread_exit(NULL);
}
int main(int argc, char* argv[]) {
AVFormatContext *fmt_ctx = NULL;
AVCodecContext *audio_codec_ctx = NULL;
AVCodec *audio_codec = NULL;
AVPacket pkt;
int audio_stream_index = -1;
int ret;
if (argc < 2) {
fprintf(stderr, "Usage: %s <input file>\n", argv[0]);
exit(1);
}
av_register_all();
avformat_network_init();
if (avformat_open_input(&fmt_ctx, argv[1], NULL, NULL) < 0) {
fprintf(stderr, "Could not open input file '%s'\n", argv[1]);
exit(1);
}
if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
fprintf(stderr, "Could not find stream information\n");
exit(1);
}
av_dump_format(fmt_ctx, 0, argv[1], 0);
for (int i = 0; i < fmt_ctx->nb_streams; i++) {
if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
audio_stream_index = i;
break;
}
}
if (audio_stream_index == -1) {
fprintf(stderr, "Could not find audio stream\n");
exit(1);
}
audio_codec_ctx = avcodec_alloc_context3(NULL);
if (!audio_codec_ctx) {
fprintf(stderr, "Could not allocate audio codec context\n");
exit(1);
}
ret = avcodec_parameters_to_context(audio_codec_ctx, fmt_ctx->streams[audio_stream_index]->codecpar);
if (ret < 0) {
fprintf(stderr, "Could not copy audio codec parameters to context\n");
exit(1);
}
audio_codec = avcodec_find_decoder(audio_codec_ctx->codec_id);
if (!audio_codec) {
fprintf(stderr, "Could not find audio codec\n");
exit(1);
}
if (avcodec_open2(audio_codec_ctx, audio_codec, NULL) < 0) {
fprintf(stderr, "Could not open audio codec\n");
exit(1);
}
audioq.nb_packets = 0;
audioq.size = 0;
packet_queue_init(&audioq);
pthread_t audio_tid;
pthread_create(&audio_tid, NULL, audio_decode_thread, audio_codec_ctx);
while (av_read_frame(fmt_ctx, &pkt) >= 0) {
if (pkt.stream_index == audio_stream_index) {
packet_queue_put(&audioq, &pkt);
} else {
av_packet_unref(&pkt);
}
}
quit = 1;
pthread_join(audio_tid, NULL);
avcodec_free_context(&audio_codec_ctx);
avformat_close_input(&fmt_ctx);
avformat_network_deinit();
return 0;
}
```
希望对你有所帮助!
阅读全文