From ae14c862d2a3a4ce38c6fbc6ae317b56f8ff4d92 Mon Sep 17 00:00:00 2001 From: Mistivia Date: Sat, 13 Sep 2025 14:07:15 +0800 Subject: fix output stream index bug --- Makefile | 2 +- ringbuf.c | 2 +- transmuxer.c | 48 ++++++++++++++++++++++++++---------------------- 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/Makefile b/Makefile index 2f2ab2f..a454c34 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ CC := gcc CXX := g++ CFLAGS := -g -Wall CXXFLAGS := -g -Wall -std=c++14 -LDFLAGS := -lavformat -lavutil -lavcodec +LDFLAGS := -g -lavformat -lavutil -lavcodec C_SOURCES := $(shell find . -maxdepth 1 -name '*.c') CPP_SOURCES := $(shell find . -maxdepth 1 -name '*.cpp') diff --git a/ringbuf.c b/ringbuf.c index 876e590..29301e5 100644 --- a/ringbuf.c +++ b/ringbuf.c @@ -81,7 +81,7 @@ size_t RingBuffer_read(RingBuffer *self, uint8_t *data, size_t len) { pthread_mutex_lock(&self->mutex); while (read < len) { - while (RingBuffer_space(self) == 0) { + while (RingBuffer_size(self) == 0) { if (self->finished_flag) { goto end; } diff --git a/transmuxer.c b/transmuxer.c index 4c0f993..e2f60fc 100644 --- a/transmuxer.c +++ b/transmuxer.c @@ -25,27 +25,30 @@ typedef struct { AVStream *video_stream; } StreamPair; +#define OUT_VIDEO_STREAM_INDEX 0 +#define OUT_AUDIO_STREAM_INDEX 1 + static StreamPair start_new_output_file( AVFormatContext *in_fmt_ctx, - AVFormatContext *out_fmt_ctx, + AVFormatContext **out_fmt_ctx, const char *out_filename, int aidx, int vidx) { - avformat_alloc_output_context2(&out_fmt_ctx, NULL, "mpegts", out_filename); + avformat_alloc_output_context2(out_fmt_ctx, NULL, "mpegts", out_filename); - AVStream *out_video_stream = avformat_new_stream(out_fmt_ctx, NULL); - AVStream *out_audio_stream = avformat_new_stream(out_fmt_ctx, NULL); + AVStream *out_video_stream = avformat_new_stream(*out_fmt_ctx, NULL); + AVStream *out_audio_stream = avformat_new_stream(*out_fmt_ctx, NULL); avcodec_parameters_copy(out_video_stream->codecpar, in_fmt_ctx->streams[vidx]->codecpar); avcodec_parameters_copy(out_audio_stream->codecpar, in_fmt_ctx->streams[aidx]->codecpar); - if (!(out_fmt_ctx->oformat->flags & AVFMT_NOFILE)) { - if (avio_open(&out_fmt_ctx->pb, out_filename, AVIO_FLAG_WRITE) < 0) { + if (!((*out_fmt_ctx)->oformat->flags & AVFMT_NOFILE)) { + if (avio_open(&(*out_fmt_ctx)->pb, out_filename, AVIO_FLAG_WRITE) < 0) { fprintf(stderr, "Could not open output file '%s'\n", out_filename); exit(-1); } } - if (avformat_write_header(out_fmt_ctx, NULL) < 0) { + if (avformat_write_header(*out_fmt_ctx, NULL) < 0) { fprintf(stderr, "avformat_write_header failed.\n"); abort(); } @@ -57,8 +60,10 @@ static StreamPair start_new_output_file( static int RingBuffer_avio_read(void *ctx, uint8_t *buf, int buf_size) { RingBuffer *rb = ctx; - if (rb->finished_flag) return AVERROR_EOF; size_t n = RingBuffer_read(rb, buf, buf_size); + if (n == 0 && buf_size > 0) { + return AVERROR_EOF; + } return (int)n; } @@ -66,12 +71,11 @@ AVIOContext* create_avio_from_ringbuffer(RingBuffer *rb, int buffer_size) { uint8_t *avio_buf = av_malloc(buffer_size); AVIOContext *avio = avio_alloc_context( avio_buf, buffer_size, - 0, // write_flag=0 => read only + 0, rb, - RingBuffer_avio_read, // read - NULL, // write - NULL // seek - ); + RingBuffer_avio_read, + NULL, + NULL); return avio; } @@ -90,9 +94,10 @@ void* Transmuxer_main (void *vself) { Transmuxer *self = vself; pthread_mutex_lock(&self->lock); while (wait_for_new_stream(self)) { - AVFormatContext *in_fmt_ctx = NULL; + AVFormatContext *in_fmt_ctx = avformat_alloc_context(); in_fmt_ctx->pb = create_avio_from_ringbuffer(self->stream, 4096); - if (avformat_open_input(&in_fmt_ctx, NULL, NULL, NULL) < 0) { + const AVInputFormat *flv_fmt = av_find_input_format("flv"); + if (avformat_open_input(&in_fmt_ctx, NULL, flv_fmt, NULL) < 0) { fprintf(stderr, "Could not open input file\n"); abort(); } @@ -129,16 +134,15 @@ void* Transmuxer_main (void *vself) { int64_t pts_time; AVPacket pkt; - StreamPair output_stream; - - output_stream = start_new_output_file(in_fmt_ctx, out_fmt_ctx, out_filename, audio_stream_index, video_stream_index); + StreamPair output_stream = start_new_output_file( + in_fmt_ctx, &out_fmt_ctx, out_filename, audio_stream_index, video_stream_index); while (av_read_frame(in_fmt_ctx, &pkt) >= 0) { AVStream *in_stream = in_fmt_ctx->streams[pkt.stream_index]; AVStream *out_stream = NULL; if (pkt.stream_index == video_stream_index) out_stream = output_stream.video_stream; else if (pkt.stream_index == audio_stream_index) - out_stream = output_stream.video_stream; + out_stream = output_stream.audio_stream; else { av_packet_unref(&pkt); continue; @@ -157,21 +161,21 @@ void* Transmuxer_main (void *vself) { segment_index++; segment_start_pts = pts_time; snprintf(out_filename, sizeof(out_filename), "segment_%03d.ts", segment_index); - start_new_output_file(in_fmt_ctx, out_fmt_ctx, out_filename, audio_stream_index, video_stream_index); + output_stream = start_new_output_file(in_fmt_ctx, &out_fmt_ctx, out_filename, audio_stream_index, video_stream_index); } } pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base); pkt.pos = -1; - pkt.stream_index = (pkt.stream_index == video_stream_index) ? output_stream.video_stream->index : output_stream.audio_stream->index; + pkt.stream_index = (pkt.stream_index == audio_stream_index) ? OUT_AUDIO_STREAM_INDEX : OUT_VIDEO_STREAM_INDEX; av_interleaved_write_frame(out_fmt_ctx, &pkt); av_packet_unref(&pkt); } printf("new ts: %ld\n", pts_time - segment_start_pts); finalize_output_file(out_fmt_ctx); - + av_free(in_fmt_ctx->pb->buffer); avio_context_free(&in_fmt_ctx->pb); avformat_close_input(&in_fmt_ctx); -- cgit v1.0