2014-09-27 145 views
0

我想從OpenGL中的動畫創建視頻文件。 我一直在閱讀關於如何做到這一點,我的理解有兩種選擇:從OpenGL渲染幀創建視頻

  1. 保存每一個在OpenGL渲染幀圖像文件,然後創建從這些
  2. 視頻文件獲取的幀數據使用glReadPixels()和動態寫那些爲視頻文件

第二種方法是什麼,我相信會的工作最適合我,但是,我無法找到如何實現第二部分信息(寫入到視頻文件)。

任何人都可以指出我對一些網站,我學習如何做到這一點?我可以使用什麼類型的庫來編碼(?)我在OpenGL中渲染的幀中的視頻?

編輯

搜索更加一下這個之後,我相信ffmpeg的是要走的路。我發現this blog有一個顯然可以在Windows上工作的代碼。

我已經從網站上下載了ffmpeg,這樣我就可以執行命令,就像在這個例子中一樣。不幸的是,我的應用程序崩潰,沒有視頻正在創建。我檢查了文件指針是否有效,但不是,所以我認爲錯誤來自函數popen的執行。

我傳遞了與命令完全相同的參數,但仍然沒有有效的文件指針,關於可能發生什麼的任何想法?

事情是,我不想花很多時間編碼視頻編碼,因爲我有其他項目可以工作。

+0

我在編碼/解碼視頻文件方面並不是很有經驗,但我認爲你最好的選擇是尋找一個能爲你做到這一點的圖書館,而且你只需將數據傳遞給它。如果它的任何部分與我想象的音頻(哪個)相同,它不會變得微不足道。不幸的是,我不知道任何圖書館。 – Daniel 2014-09-27 17:22:51

+0

問題是,你並沒有要求特定的幫助。有很多庫能夠將一系列RGB圖像編碼成視頻流(ffmpeg,gstreamer,我非常確定OSX有本地的東西)。除非您要求提供有關這些庫的具體內容,否則此問題無意義。 – peppe 2014-09-28 20:18:07

回答

1

由於我無法直接從我的C++代碼使用ffmpeg,所以可能的解決方案如下。在Qt5中,您可以使用功能paintGL更新要渲染的幀。這之後,得到的像素與glReadPixels,然後只用QImage

void OpenGLViewer::paintGL() 
{ 
    // Clear screen 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    // Update array attached to OpenGL 

    glDrawArrays(GL_POINTS, 0, _points); 

    update(); 

    glReadPixels(0, 0, this->width(), this->height(), GL_RGBA, GL_UNSIGNED_BYTE, _buffer); 

    std::stringstream name; 
    name << "Frame" << _frame++ << ".png"; 
    QString filename(name.str().c_str()); 
    QImage imagen(_buffer, this->width(), this->height(), QImage::Format_ARGB32); 
    imagen.save(filename, "PNG"); 
} 

的圖像保存爲PNG圖像這將使用從下面的命令留在你的工作目錄中的一些圖片,你可以在視頻編碼控制檯

ffmpeg -framerate 30 -start_number 0 -i Frame%d.png -vcodec mpeg4 -vf vflip test.avi

我還是要查,爲什麼顏色反轉,但現在由於動畫是最重要的事情,而不是顏色能正常工作。

0

您可以在安裝libpng後以這種方式完成: uint8_t pixels = new uint8_t [w h * 3]; glReadPixels(0,0,w,h,GL_RGB,GL_UNSIGNED_BYTE,(GLvoid *)pixels);

for (int j = 0; j * 2 < h; ++j) { 
int x = j * w * 3; 
int y = (h - 1 - j) * w * 3; 
for (int i = w * 3; i > 0; --i) { 
    uint8_t tmp = pixels[x]; 
    pixels[x] = pixels[y]; 
    pixels[y] = tmp; 
    ++x; 
    ++y; 
    } 
} 

png_structp PNG = png_create_write_struct(PNG_LIBPNG_VER_STRING,nullptr,nullptr,nullptr); if(!png) return false;

png_infop info = png_create_info_struct(png); 
if (!info) { 
    png_destroy_write_struct(&png, &info); 
    return false; 
} 
std::string s = "IMAGE/"+string(filename); 
FILE *fp = fopen(s.c_str(), "wb"); 
if (!fp) { 
    png_destroy_write_struct(&png, &info); 
    return false; 
} 

png_init_io(png, fp); 
png_set_IHDR(png, info, w, h, 8 , PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, 
    PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); 
png_colorp palette = (png_colorp)png_malloc(png, PNG_MAX_PALETTE_LENGTH * sizeof(png_color)); 
if (!palette) { 
    fclose(fp); 
    png_destroy_write_struct(&png, &info); 
    return false; 
} 
png_set_PLTE(png, info, palette, PNG_MAX_PALETTE_LENGTH); 
png_write_info(png, info); 
png_set_packing(png); 

png_bytepp rows = (png_bytepp)png_malloc(png, h * sizeof(png_bytep)); 
for (int i = 0; i < h; ++i) 
    rows[i] = (png_bytep)(pixels + (h - i - 1) * w * 3); 

png_write_image(png, rows); 
png_write_end(png, info); 
png_free(png, palette); 
png_destroy_write_struct(&png, &info); 

fclose(fp); 
delete[] rows; 
+0

ffmpeg -framerate 30 -start_number 0 -i Frame%d.png -vcodec mpeg4 -vf vflip test.avi – user3059007 2015-04-23 00:50:04