diff --git a/transcode.c b/transcode.c index f5b9f672eb21eb3a7f0ea2de201ba2eb6a80e249..b7994b8047185335721ab476b5d84c9d43fd1610 100644 --- a/transcode.c +++ b/transcode.c @@ -77,7 +77,7 @@ static void setup_input_stream(char *stream, AVFormatContext *demux, p = mprintf("time_base=%d/%d:sample_rate=%d:sample_fmt=%d:channel_layout=%s:channels=%d", demux->streams[idx]->time_base.num, demux->streams[idx]->time_base.den, decs[idx]->sample_rate, decs[idx]->sample_fmt, ch_layout, - decs[idx]->channels); + decs[idx]->ch_layout.nb_channels); err = avfilter_graph_create_filter(&srcs[idx], avfilter_get_by_name("abuffer"), 0, p, 0, fg); if (err < 0) @@ -135,8 +135,16 @@ static void prepare_output_stream(char *stream, AVStream *st, AV_SAMPLE_FMT_NONE, AV_OPT_SEARCH_CHILDREN); av_opt_set_int_list(sinks[idx], "sample_rates", encs[idx]->codec->supported_samplerates, 0, AV_OPT_SEARCH_CHILDREN); - av_opt_set_int_list(sinks[idx], "channel_layouts", - encs[idx]->codec->channel_layouts, 0, AV_OPT_SEARCH_CHILDREN); + + // find length of ch_layouts + int ch_layouts_len = 0; + for (int i = 0; encs[idx]->codec->ch_layouts && encs[idx]->codec->ch_layouts[i].nb_channels; i++) + ch_layouts_len++; + + if (ch_layouts_len > 0) { + av_opt_set_bin(sinks[idx], "ch_layouts", (const uint8_t *) encs[idx]->codec->ch_layouts, ch_layouts_len, AV_OPT_SEARCH_CHILDREN); + } + // not setting ch_layouts equals to setting all possible layouts } else job_failed("Requested codec has unsupported type\n"); @@ -174,8 +182,8 @@ static void setup_output_stream(char *stream, AVStream *st, AVCodecContext *enc, else if (enc->codec_type == AVMEDIA_TYPE_AUDIO) { enc->sample_rate = av_buffersink_get_sample_rate(sink); - enc->channel_layout = av_buffersink_get_channel_layout(sink); - enc->channels = av_buffersink_get_channels(sink); + if((err = av_buffersink_get_ch_layout(sink, &enc->ch_layout)) < 0) + job_failed("Could not get channel layout: %s", av_err2str(err)); enc->sample_fmt = av_buffersink_get_format(sink); } enc->time_base = av_buffersink_get_time_base(sink); @@ -193,18 +201,16 @@ static void setup_output_stream(char *stream, AVStream *st, AVCodecContext *enc, static void flush_encoder(AVFormatContext *mux, AVFilterContext *sink, AVCodecContext *enc, int idx) { int err; - AVPacket pkt; - pkt.data = 0; - pkt.size = 0; - av_init_packet(&pkt); - while (!avcodec_receive_packet(enc, &pkt)) + AVPacket* pkt = av_packet_alloc(); + while (!avcodec_receive_packet(enc, pkt)) { - pkt.stream_index = idx; - av_packet_rescale_ts(&pkt, enc->time_base, + pkt->stream_index = idx; + av_packet_rescale_ts(pkt, enc->time_base, mux->streams[idx]->time_base); - if (err = av_interleaved_write_frame(mux, &pkt)) + if (err = av_interleaved_write_frame(mux, pkt)) job_failed("Could not write frame: %s", av_err2str(err)); } + av_packet_free(&pkt); } static void flush_filtergraph(AVFormatContext *mux, AVFilterContext **sinks, AVCodecContext **encs) @@ -267,7 +273,7 @@ int main(int argc, char *argv[]) AVFilterContext **srcs, **sinks; AVFilterGraph *fg; AVFilterInOut *inpads, *outpads; - AVPacket pkt; + AVPacket* pkt; AVStream *stream; AVDictionary *opts; if (argc != 5) @@ -275,9 +281,6 @@ int main(int argc, char *argv[]) init_env(); umask(S_IWOTH); init_avlogbuf(); - pkt.data = 0; - pkt.size = 0; - av_init_packet(&pkt); if (!(fg = avfilter_graph_alloc())) return 99; @@ -343,10 +346,11 @@ int main(int argc, char *argv[]) progress = 0; ping_job(jobid, "running", 0); - while (!av_read_frame(demux, &pkt)) + pkt = av_packet_alloc(); + while (!av_read_frame(demux, pkt)) { - i = pkt.stream_index; - _progress = av_rescale_q(pkt.pts, demux->streams[i]->time_base, AV_TIME_BASE_Q)*100/demux->duration; + i = pkt->stream_index; + _progress = av_rescale_q(pkt->pts, demux->streams[i]->time_base, AV_TIME_BASE_Q)*100/demux->duration; if (_progress > progress || !checktime(30)) { canceled = ping_job(jobid, "running", "{\"progress\": %i, \"log\": \"%s\"}", _progress, @@ -355,9 +359,11 @@ int main(int argc, char *argv[]) job_failed("Job canceled"); progress = _progress; } - filtergraph_send(srcs[i], decs[i], &pkt); + filtergraph_send(srcs[i], decs[i], pkt); flush_filtergraph(mux, sinks, encs); + av_packet_unref(pkt); } + av_packet_free(&pkt); /* Flush */ for (i = 0; i < demux->nb_streams; i ++)