[問題] 兩程式間傳資料 stdout 與 stdin 的問題

看板C_and_CPP作者 ( )時間14年前 (2009/12/13 09:04), 編輯推噓4(4018)
留言22則, 2人參與, 最新討論串1/2 (看更多)
遇到的問題: (題意請描述清楚) 由於影音轉檔需要,要用到 avs2wav 把資料由 stdout 輸出給 NeroAACEnc 轉檔 程式用途: PS: avs 是一種偽裝avi檔的 frame server,用來把各種格式的影音檔 偽裝成 avi 給程式如 x264 去轉換 avs2wav --> 把 avs (Avisynth) 轉成 wav,或者 stdout 輸出 NeroAACEnc --> 把 wav 轉成 aac,可吃 stdin lame --> 把 wav 轉成 mp3,可吃 stdin 指令: avs2wav input.avs out.wav avs2wav input.avs - | neroaacenc -ignorelength -br 128000 -if - -of out.m4a avs2wav input.avs - | lame -h -b 128 --cbr - out.mp3 但是發現 avs2wav 的 stdout 結果有問題 wav 只能正確輸出不到2秒 接下來都是雜訊 而且大小也不正確 經交叉比對後,不論是由 NeroAACEnc 或者 lame 去轉都一樣失敗 所以可以判斷是 avs2wav 的 stdout 部分有問題 對於 stdout/stdin 實在不太了解 想請問使用 stdout 有什麼要注意的才不會使 stdout 破損? 有想過所遇到的問題或許來自 buffer ? 用了 setvbuf (stdout, NULL, _IONBF, NULL); 或 setvbuf (stdout, buff, _IOFBF, buffs); 其中 char buff[buffs]; // buffs = 超大 或 很小 不管如何狀況都一樣,最終產生的檔案也完全一樣 開發平台: (例: VC++ or gcc/g++ or Dev-C++, Windows or Linux) VC++ 2008 (原始碼可用 2008 compile) 只要開新專案,把 AVS2WAV.cpp, AVS2WAV.h 加入即可 有問題的code: (請善用置底文標色功能) 分析原始碼,avs2wav 使用的方法如下 FILE* m_Outputfile; m_OutputFile = stdout; setmode(1, O_BINARY); while( ..... ){ fwrite( .....); } fclose(m_OutputFile); 補充說明: avs2wav 來源: 下載頁面 http://www.avisynth.info/?avs2wav 已編譯檔案(含原始碼) http://home.pages.at/kassandro/avs2wav.rar PS: 由於使用了 VfW 的 avi interface function, 可能需要加上一行 #pragma comment(lib, "Vfw32.lib") 才能正確編譯 NeroAACEnc 來源: http://www.nero.com/eng/downloads-nerodigital-nero-aac-codec.php Avisynth: *可能需要安裝,系統才能認識 avs (用 2.5.8) http://sourceforge.net/projects/avisynth2/files/ 所需的檔案一起通包: 檔案都一樣 http://www.mediafire.com/?ljwzvjfiyjm http://rapidshare.com/files/320068516/Package.zip.html http://www.megaupload.com/?d=3DFD3LNE http://www.badongo.com/file/19010795 http://vspace.cc/file/DFLUYBM63S5SJ797.html -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 125.229.14.202

12/13 10:42, , 1F
我倒認為是那些程式在 win32 上沒處理好 binary stdin
12/13 10:42, 1F

12/13 10:42, , 2F
你要不要試試把你的程式 redirect 到檔案去試聽看看?
12/13 10:42, 2F

12/13 11:03, , 3F
可以簡單提供讀 stdin 然後寫入檔案的程式嗎?
12/13 11:03, 3F

12/13 11:03, , 4F
我寫的都會錯誤
12/13 11:03, 4F

