From be9c1d1f659b0ff31f656424c478e83a4f7c53b5 Mon Sep 17 00:00:00 2001
From: zhangmeng <775834166@qq.com>
Date: 星期五, 20 九月 2019 11:44:19 +0800
Subject: [PATCH] update ffmpeg

---
 csrc/ffmpeg/format/FormatOut.cpp |  144 ++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 109 insertions(+), 35 deletions(-)

diff --git a/csrc/ffmpeg/format/FormatOut.cpp b/csrc/ffmpeg/format/FormatOut.cpp
index a6e8c3c..0c6958f 100644
--- a/csrc/ffmpeg/format/FormatOut.cpp
+++ b/csrc/ffmpeg/format/FormatOut.cpp
@@ -32,6 +32,7 @@
     ,record_(false)
     ,fps_(0.0f)
     ,format_name_("mp4")
+    ,streams_(NULL)
 	{}
 
 	FormatOut::~FormatOut()
@@ -265,42 +266,16 @@
     }
 
 //////////////////////////////////////////////////////////////////////////
-    FormatOut::FormatOut(AVStream *in, const char *format_name)
+    FormatOut::FormatOut(const double fps, const char *format_name)
     :FormatOut(){
 
         format_name_ = format_name;
 
-        if(in->r_frame_rate.num >=1 && in->r_frame_rate.den >= 1){
-            fps_ = av_q2d(in->r_frame_rate);
-        }else if(in->avg_frame_rate.num >=1 && in->avg_frame_rate.den >= 1){
-            fps_ = av_q2d(in->avg_frame_rate);
-        }
-    }
-
-    
-    bool FormatOut::copyCodecFromIn(AVStream *in){
-
-        v_s_ = avformat_new_stream(ctx_, in->codec->codec);
-        if(!v_s_){
-            return false;
-        }
-
-        int ret = avcodec_copy_context(v_s_->codec, in->codec);
-        if (ret < 0){
-            logIt("can't copy codec from in error:%s", getAVErrorDesc(ret).c_str()); 
-
-            return false;
-        }
-                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
-        if (ctx_->oformat->flags & AVFMT_GLOBALHEADER)  
-        {  
-            v_s_->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;  
-        }  
-        return true;
+        fps_ = fps;
     }
 
     bool FormatOut::openResource(const char *filename, const int flags){
-        if((ctx_->flags & AVFMT_NOFILE) != AVFMT_NOFILE){
+        if((ctx_->oformat->flags & AVFMT_NOFILE) != AVFMT_NOFILE){
             
             const int err = avio_open2(&ctx_->pb, filename, flags, NULL, NULL);
             if(err < 0)
@@ -320,7 +295,43 @@
         }
         return true;
     }
-    bool FormatOut::JustWriter(AVStream *in, const char *filename){
+
+    bool FormatOut::copyCodecFromIn(std::vector<AVStream*> in){
+        auto count = in.size();
+
+        for(int i = 0; i < count; i++)
+        {    //鏍规嵁杈撳叆娴佸垱寤鸿緭鍑烘祦
+            AVStream *in_stream = in[i];
+            AVStream *out_stream = avformat_new_stream(ctx_, in_stream->codec->codec);
+            if(!out_stream)
+            {
+                logIt("Failed allocating output stream.\n");
+                return false;
+            }
+
+            if (in_stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){
+                v_s_ = out_stream;
+            }
+            //灏嗚緭鍑烘祦鐨勭紪鐮佷俊鎭鍒跺埌杈撳叆娴�
+            auto ret = avcodec_copy_context(out_stream->codec, in_stream->codec);
+            if(ret<0)
+            {
+                logIt("Failed to copy context from input to output stream codec context\n");
+                return false;
+            }
+            out_stream->codec->codec_tag = 0;
+
+            if(ctx_->oformat->flags & AVFMT_GLOBALHEADER)
+                out_stream->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
+
+        }
+
+        streams_ = in;
+
+        return true;
+    }
+
+    bool FormatOut::JustWriter(std::vector<AVStream*> in, const char *filename){
         if(ctx_){
             clear();
         }
@@ -386,7 +397,7 @@
         return true;
     }
 
-    void FormatOut::adjustPTS(AVPacket &pkt, const int64_t &frame_cnt){
+    void FormatOut::adjustVideoPTS(AVPacket &pkt, const int64_t &frame_cnt){
         int64_t time_stamp = frame_cnt;
         
         pkt.pos = -1;  
@@ -404,7 +415,70 @@
         pkt.dts = pkt.pts;
         pkt.duration = av_rescale_q(calc_duration, time_base_q, time_base); //(double)(calc_duration)*(double)(av_q2d(time_base_q)) / (double)(av_q2d(time_base));
         
-        // logIt("FRAME ID: %lld, PTS : %lld, DTS : %lld", frame_cnt, pkt.pts, pkt.dts);        
+        // logIt("FRAME ID: %lld, PTS : %lld, DTS : %lld", frame_cnt, pkt.pts, pkt.dts);
+    }
+
+    void FormatOut::adjustPTS(AVPacket &pkt, const int64_t &frame_cnt){
+        if (streams_.size() == 1){
+            return adjustVideoPTS(pkt, frame_cnt);
+        }
+
+        if (pkt.stream_index >= streams_.size()){
+            logIt("adjustPTS pkt stream index too much");
+            return;
+        }
+
+        AVStream *in_stream,*out_stream;
+        
+        in_stream = streams_[pkt.stream_index];
+        out_stream = ctx_->streams[pkt.stream_index];
+
+        // logIt("stream %d time_base %d : %d", pkt.stream_index, in_stream->time_base.num, in_stream->time_base.den);
+        // logIt("out time_base %d : %d", out_stream->time_base.num, out_stream->time_base.den);
+        
+        std::string type("video");
+        if (in_stream->codecpar->codec_type == 1){
+            type = "audio";
+        }
+
+        // logIt("BEFORE stream %d type: %s, pts: %lld, dts: %lld, duration: %lld", 
+        // pkt.stream_index, type.c_str(), pkt.pts, pkt.pts, pkt.duration);
+        //copy packet
+        //杞崲 PTS/DTS 鏃跺簭
+        pkt.pts = av_rescale_q_rnd(pkt.pts,in_stream->time_base,out_stream->time_base,(enum AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
+        pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, (enum AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
+        //printf("pts %d dts %d base %d\n",pkt.pts,pkt.dts, in_stream->time_base);
+        pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base); 
+        pkt.pos = -1;  
+
+        // logIt("AFTER stream %d type: %s, pts: %lld, dts: %lld, duration: %lld", 
+        // pkt.stream_index, type.c_str(), pkt.pts, pkt.pts, pkt.duration);
+
+        // //姝hile寰幆涓苟闈炴墍鏈塸acket閮芥槸瑙嗛甯э紝褰撴敹鍒拌棰戝抚鏃惰褰曚竴涓嬶紝浠呮鑰屽凡
+        // if(pkt.stream_index==video_index)
+        // {
+        //     printf("Receive %8d video frames from input URL\n",frame_index);
+        //     frame_index++;
+        // }
+
+        // //灏嗗寘鏁版嵁鍐欏叆鍒版枃浠躲��
+        // ret = av_interleaved_write_frame(ofmt_ctx,&pkt);
+        // if(ret < 0)
+        // {
+        //     /**
+        //     褰撶綉缁滄湁闂鏃讹紝瀹规槗鍑虹幇鍒拌揪鍖呯殑鍏堝悗涓嶄竴鑷达紝pts鏃跺簭娣蜂贡浼氬鑷�
+        //     av_interleaved_write_frame鍑芥暟鎶� -22 閿欒銆傛殏鏃跺厛涓㈠純杩欎簺杩熸潵鐨勫抚鍚�
+        //     鑻ユ墍澶ч儴鍒嗗寘閮芥病鏈塸ts鏃跺簭锛岄偅灏辫鐪嬫儏鍐佃嚜宸辫ˉ涓婃椂搴忥紙姣斿杈冨墠涓�甯ф椂搴�+1锛夊啀鍐欏叆銆�
+        //     */
+        //     if(ret==-22){
+        //         continue;
+        //     }else{
+        //         printf("Error muxing packet.error code %d\n" , ret);
+        //         break;
+        //     }
+            
+        // }
+                
     }
 
     bool FormatOut::writeFrame(AVPacket &pkt, const int64_t &frame_cnt,
@@ -429,11 +503,11 @@
             ret = av_write_frame(ctx_, &pkt);
         }
     
-        if(ret < 0){
-            return false;
+        if(ret < -22 || ret == 0){
+            return true;
         }
 
-        return true;
+        return false;
     }
 
     bool FormatOut::writeTrailer(){

--
Gitblit v1.8.0