在liunx系统下用C语言写一个视频播放器的代码
时间: 2024-01-22 10:19:09 浏览: 117
视频播放器是一个比较复杂的应用程序,需要使用多个库和工具来实现。以下是一个简单的视频播放器的示例代码,使用了FFmpeg和SDL库,可以在Linux系统下使用。
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <SDL2/SDL.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#define SDL_AUDIO_BUFFER_SIZE 1024
#define MAX_AUDIO_FRAME_SIZE 192000
static Uint8 *audio_buffer;
static Uint32 audio_len;
static Uint8 *audio_pos;
static void audio_callback(void *userdata, Uint8 *stream, int len) {
if (audio_len == 0)
return;
len = (len > audio_len ? audio_len : len);
memcpy(stream, audio_pos, len);
audio_pos += len;
audio_len -= len;
}
int main(int argc, char **argv) {
if (argc < 2) {
fprintf(stderr, "Usage: %s <input_file>\n", argv[0]);
return 1;
}
const char *filename = argv[1];
AVFormatContext *pFormatCtx = NULL;
if (avformat_open_input(&pFormatCtx, filename, NULL, NULL) != 0) {
fprintf(stderr, "Error: Couldn't open file '%s'\n", filename);
return 1;
}
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
fprintf(stderr, "Error: Couldn't find stream information\n");
return 1;
}
int audio_stream_idx = -1;
for (int i = 0; i < pFormatCtx->nb_streams; i++) {
if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
audio_stream_idx = i;
break;
}
}
if (audio_stream_idx == -1) {
fprintf(stderr, "Error: Couldn't find audio stream\n");
return 1;
}
AVCodecParameters *audio_codecpar = pFormatCtx->streams[audio_stream_idx]->codecpar;
AVCodec *audio_codec = avcodec_find_decoder(audio_codecpar->codec_id);
if (!audio_codec) {
fprintf(stderr, "Error: Couldn't find audio decoder\n");
return 1;
}
AVCodecContext *audio_ctx = avcodec_alloc_context3(audio_codec);
if (avcodec_parameters_to_context(audio_ctx, audio_codecpar) < 0) {
fprintf(stderr, "Error: Couldn't copy audio codec parameters to context\n");
return 1;
}
if (avcodec_open2(audio_ctx, audio_codec, NULL) < 0) {
fprintf(stderr, "Error: Couldn't open audio codec\n");
return 1;
}
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
AVFrame *audio_frame = av_frame_alloc();
SwrContext *swr_ctx = swr_alloc();
av_opt_set_channel_layout(swr_ctx, "in_channel_layout", audio_codecpar->channel_layout, 0);
av_opt_set_channel_layout(swr_ctx, "out_channel_layout", audio_ctx->channel_layout, 0);
av_opt_set_int(swr_ctx, "in_sample_rate", audio_codecpar->sample_rate, 0);
av_opt_set_int(swr_ctx, "out_sample_rate", audio_ctx->sample_rate, 0);
av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", audio_codecpar->format, 0);
av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", audio_ctx->sample_fmt, 0);
swr_init(swr_ctx);
SDL_AudioSpec wanted_spec, spec;
wanted_spec.freq = audio_ctx->sample_rate;
wanted_spec.format = AUDIO_S16SYS;
wanted_spec.channels = audio_ctx->channels;
wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
wanted_spec.callback = audio_callback;
wanted_spec.userdata = NULL;
if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
fprintf(stderr, "Error: Couldn't open SDL audio\n");
return 1;
}
av_dump_format(pFormatCtx, 0, filename, 0);
AVPacket packet;
int frame_finished;
while (av_read_frame(pFormatCtx, &packet) >= 0) {
if (packet.stream_index == audio_stream_idx) {
int ret = avcodec_send_packet(audio_ctx, &packet);
if (ret < 0) {
fprintf(stderr, "Error: Couldn't send packet for decoding\n");
continue;
}
while (ret >= 0) {
ret = avcodec_receive_frame(audio_ctx, audio_frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
break;
else if (ret < 0) {
fprintf(stderr, "Error: Couldn't decode frame\n");
continue;
}
int dst_nb_samples = av_rescale_rnd(
swr_get_delay(swr_ctx, audio_ctx->sample_rate) + audio_frame->nb_samples,
audio_ctx->sample_rate, audio_ctx->sample_rate, AV_ROUND_UP);
int nb_channels = av_get_channel_layout_nb_channels(audio_ctx->channel_layout);
int data_size = av_samples_get_buffer_size(
NULL, nb_channels, dst_nb_samples, audio_ctx->sample_fmt, 1);
uint8_t *dst_data = NULL;
av_samples_alloc(&dst_data, NULL, nb_channels, dst_nb_samples, audio_ctx->sample_fmt, 1);
swr_convert(swr_ctx, &dst_data, dst_nb_samples, (const uint8_t **)audio_frame->data, audio_frame->nb_samples);
audio_buffer = dst_data;
audio_len = data_size;
audio_pos = audio_buffer;
SDL_PauseAudio(0);
}
}
av_packet_unref(&packet);
}
av_frame_free(&audio_frame);
avcodec_free_context(&audio_ctx);
avformat_close_input(&pFormatCtx);
swr_free(&swr_ctx);
SDL_CloseAudio();
SDL_Quit();
return 0;
}
```
这个示例程序使用了SDL库来播放音频,通过FFmpeg库解码音频数据。在播放音频之前,需要对音频进行重采样,以便与SDL的音频设备兼容。
阅读全文