12/13 11:29, , 5F
我寫出來了,測試中...
12/13 11:29, 5F
#include "stdafx.h" #include <io.h> int _tmain(int argc, _TCHAR* argv[]) { FILE* pOut; int i=0; char byte; fopen_s(&pOut,"stdouts.wav","wb"); while (fread(&byte,1,1,stdin)){ i++; fwrite(&byte,1,1,pOut); } printf("gets %d bytes from stdin\n",i); fclose(pOut); return 0; } 倘若無誤的話,我的電腦只能吃到該有的 695,852 中的 1,804 Bytes 比用 NeroAACEnc 或者 lame 還要慘 附上測試用的 stdout 產生器,用65535的大魔王血量長度是測試正常的 #include "stdafx.h" #include <io.h> #include <fcntl.h> int _tmain(int argc, _TCHAR* argv[]) { _setmode(_fileno( stdout ), _O_BINARY); for(int i=0;i<65535;i++){ fwrite("a",1,1,stdout); } return 0; } ================================================================ 除此之外,另一個軟體 MeGUI 看過原始碼,裡頭用的也是 stdout 送給 audio encoder 位置: \megui\trunk\packages\audio\AudioEncoderInterface.cs 只不過他用的是 C# 看起來有在寫wave檔頭,註解裡也有提到送出資料到 encoder 的 stdin 所以可以判斷 MeGUI 一樣使用 stdout 那既然同樣都是 stdout MeGUI 可以正確轉檔,avs2wav 卻不行 似乎更可以確定 audio encoder 的 stdin 接收應該沒有問題 而是 avs2wav 的 stdout 有問題 ※ 編輯: logs 來自: 125.229.14.202 (12/13 11:49)

12/13 13:35, , 6F
唔...剛剛拿了個比較程式去比發現了一個嚴重的問題:
12/13 13:35, 6F

12/13 13:36, , 7F
avs2wav 在 scanning 時會輸出 MPEG 1.0 layer II ...的訊息
12/13 13:36, 7F

12/13 13:36, , 8F
但這些訊息並不是送去 stderr 的 而是送去 stdout 的...|||
12/13 13:36, 8F

12/13 13:36, , 9F
所以當輸出檔也輸出到 stdout 就會全部寫入檔案裡...orz
12/13 13:36, 9F

12/13 13:38, , 10F
然後這個訊息貌似不在 avs2wav.cpp 裡面..||
12/13 13:38, 10F

12/13 13:44, , 11F
OK, 確認問題是在那個地方了 orz 那個東西以外都是一樣的
12/13 13:44, 11F

12/13 13:44, , 12F
然後你的測試程式的問題在於你用了 text mode 讀 stdin...
12/13 13:44, 12F

12/13 13:45, , 13F
所以碰到 0x1A 就被認為是 EOF 了
12/13 13:45, 13F

12/13 13:46, , 14F
http://www.avisynth.info/?avs2wav seraphy 版の入手方法
12/13 13:46, 14F

12/13 13:48, , 15F
http://tinyurl.com/yaeftmn 有一個日本人寫的新版本
12/13 13:48, 15F

12/13 13:49, , 16F
也有發現 "標準出力" 的問題. 但那個下載後沒有解決
12/13 13:49, 16F

12/13 13:50, , 17F
因為我用的avs是 MpaSource 所以搭配 NeroAACEnc 要執行兩次
12/13 13:50, 17F

12/13 13:52, , 18F
生成 d2a 之後,再一次執行才會正常 ?? 原因不明
12/13 13:52, 18F

12/13 13:53, , 19F
用 lame 搭配則一次生成.可能是這樣導致 cpp 中找不到
12/13 13:53, 19F

12/13 13:53, , 20F
然後網路上的 EZBuilder 用的 avs2wav 跟我附的完全一樣
12/13 13:53, 20F

12/13 14:13, , 21F
---- 那有沒有辦法藉由修改 avs2wav.cpp 讓字串為 MPEG 1.0..
12/13 14:13, 21F

12/13 14:13, , 22F
的那些被自動過濾掉,這樣應該就可以解決了吧?
12/13 14:13, 22F
文章代碼(AID): #1B93smsk (C_and_CPP)
文章代碼(AID): #1B93smsk (C_and_CPP)