2013-07-11 64 views
7

'ts' i có lệnh ffmpeg nàyFFMpeg - Làm thế nào để sao chép codec (video và audio) từ 'mp4' container để chứa

ffmpeg-ic: \ input.mp4 -vcodec sao chép bản sao -acodec - vbsf h264_mp4toannexb c: \ output.ts.

Lệnh trên chuyển đổi thành công input.mp4 thành output.ts.

Tôi cần triển khai cùng chức năng thông qua mã (sử dụng thư viện ffmpeg).

Có ai biết cách sao chép từ vùng chứa này sang vùng chứa khác mà không cần giải mã và mã hóa không?

+0

Cảm ơn bạn đã hỏi điều này :) –

Trả lời

13

Nếu bạn đang tìm kiếm chỉ để sao chép luồng, bạn có thể làm điều này khá dễ dàng. Bạn có thể tham khảo các bước sau.

//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

thanku rất nhiều praks411. – Febin

+0

thanku rất nhiều cho việc cập nhật. Như bạn đã nói, tôi có thể sao chép luồng vào vùng chứa đầu ra. Tuy nhiên, tôi gặp lỗi [mpegts @ 046bf840] Dòng bit H.264 không đúng định dạng, không tìm thấy mã khởi đầu, hãy sử dụng bộ lọc bitstream h264_ mp4toannexb (-bsf h264_mp4toannexb). Tôi có thể biết cách chỉ định -bsf h264_mp4toannexb qua mã không? – Febin

+0

Tôi chưa sử dụng bsf cho đến bây giờ. Nhưng bạn có thể thử sử dụng nó. Bạn cũng có thể tham khảo ffmpeg.c để biết thêm thông tin khi họ sử dụng nó ở đó. Ngoài ra bạn câu trả lời của tôi đã giúp bạn sau đó bạn có thể đánh dấu nó chính xác :) – praks411

Các vấn đề liên quan