2013-07-11 46 views

回答

13

如果您正在寻找流式复制,您可以很容易地做到这一点。 您可以参考以下步骤。

//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); 
+0

非常感谢praks411。 – Febin

+0

非常感谢您的更新。如你所说,我可以将流复制到输出容器。 但是,我得到一个错误 [mpegts @ 046bf840] H.264比特流格式错误,没有找到startcode,使用h264_mp4toannexb比特流过滤器(-bsf h264_mp4toannexb)。 我可以通过代码知道如何指定-bsf h264_mp4toannexb吗? – Febin

+0

我到现在还没有使用bsf。但你可以尝试使用它。您也可以参考ffmpeg.c获取更多信息,因为他们已经在那里使用它。此外,你我的回答已经帮助你,那么你可以标记它是正确的:) – praks411

相关问题