我正在尝试使用Windowspipe道将数据写入Ffmpeg中的inputpipe道。 我正在使用以下命令ffmpeg:
ffmpeg -r 24 -pix_fmt rgba -s 1280x720 -f rawvideo -y -i \\.\pipe\videopipe -f s16le -ac 1 -ar 44100 -i \\.\pipe\audiopipe -acodec pcm_s16le -ac 1 -b:a 320k -ar 44100 -vf vflip -vcodec mpeg1video -qscale 4 -bufsize 500KB -maxrate 5000KB OUTPUT_FILE
我尝试使用CreateFile()
方法连接到它,但似乎不工作。 我也尝试过使用CreateNamedPipe()
开始运行ffmpeg命令后,但似乎等待别的东西连接。
我不知道按什么顺序,我必须打电话给那两个。 我是否首先需要创build一个Windowspipe道,并在ffmpeg中使用相同的名称,或者是否需要先使用命名pipe道调用ffmpeg,然后使用CreateFile()
连接到它?
提前致谢
我已经开发了代码来做,也许会有所帮助。 在我的情况下,我正在流式传输一个图像,并在ffplay中播放。 我启动了3个线程,一个创建管道(在演示管道中执行'initializePipe'的管道),一个监听管道创建并启动ffplay,另一个写入线程向管道写入映像。
demoPipes.cpp
#include "demoPipes.h" using namespace std; #define MAX_THREADS 100 //#define BUF_SIZE 255 void ErrorHandler(LPTSTR lpszFunction); // Sample custom data structure for threads to use. // This is passed by void pointer so it can be any data type // that can be passed using a single void pointer (LPVOID). /*typedef struct MyData { int val1; int val2; } MYDATA, *PMYDATA; */ typedef struct { HANDLE pipe; LPCSTR MEDIA_PIPE; } Session; int _tmain() { Session* s = (Session*)malloc(sizeof(Session)); s->pipe = NULL; s->MEDIA_PIPE = "\\\\.\\pipe\\screenRec"; DWORD dwThreadIdArray[MAX_THREADS]; HANDLE hThreadArray[MAX_THREADS]; // Create MAX_THREADS worker threads. for( int i=0; i<MAX_THREADS; i++ ) { //create pipe initializer thread if(i==0){ hThreadArray[i] = CreateThread( NULL, // default security attributes 0, // use default stack size initializePipe, // thread function name (LPVOID) s, // argument to thread function 0, // use default creation flags &dwThreadIdArray[i]); // returns the thread identifier } //create writer thread if(i>1){ PipeMetaData* pipe_data1 = fetch_file("D:\\images.png", s->pipe); //PipeMetaData* pipe_data = createPipeMetaData(pipe_data1->file_vector,pipe_data1->byte_size); //pipe_data1->pipe =s->pipe; hThreadArray[i] = CreateThread( NULL, // default security attributes 0, // use default stack size send_media_to_recorder, // thread function name pipe_data1, // argument to thread function 0, // use default creation flags &dwThreadIdArray[i]); // returns the thread identifier } //create recorder thread if(i==1){ hThreadArray[i] = CreateThread( NULL, // default security attributes 0, // use default stack size recorder_pipe_function, // thread function name 0, // argument to thread function 0, // use default creation flags &dwThreadIdArray[i]); // returns the thread identifier } // Check the return value for success. // If CreateThread fails, terminate execution. // This will automatically clean up threads and memory. if (dwThreadIdArray[i] == NULL) { ErrorHandler(TEXT("CreateThread")); ExitProcess(3); } } // End of main thread creation loop. //for close RTP // Wait until all threads have terminated. WaitForMultipleObjects(MAX_THREADS, hThreadArray, TRUE, INFINITE); // Close all thread handles and free memory allocations. CloseHandle(s->pipe); for(int i=0; i<MAX_THREADS; i++) { CloseHandle(hThreadArray[i]); } getchar(); return 0; } void ErrorHandler(LPTSTR lpszFunction) { // Retrieve the system error message for the last-error code. LPVOID lpMsgBuf; LPVOID lpDisplayBuf; DWORD dw = GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); // Display the error message. lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR) lpMsgBuf) + lstrlen((LPCTSTR) lpszFunction) + 40) * sizeof(TCHAR)); StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(TCHAR), TEXT("%s failed with error %d: %s"), lpszFunction, dw, lpMsgBuf); MessageBox(NULL, (LPCTSTR) lpDisplayBuf, TEXT("Error"), MB_OK); // Free error-handling buffer allocations. LocalFree(lpMsgBuf); LocalFree(lpDisplayBuf); }
clientpipe.cpp
#include "client_pipe.h" using namespace std; DWORD WINAPI recorder_pipe_function( LPVOID lpParam){ const char* MEDIA_PIPE = "\\\\.\\pipe\\screenRec"; //LPCWSTR MEDIA_PIPE_wchar = L"\\\\.\\pipe\\screenRec"; //waits for server to initialize the media pipe. //wait_for_media_pipe(MEDIA_PIPE,10); WaitNamedPipeA(MEDIA_PIPE,1000); start_recording_session(MEDIA_PIPE); return 0; } void start_recording_session(const char* media_pipe){ //initialize recording command char* command = (char*)malloc(sizeof(char)*100+1); command[0] ='\0'; strcpy_s(command,sizeof(char)*100+1,"start ffplay -i "); //strcpy_s(command,sizeof(char)*100+1,"ffmpeg -i "); strcat_s(command,sizeof(char)*100+1, media_pipe); //strcat_s(command,sizeof(char)*100+1, " -f matroska D:\\djhfifj.mkv"); std::cout << "Executing ffmpeg command\n"; int i=system (command); std::cout << "The value returned was: " << i << std::endl; }
serverPipe.cpp
#include "server_pipe.h" using namespace std; typedef struct { HANDLE pipe; LPCSTR MEDIA_PIPE; } Session; DWORD WINAPI initializePipe( LPVOID lpParam ) { printf("Creating an instance of a named pipe..."); Session* s = (Session*) lpParam; LPCSTR MEDIA_PIPE = s->MEDIA_PIPE; // Create a pipe to send data s->pipe = CreateNamedPipeA( MEDIA_PIPE, // name of the pipe PIPE_ACCESS_OUTBOUND, // 1-way pipe -- send only PIPE_TYPE_BYTE, // send data as a byte stream 1, // only allow 1 instance of this pipe 0, // no outbound buffer 0, // no inbound buffer 0, // use default wait time NULL // use default security attributes ); if (s->pipe == NULL ||s->pipe == INVALID_HANDLE_VALUE) { wcout << "Failed to create outbound pipe instance."; // look up error code here using GetLastError() return NULL; } wcout << "Waiting for a client to connect to the pipe..." << endl; // This call blocks until a client process connects to the pipe BOOL result = ConnectNamedPipe(s->pipe, NULL); if (!result) { wcout << "Failed to make connection on named pipe." << endl; // look up error code here using GetLastError() CloseHandle(s->pipe); // close the pipe system("pause"); return NULL; } } PipeMetaData* fetch_file(char* file_path,HANDLE pipe){ PipeMetaData* data = (PipeMetaData*) malloc(sizeof(PipeMetaData)); //opening file ifstream infile; infile.open(file_path,std::ios::binary); infile.seekg(0,std::ios::end); //get file byte size data->byte_size = infile.tellg(); //fetch data to send data->file_vector =(char*) malloc(sizeof(char)*data->byte_size); infile.seekg(0,std::ios::beg); infile.read(&(data->file_vector)[0],data->byte_size); data->packet = &(data->file_vector)[0]; data->pipe = pipe; wcout<<data->byte_size<<endl; return data; } DWORD WINAPI send_media_to_recorder(LPVOID lpParam){ PipeMetaData* p = (PipeMetaData*) lpParam; // This call blocks until a client process reads all the data DWORD numBytesWritten = 0; BOOL result = WriteFile( p->pipe, // handle to our outbound pipe p->packet,//&(p->file_vector)[0], // data to send p->byte_size, // length of data to send (bytes) &numBytesWritten, // will store actual amount of data sent NULL // not using overlapped IO ); if (result) { wcout << "Number of bytes sent: " << numBytesWritten << endl; } else { wcout << "Failed to send data." << endl; // look up error code here using GetLastError() GetLastError(); } free(p); return 0; }