ffmpeg - Muxing with libav -


i have program supposed demux input mpeg-ts, transcode mpeg2 h264 , mux audio alongside transcoded video. when open resulting muxed file vlc neither audio nor video. here relevant code.

my main worker loop follows:

void *writer_thread(void *thread_ctx) {      struct transcoder_ctx_t *ctx = (struct transcoder_ctx_t *) thread_ctx;     avstream *video_stream = null, *audio_stream = null;     avformatcontext *output_context = init_output_context(ctx, &video_stream, &audio_stream);     struct mux_state_t mux_state = {0};      //from omxtx     mux_state.pts_offset = av_rescale_q(ctx->input_context->start_time, av_time_base_q, output_context->streams[ctx->video_stream_index]->time_base);      //write stream header if     avformat_write_header(output_context, null);      //do not start doing until encoded packet     pthread_mutex_lock(&ctx->pipeline.video_encode.is_running_mutex);     while (!ctx->pipeline.video_encode.is_running) {         pthread_cond_wait(&ctx->pipeline.video_encode.is_running_cv, &ctx->pipeline.video_encode.is_running_mutex);     }      while (!ctx->pipeline.video_encode.eos || !ctx->processed_audio_queue->queue_finished) {         //fixme memory barrier required here don't race          //on above variables           //fill buffer video data          oerr(omx_fillthisbuffer(ctx->pipeline.video_encode.h, omx_get_next_output_buffer(&ctx->pipeline.video_encode)));          write_audio_frame(output_context, audio_stream, ctx); //write full audio frame          //fixme no guarantee have full frame per packet?         write_video_frame(output_context, video_stream, ctx, &mux_state); //write full video frame         //encoded_video_queue being filled previous command      }      av_write_trailer(output_context);      //free resources     avcodec_close(video_stream->codec);     avcodec_close(audio_stream->codec);     /* free streams. */     (int = 0; < output_context->nb_streams; i++) {         av_freep(&output_context->streams[i]->codec);         av_freep(&output_context->streams[i]);     }      if (!(output_context->oformat->flags & avfmt_nofile)) {         /* close output file. */         avio_close(output_context->pb);     }       /* free stream */     av_free(output_context);     free(mux_state.pps);     free(mux_state.sps); } 

the code initialising libav output context this:

static  avformatcontext * init_output_context(const struct transcoder_ctx_t *ctx, avstream **video_stream, avstream **audio_stream) {     avformatcontext *oc;     avoutputformat *fmt;     avstream *input_stream, *output_stream;     avcodec *c;     avcodeccontext *cc;     int audio_copied = 0; //copy 1 stream      fmt = av_guess_format("mpegts", null, null);     if (!fmt) {         fprintf(stderr, "[debug] error guessing format, dying\n");         exit(199);     }      oc = avformat_alloc_context();     if (!oc) {         fprintf(stderr, "[debug] error allocating context, dying\n");         exit(200);     }      oc->oformat = fmt;     snprintf(oc->filename, sizeof(oc->filename), "%s", ctx->output_filename);     oc->debug = 1;     oc->start_time_realtime = ctx->input_context->start_time;     oc->start_time = ctx->input_context->start_time;     oc->duration = 0;     oc->bit_rate = 0;      (int = 0; < ctx->input_context->nb_streams; i++) {         input_stream = ctx->input_context->streams[i];         output_stream = null;         if (input_stream->index == ctx->video_stream_index) {             //copy stuff input video index             c = avcodec_find_encoder(codec_id_h264);             output_stream = avformat_new_stream(oc, c);             *video_stream = output_stream;             cc = output_stream->codec;             cc->width = input_stream->codec->width;             cc->height = input_stream->codec->height;             cc->codec_id = codec_id_h264;             cc->codec_type = avmedia_type_video;             cc->bit_rate = encoded_bitrate;             cc->time_base = input_stream->codec->time_base;              output_stream->avg_frame_rate = input_stream->avg_frame_rate;             output_stream->r_frame_rate = input_stream->r_frame_rate;             output_stream->start_time = av_nopts_value;          } else if ((input_stream->codec->codec_type == avmedia_type_audio) && !audio_copied)  {              /* care audio */             c = avcodec_find_encoder(input_stream->codec->codec_id);             output_stream = avformat_new_stream(oc, c);             *audio_stream = output_stream;             avcodec_copy_context(output_stream->codec, input_stream->codec);             /* apparently fixes crash on .mkvs attachments: */             av_dict_copy(&output_stream->metadata, input_stream->metadata, 0);             /* reset codec tag not cause problems output format */             output_stream->codec->codec_tag = 0;             audio_copied = 1;         }     }      (int = 0; < oc->nb_streams; i++) {         if (oc->oformat->flags & avfmt_globalheader)             oc->streams[i]->codec->flags |= codec_flag_global_header;         if (oc->streams[i]->codec->sample_rate == 0)             oc->streams[i]->codec->sample_rate = 48000; /* ish */     }      if (!(fmt->flags & avfmt_nofile)) {         fprintf(stderr, "[debug] avfmt_nofile set, allocating output container\n");         if (avio_open(&oc->pb, ctx->output_filename, avio_flag_write) < 0) {             fprintf(stderr, "[debug] error creating output context\n");             exit(1);         }     }      return oc; } 

finally code writing audio:

static void write_audio_frame(avformatcontext *oc, avstream *st, struct transcoder_ctx_t *ctx) {     avpacket pkt = {0}; // data , size must 0;     struct packet_t *source_audio;     av_init_packet(&pkt);      if (!(source_audio = packet_queue_get_next_item_asynch(ctx->processed_audio_queue))) {         return;     }      pkt.stream_index = st->index;     pkt.size = source_audio->data_length;     pkt.data = source_audio->data;     pkt.pts = source_audio->pts;     pkt.dts = source_audio->dts;     pkt.duration = source_audio->duration;     pkt.destruct = avpacket_destruct;     /* write compressed frame media file. */     if (av_interleaved_write_frame(oc, &pkt) != 0) {         fprintf(stderr, "[debug] error while writing audio frame\n");     }      packet_queue_free_packet(source_audio, 0); } 

a resulting mpeg4 file can obtained here: http://87.120.131.41/dl/mpeg4.h264

i have ommited write_video_frame code since lot more complicated , might making wrong there i'm doing timebase conversation etc. audio i'm doing 1:1 copy. each packet_t packet contains data av_read_frame input mpegts container. in worst case i'd expect audio working , not video. cannot either of work. seems documentation rather vague on making things - i've tried both libav , ffmpeg irc channels no avail. information regarding how can debug issue appreciated.

when different containers yield different results in libav timebase issue. containers have time_base like, , accept custom values... sometimes.

you must rescale time base before putting in container. tinkering mux state struct isn't want , think did there doesn't think. try printing out of timebases find out are.

each frame must recalculate pts @ least. if before call encode encoder produce proper dts. same audio, set dts av_no_pts , can away setting audio pts well. rescale use av_rescale(...) functions.

be careful assuming have mpeg-2 data in mpeg-ts container, not true.


Comments

Popular posts from this blog

Ansible - ERROR! the field 'hosts' is required but was not set -

customize file_field button ruby on rails -

SoapUI on windows 10 - high DPI/4K scaling issue -