2014-10-27 58 views
2

我試圖將一系列視頻片段文件(以.flv格式,全部使用相同的音頻/視頻編碼)連接起來,並將它們連接到一個新文件(以.mp4格式)。我的編碼管道對於普通的單段文件來說工作得很好,但是一旦我添加了第二個段,我就無法正常工作了。在gstreamer中連接視頻文件(在python中)

從我目前的執行情況,我對EOS消息的消息處理程序,例如:

def on_eos(self, bus, msg): 
     remain = len(self.metadata['localSegments']) 
     logger.warning("Hit EOS Probe: %d segments left" % remain) 
     if remain == 0: 
      self.abort = True 
      self.mainloop.quit() 
      return 

     duration = self.pipeline.query_duration(Gst.Format(Gst.Format.TIME))[1] 
     self.offset += duration 
     logger.info("Duration: %s, new offset: %s" % (Gst.TIME_ARGS(duration), 
                 Gst.TIME_ARGS(self.offset))) 
     self.pipeline.set_state(Gst.State.READY) 
     self.localInFile = self.metadata['localSegments'].pop(0) 
     logger.info("Starting new file: %s" % self.localInFile) 
     self.elem_src.set_property('location', self.localInFile) 
     self.elem_src_src.set_offset(self.offset) 
     self.pipeline.set_state(Gst.State.PLAYING) 

這顯示最後段的持續時間,並嘗試將下一個段的偏移設置爲結束以前的細分市場。這確實代碼轉換,但它總是回溯到輸出文件的開頭並覆蓋以前的內容。顯然這不是我想要的輸出!

有什麼我錯過了嗎?我試着用它作爲pad的探測器,但是它不會讓我停下來,從它自己的線程重新啓動管道,並且崩潰慘劇(告訴我在一個消息處理程序中執行,這正是我現在的做法) 。

回答

4

filesink總是覆蓋現有的文件。你真正想要的是將新的段添加到現有的MP4文件中(並且你不想僅僅將另一個MP4文件附加到現有的MP4文件的末尾)。

您需要做的是,您必須通過焊盤探頭在複用器正前方的srcpad上捕獲EOS 事件(不是消息)。從pad探針回調中,您可以取消鏈接該srcpad和複用器的sinkpad。然後,您將動態鏈接一個新的輸入,並將其鏈接到複用器,同時按照您的設置設置焊盤偏移量。永遠不要改變管線的狀態,並且在最後一段中,您會讓EOS事件通過並等待EOS信息(不是事件!)發佈到公交車上。只有然後關閉管道。

現在所有這一切的棘手部分是,你可能也想清理舊的細分市場。由於EOS是從流線程發送的,因此您無法通過pad探針回調來完成此操作。你需要做的是(在從pad探針回調中斷開連接之後!),你將從另一個線程的管道中刪除與舊段相關的元素,將它們的狀態設置爲GST_STATE_NULL,然後取消它們。

+0

我當然越來越近了。我已經嘗試了你的建議,但是遇到了讓音頻和視頻捕捉EOS事件的問題,所以我讓一個人發送了一個事件給另一個人觸發它......這種工作方式,但我永遠不會讓管道再次正常運行,並且在第一個段後沒有更多的輸出。現在,我正在使用src焊盤上的探針進入混合器的隊列之前(因爲總有一些東西留在它們中的一個裏面)。我已經回來了,但仍然沒有更多的產出後的第一部分。 – Beirdo 2014-10-28 10:40:19

+0

一旦它處於第二段並且沒有改變,它會報告「-1:59:59.999999999」的位置,如果這觸發了任何想法。 – Beirdo 2014-10-28 10:42:56

+0

您需要在EOS事件到達將要稍後重用的打印墊之前捕捉它。 對於位置報告,您必須檢查GStreamer調試日誌的來源。 – 2014-10-28 10:48:43