2016-05-28 10 views
0

ffmpegがC++プログラムから呼び出されることを含むC++プログラムを記述しています。数日前、私はシステムffmpegは、C++でexecveから呼び出されたときに不正な出力を生成します。

std::system("ffmpeg -threads auto -y -r 1.74659 -i /mnt/ev_ramdsk/1/%05d-capture.jpg -px_fmt yuv420p -preset ultrafast -r 10 /mnt/ev_ramdsk/1/video.mp4"); 

::それはSTDを使用して作業しましたが、これは一度だけ働いた今、これは8メガバイトの.MP4動画を作成するか、そのためにはとてもためで提案の...どこでも再生することはできません前の質問私はexecveに移動しました。

ここに私のコードは

child_pid = fork(); 
     if(child_pid < 0){ 
      syslog(LOG_ERR, "ERROR: ffmpeg forking failed"); 
      return false; 
     } 
     else if(child_pid > 0){ 
      syslog(LOG_DEBUG, "DEBUG: forking succeeded, pid: %d", child_pid); 
     } 
     else if(child_pid == 0){ 
      char *newargv[16]; 
      for(int i=0; i < 15; i++) newargv[i] = (char *)malloc(sizeof(char) * 60); //allocate the array in memory 
      strcpy(newargv[0], "/usr/bin/ffmpeg"); 
      strcpy(newargv[1], "-threads"); 
      strcpy(newargv[2], "auto"); 
      strcpy(newargv[3], "-y"); 
      strcpy(newargv[4], "-framerate"); 
      tempSS << fps; 
      strcpy(newargv[5], tempSS.str().c_str()); 
      tempSS.str(std::string()); 
      strcpy(newargv[6], "-i"); 
      strcpy(newargv[7], std::string(conf->dir_ram + dest + "%05d-capture.jpg").c_str()); 
      strcpy(newargv[8], "-pix_fmt"); 
      strcpy(newargv[9], "yuv420p"); 
      strcpy(newargv[10], "-preset"); 
      strcpy(newargv[11], "ultrafast"); 
      strcpy(newargv[12], "-r"); 
      strcpy(newargv[13], "25"); 
      strcpy(newargv[14], std::string(conf->dir_ram + dest + "video.mp4").c_str()); 
      newargv[15] = NULL; 

      for(int i=0; i < 15; i++){ 
       tempSS << "newargv[" << i << "] = \"" << newargv[i] << "\", "; 
      } 
      syslog(LOG_DEBUG, "DEBUG:newargv: %s", tempSS.str().c_str()); 
      tempSS.str(std::string()); 

      char *newenviron[] = { NULL }; 

      if(execve(newargv[0], newargv, newenviron) == -1){ 
       syslog(LOG_ERR, "ERROR: execve returned -1"); 
       exit(EXIT_SUCCESS); 
      } 
     } 

     wpid = wait(&status); 
     syslog(LOG_DEBUG, "DEBUG: ffmpeg child terminated, pid: %d, status: %d", wpid, status); 

でのsyslogの出力は次のようになります。この場合、

May 28 00:25:03 SERVER dt_ev_maker[10471]: DEBUG: forking succeeded, pid: 10658 
May 28 00:25:03 SERVER dt_ev_maker[10658]: DEBUG:newargv: 
newargv[0] = "/usr/bin/ffmpeg", 
newargv[1] = "-threads", 
newargv[2] = "auto", 
newargv[3] = "-y", 
newargv[4] = "-framerate", 
newargv[5] = "1.45097", 
newargv[6] = "-i", 
newargv[7] = "/mnt/ev_ramdsk/1/%05d-capture.jpg", 
newargv[8] = "-pix_fmt", 
newargv[9] = "yuv420p", 
newargv[10] = "-preset", 
newargv[11] = "ultrafast", 
newargv[12] = "-r", 
newargv[13] = "25", 
newargv[14] = "/mnt/ev_ramdsk/1/video.mp4", 
May 28 00:25:03 SERVER dt_ev_maker[10471]: DEBUG: ffmpeg child terminated, pid: 10658, status: 256 

映像を約90B大きさを持っており、また破損しています。

