FFMpeg - 如何将编解码器(视频和音频)从'mp4'容器复制到'ts'容器 [英] FFMpeg - How to copy codec ( video and audio ) from 'mp4' container to 'ts' container

查看:534
本文介绍了FFMpeg - 如何将编解码器(视频和音频)从'mp4'容器复制到'ts'容器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个ffmpeg命令

i have this ffmpeg command


ffmpeg -ic:\input.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb c: \output.ts。

ffmpeg -i c:\input.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb c:\output.ts.

上述命令将input.mp4成功转换为output.ts。

The above command successfully converts input.mp4 to output.ts.

我需要通过代码(使用ffmpeg库)实现相同的功能。

I need to implement the same functionality via code (using the ffmpeg library).

有人知道如何从一个容器复制到另一个解码和编码?

Does anybody know how to copy from one container to another without decoding and encoding?

推荐答案

如果你只是寻找流复制,你可以很容易做到。
您可以参考以下步骤。

If you are looking just for stream copy you can do this quite easily. You can refer following steps.

//1. Do 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 to find stream info:: ", errbuf)
           ret = -1;
           return ret;
        }

        for (unsigned int i = 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  and 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 and video stream to 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 to 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 to 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 to 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 to 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. Finally 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 the 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. Now in while loop read frame using av_read_frame and write to output format using 
//  av_interleaved_write_frame(). You 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. Finally write trailer and clean up everything

     av_write_trailer(m_outformat);
        av_free_packet(&outpkt);
        av_free_packet(&pkt);

这篇关于FFMpeg - 如何将编解码器(视频和音频)从'mp4'容器复制到'ts'容器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