2013-07-11 8 views
7

करने के लिए 'mp4' कंटेनर से कोडेक (वीडियो और ऑडियो) कॉपी करने के लिए कैसे मैं इस ffmpeg आदेशffmpeg - 'ts' कंटेनर

ffmpeg -ic है: \ input.mp4 -vcodec कॉपी -acodec प्रतिलिपि - vbsf h264_mp4toannexb c: \ output.ts।

उपरोक्त आदेश input.mp4 को output.ts में सफलतापूर्वक परिवर्तित करता है।

मुझे कोड के माध्यम से समान कार्यक्षमता को लागू करने की आवश्यकता है (ffmpeg लाइब्रेरी का उपयोग करके)।

क्या कोई जानता है कि एक कंटेनर से दूसरे में डीकोडिंग और एन्कोडिंग के बिना कैसे कॉपी करें?

+0

यह पूछने के लिए धन्यवाद :) –

उत्तर

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

अद्यतन के लिए बहुत बहुत धन्यवाद। जैसा कि आपने कहा था, मैं धाराओं को आउटपुट कंटेनर में कॉपी कर सकता हूं। लेकिन, मुझे एक त्रुटि मिली [एमपीईजी @ 046bf840] एच .264 बिटस्ट्रीम विकृत, कोई स्टार्टकोड नहीं मिला, h264_ mp4toannexb बिटस्ट्रीम फ़िल्टर (-bsf h264_mp4toannexb) का उपयोग करें। क्या मुझे पता है कि कोड के माध्यम से -bsf h264_mp4toannexb निर्दिष्ट करने के लिए कैसे? – Febin

+0

मैंने अब तक बीएसएफ का उपयोग नहीं किया है। लेकिन आप इसका उपयोग करने का प्रयास कर सकते हैं। आप अधिक जानकारी के लिए ffmpeg.c का भी उल्लेख कर सकते हैं क्योंकि उन्होंने इसका उपयोग किया है। इसके अलावा आप मेरे जवाब ने आपकी मदद की है तो आप इसे सही चिह्नित कर सकते हैं :) – praks411