i have ffmpeg command
ffmpeg -i c:\input.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb c:\output.ts.
the above command converts input.mp4 output.ts.
i need implement same functionality via code (using ffmpeg library).
does know how copy 1 container without decoding , encoding?
if looking stream copy can quite easily. can refer following steps.
//1. initialization using av_register_all(); // 2. open input file using avformat_open_input( &m_informat, filename.c_str(), 0, 0)); //3. find input stream info. if ((ret = avformat_find_stream_info(m_informat, 0))< 0) { av_strerror(ret,errbuf,sizeof(errbuf)); print_val("not able find stream info:: ", errbuf) ret = -1; return ret; } (unsigned int = 0; i<m_informat->nb_streams; i++) { if(m_informat->streams[i]->codec->codec_type == avmedia_type_video) { print_msg("found video stream ") m_in_vid_strm_idx = i; m_in_vid_strm = m_informat->streams[i]; } if(m_informat->streams[i]->codec->codec_type == avmedia_type_audio) { m_in_aud_strm_idx = i; m_in_aud_strm = m_informat->streams[i]; } // 4. create ouputfile , allocate output format. avoutputformat *outfmt = null; std::string outfile = std::string(filename) + "clip_out.ts"; outfmt = av_guess_format(null,outfile.c_str(),null); if(outfmt == null) { ret = -1; return ret; } else { m_outformat = avformat_alloc_context(); if(m_outformat) { m_outformat->oformat = outfmt; _snprintf(m_outformat->filename, sizeof(m_outformat->filename), "%s", outfile.c_str()); } else { ret = -1; return ret; } } //5. add audio , video stream output format. avcodec *out_vid_codec,*out_aud_codec; out_vid_codec = out_aud_codec = null; if(outfmt->video_codec != av_codec_id_none && m_in_vid_strm != null) { out_vid_codec = avcodec_find_encoder(outfmt->video_codec); if(null == out_vid_codec) { print_msg("could not find vid encoder") ret = -1; return ret; } else { print_msg("found out vid encoder ") m_out_vid_strm = avformat_new_stream(m_outformat, out_vid_codec); if(null == m_out_vid_strm) { print_msg("failed allocate output vid strm ") ret = -1; return ret; } else { print_msg("allocated video stream ") if(avcodec_copy_context(m_out_vid_strm->codec, m_informat->streams[m_in_vid_strm_idx]->codec) != 0) { print_msg("failed copy context ") ret = -1; return ret; } else { m_out_vid_strm->sample_aspect_ratio.den = m_out_vid_strm->codec->sample_aspect_ratio.den; m_out_vid_strm->sample_aspect_ratio.num = m_in_vid_strm->codec->sample_aspect_ratio.num; print_msg("copied context ") m_out_vid_strm->codec->codec_id = m_in_vid_strm->codec->codec_id; m_out_vid_strm->codec->time_base.num = 1; m_out_vid_strm->codec->time_base.den = m_fps*(m_in_vid_strm->codec->ticks_per_frame); m_out_vid_strm->time_base.num = 1; m_out_vid_strm->time_base.den = 1000; m_out_vid_strm->r_frame_rate.num = m_fps; m_out_vid_strm->r_frame_rate.den = 1; m_out_vid_strm->avg_frame_rate.den = 1; m_out_vid_strm->avg_frame_rate.num = m_fps; m_out_vid_strm->duration = (m_out_end_time - m_out_start_time)*1000; } } } } if(outfmt->audio_codec != av_codec_id_none && m_in_aud_strm != null) { out_aud_codec = avcodec_find_encoder(outfmt->audio_codec); if(null == out_aud_codec) { print_msg("could not find out aud encoder ") ret = -1; return ret; } else { print_msg("found out aud encoder ") m_out_aud_strm = avformat_new_stream(m_outformat, out_aud_codec); if(null == m_out_aud_strm) { print_msg("failed allocate out vid strm ") ret = -1; return ret; } else { if(avcodec_copy_context(m_out_aud_strm->codec, m_informat->streams[m_in_aud_strm_idx]->codec) != 0) { print_msg("failed copy context ") ret = -1; return ret; } else { print_msg("copied context ") m_out_aud_strm->codec->codec_id = m_in_aud_strm->codec->codec_id; m_out_aud_strm->codec->codec_tag = 0; m_out_aud_strm->pts = m_in_aud_strm->pts; m_out_aud_strm->duration = m_in_aud_strm->duration; m_out_aud_strm->time_base.num = m_in_aud_strm->time_base.num; m_out_aud_strm->time_base.den = m_in_aud_strm->time_base.den; } } } } // 6. output header. if (!(outfmt->flags & avfmt_nofile)) { if (avio_open2(&m_outformat->pb, outfile.c_str(), avio_flag_write,null, null) < 0) { print_val("could not open file ", outfile) ret = -1; return ret; } } /* write stream header, if any. */ if (avformat_write_header(m_outformat, null) < 0) { print_val("error occurred while writing header ", outfile) ret = -1; return ret; } else { print_msg("written output header ") m_init_done = true; } // 7. in while loop read frame using av_read_frame , write output format using // av_interleaved_write_frame(). can use following loop while(av_read_frame(m_informat, &pkt) >= 0 && (m_num_frames-- > 0)) { if(pkt.stream_index == m_in_vid_strm_idx) { print_val("actual vid pkt pts ",av_rescale_q(pkt.pts,m_in_vid_strm->time_base, m_in_vid_strm->codec->time_base)) print_val("actual vid pkt dts ", av_rescale_q(pkt.dts, m_in_vid_strm->time_base, m_in_vid_strm->codec->time_base )) av_init_packet(&outpkt); if(pkt.pts != av_nopts_value) { if(last_vid_pts == vid_pts) { vid_pts++; last_vid_pts = vid_pts; } outpkt.pts = vid_pts; print_val("rescaled vid pts ", outpkt.pts) } else { outpkt.pts = av_nopts_value; } if(pkt.dts == av_nopts_value) { outpkt.dts = av_nopts_value; } else { outpkt.dts = vid_pts; print_val("rescaled vid dts ", outpkt.dts) print_msg("=======================================") } outpkt.data = pkt.data; outpkt.size = pkt.size; outpkt.stream_index = pkt.stream_index; outpkt.flags |= av_pkt_flag_key; last_vid_pts = vid_pts; if(av_interleaved_write_frame(m_outformat, &outpkt) < 0) { print_msg("failed video write ") } else { m_out_vid_strm->codec->frame_number++; } av_free_packet(&outpkt); av_free_packet(&pkt); } else if(pkt.stream_index == m_in_aud_strm_idx) { print_val("actual aud pkt pts ", av_rescale_q(pkt.pts, m_in_aud_strm->time_base, m_in_aud_strm->codec->time_base)) print_val("actual aud pkt dts ", av_rescale_q(pkt.dts, m_in_aud_strm->time_base, m_in_aud_strm->codec->time_base)) //num_aud_pkt++; av_init_packet(&outpkt); if(pkt.pts != av_nopts_value) { outpkt.pts = aud_pts; print_val("rescaled aud pts ", outpkt.pts) } else { outpkt.pts = av_nopts_value; } if(pkt.dts == av_nopts_value) { outpkt.dts = av_nopts_value; } else { outpkt.dts = aud_pts; print_val("rescaled aud dts ", outpkt.dts) print_msg("====================================") if( outpkt.pts >= outpkt.dts) { outpkt.dts = outpkt.pts; } if(outpkt.dts == aud_dts) { outpkt.dts++; } if(outpkt.pts < outpkt.dts) { outpkt.pts = outpkt.dts; aud_pts = outpkt.pts; } } outpkt.data = pkt.data; outpkt.size = pkt.size; outpkt.stream_index = pkt.stream_index; outpkt.flags |= av_pkt_flag_key; vid_pts = aud_pts; aud_pts++; if(av_interleaved_write_frame(m_outformat, &outpkt) < 0) { print_msg("faile audio write ") } else { m_out_aud_strm->codec->frame_number++; } av_free_packet(&outpkt); av_free_packet(&pkt); } else { print_msg("got unknown pkt ") //num_unkwn_pkt++; } //num_total_pkt++; } //8. write trailer , clean av_write_trailer(m_outformat); av_free_packet(&outpkt); av_free_packet(&pkt);
Comments
Post a Comment