- #include <stdio.h>
- #include <stdlib.h>
- #include <libavcodec/avcodec.h>
- #include <libavformat/avformat.h>
- #include <libavutil/avutil.h>
- #include <alsa/asoundlib.h>
- int
- main(int argc, char *argv[])
- {
- if (argc < 2) {
- return 1;
- }
- snd_pcm_t *handle = NULL;
- if (snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0) < 0)
- goto end_playback;
- struct AVFormatContext *formatContext = NULL;
- if (avformat_open_input(&formatContext, argv[1], NULL, NULL) < 0)
- goto end_playback;
- if (avformat_find_stream_info(formatContext, NULL) < 0)
- goto end_playback;
- int streamId;
- if ((streamId = av_find_best_stream(formatContext, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0)) < 0)
- goto end_playback;
- const struct AVCodec *codec = avcodec_find_decoder(formatContext->streams[streamId]->codecpar->codec_id);
- if (!codec)
- goto end_playback;
- struct AVCodecContext *codecContext = avcodec_alloc_context3(codec);
- if (!codecContext)
- goto end_playback;
- if (avcodec_parameters_to_context(codecContext, formatContext->streams[streamId]->codecpar))
- goto end_playback;
- if (avcodec_open2(codecContext, codec, NULL) < 0)
- goto end_playback;
- snd_pcm_format_t alsaFormat;
- switch (codecContext->sample_fmt)
- {
- case AV_SAMPLE_FMT_S16P:
- case AV_SAMPLE_FMT_S16: alsaFormat = SND_PCM_FORMAT_S16_LE; break;
- case AV_SAMPLE_FMT_S32: alsaFormat = SND_PCM_FORMAT_S32_LE; break;
- case AV_SAMPLE_FMT_FLTP:
- case AV_SAMPLE_FMT_FLT: alsaFormat = SND_PCM_FORMAT_FLOAT_LE; break;
- case AV_SAMPLE_FMT_U8: alsaFormat = SND_PCM_FORMAT_U8; break;
- default:
- goto end_playback;
- }
- if (snd_pcm_set_params(handle,
- alsaFormat,
- SND_PCM_ACCESS_RW_INTERLEAVED,
- formatContext->streams[streamId]->codecpar->ch_layout.nb_channels,
- codecContext->sample_rate,
- 1, 500000) < 0)
- goto end_playback;
- AVPacket *packet = av_packet_alloc();
- AVFrame *frame = av_frame_alloc();
- if (!packet || !frame)
- goto end_playback;
- while (av_read_frame(formatContext, packet) >= 0) {
- if (packet->stream_index != streamId)
- continue;
- if (avcodec_send_packet(codecContext, packet) != 0) {
- av_packet_unref(packet);
- break;
- }
- while (!avcodec_receive_frame(codecContext, frame)) {
- uint8_t *audioData = NULL;
- uint8_t *audioDataPtr = NULL;
- int channels = formatContext->streams[streamId]->codecpar->ch_layout.nb_channels;
- int sampleSize = av_get_bytes_per_sample(frame->format);
- snd_pcm_sframes_t frames = frame->nb_samples;
- if (av_sample_fmt_is_planar(frame->format)) {
- float *dst = (float *)audioData;
- for (int i = 0; i < frame->nb_samples; i++) {
- for (int ch = 0; ch < channels; ch++) {
- float *src = (float *)frame->data[ch];
- dst[i * channels + ch] = src[i];
- }
- }
- audioDataPtr = audioData;
- } else {
- audioData = frame->data[0];
- audioDataPtr = audioData;
- }
- while (frames > 0) {
- snd_pcm_sframes_t written = snd_pcm_writei(handle, audioData, frames);
- if (written < 0) {
- if (written == -EAGAIN)
- continue;
- if (av_sample_fmt_is_planar(frame->format))
- goto end_playback;
- } else {
- frames -= written;
- audioDataPtr += written * sampleSize * channels;
- }
- if (written < 0 && written != -EAGAIN)
- goto end_playback;
- }
- if (av_sample_fmt_is_planar(frame->format))
- av_frame_unref(frame);
- }
- av_packet_unref(packet);
- }
- end_playback:
- if (packet)
- av_packet_free(&packet);
- if (frame)
- av_frame_free(&frame);
- if (codecContext)
- avcodec_free_context(&codecContext);
- if (formatContext)
- avformat_close_input(&formatContext);
- if (handle)
- snd_pcm_close(handle);
- return 0;
- }
ffmeow
Posted by Anonymous on Sat 16th Aug 2025 02:57
raw | new post
Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.