注:コマンドラインから同じコマンドを実行すると、ビデオは正常に再生されます。

何が間違っていますか?

ありがとうございます! ouroborusへ

EDIT

おかげで(上記の提出変更)私はそれが18メガバイトのビデオを作るようになったが、私はそれらを再生傾けます。

+0

はい、ファイルが存在し、実行前にプログラムが実行することを確認します – Arheisel

+0

フレームレートが** 1.45097 **に設定されているのはなぜですか?あなたはスライドショーを作っていますか? –

+0

いいえ、入力はウェブカメラからの録音です。そのレートで起こっています – Arheisel

答えて

1

だから、最終的に働いていたコードはでした:私は、全体オープン()とdup2の()部分をコメントする場合

pid_t wpid, child_pid; 
      int status; 
      int fd = open(std::string(conf->dir_ram + "ffmpeg.txt").c_str(), O_CREAT | O_WRONLY, 0777); 
      if(fd < 0){ 
       syslog(LOG_ERR, "ERROR: open returned -1"); 
       return false; 
      } 

      child_pid = fork(); 
      if(child_pid < 0){ 
       syslog(LOG_ERR, "ERROR: ffmpeg forking failed"); 
       return false; 
      } 
      else if(child_pid > 0){ 
       syslog(LOG_DEBUG, "DEBUG: forking succeeded, pid: %d", child_pid); 
      } 
      else if(child_pid == 0){ 

       if(close(1) < 0){ 
        syslog(LOG_ERR, "ERROR: close returned -1"); 
        return false; 
       } 
       if(dup2(fd, 1) < 0){ 
        syslog(LOG_ERR, "ERROR: dup2 returned -1"); 
        return false; 
       } 

       char *newargv[18]; 
       for(int i=0; i < 17; i++) newargv[i] = (char *)malloc(sizeof(char) * 60); //allocate the array in memory 
       strcpy(newargv[0], conf->ffmpeg_path.c_str()); 
       strcpy(newargv[1], "-threads"); 
       strcpy(newargv[2], "auto"); 
       strcpy(newargv[3], "-y"); 
       strcpy(newargv[4], "-r"); 
       tempSS << fps; 
       strcpy(newargv[5], tempSS.str().c_str()); 
       tempSS.str(std::string()); 
       strcpy(newargv[6], "-i"); 
       strcpy(newargv[7], std::string(conf->dir_ram + dest + "%05d-capture.jpg").c_str()); 
       strcpy(newargv[8], "-pix_fmt"); 
       strcpy(newargv[9], "yuv420p"); 
       strcpy(newargv[10], "-c:v"); 
       strcpy(newargv[11], "libx264"); 
       strcpy(newargv[12], "-preset"); 
       strcpy(newargv[13], "ultrafast"); 
       strcpy(newargv[14], "-r"); 
       strcpy(newargv[15], conf->ffmpeg_rate.c_str()); 
       strcpy(newargv[16], std::string(conf->dir_ram + dest + "video.mp4").c_str()); 
       newargv[17] = NULL; 

       char *newenviron[] = { NULL }; 

       if(execve(newargv[0], newargv, newenviron) == -1){ 
        syslog(LOG_ERR, "ERROR: execve returned -1"); 
        exit(EXIT_SUCCESS); 
       } 
      } 

      wpid = wait(&status); 

はビデオが壊れます。私はなぜそれがないのか分かりませんが、それは働きません。

1

execve()は、最後の要素がNULLである必要があります。配列newargvを1つ拡張し、最後の要素をNULLに設定してからexecve()に渡します。

Refが:Using execve for the first time

+0

これは90Bビデオの問題を解決しましたが、今は16MBの再生できないビデオを出力しますが、大きな改善はありますが、かなりありがたいです! – Arheisel

+0

元の 'system()'バージョンにも問題があると言いました。私はあなたのコードは他の点ではうまくいくと思うので、コンソールから正しく動作するようにffmpegコマンドを得ることができるかどうかを確認することをお勧めします。 – Ouroborus

+0

strangley、私はコマンドラインから同じコマンドを実行すると完全に動作します!おそらく問題はffmpeg自体です – Arheisel

関連する問題