簡體   English   中英

如何將位圖作為幀寫入C \\ C ++中的Ogg Theora?

[英]How to write bitmaps as frames to Ogg Theora in C\C++?

如何將位圖作為幀寫入C \\ C ++中的Ogg Theora?

一些來源的例子將是格柵!)

整個解決方案有點冗長,可以在這里作為代碼示例發布,但如果你從Xiph.org下載libtheora,就會有一個例子png2theora。 我將要提到的所有庫函數都可以在Xiph.org上關於theora和ogg的文檔中找到。

  1. 調用th_info_init()來初始化th_info結構,然后通過在其中分配適當的成員來設置輸出參數。
  2. 在調用th_encode_alloc()時使用該結構來獲取編碼器上下文
  3. 使用ogg_stream_init()初始化ogg流
  4. 使用th_comment_init初始化空白的th_comment結構

通過以下方式迭代:

  1. 使用編碼器上下文,空白注釋結構和ogg_packet調用th_encode_flushheader。
  2. 使用ogg_stream_packetin()將生成的數據包發送到ogg流

直到th_encode_flushheader返回0(或錯誤代碼)

現在,每次重復調用ogg_stream_pageout(),每次將page.header和page.body寫入輸出文件,直到它返回0.現在調用ogg_stream_flush並將結果頁面寫入文件。

您現在可以將幀寫入編碼器。 我是這樣做的:

int theora_write_frame(int outputFd, unsigned long w, unsigned long h, unsigned char *yuv_y, unsigned char *yuv_u, unsigned char *yuv_v, int last)
{
  th_ycbcr_buffer ycbcr;
  ogg_packet op;
  ogg_page og;

  unsigned long yuv_w;
  unsigned long yuv_h;

  /* Must hold: yuv_w >= w */
  yuv_w = (w + 15) & ~15;
  /* Must hold: yuv_h >= h */
  yuv_h = (h + 15) & ~15;

  //Fill out the ycbcr buffer
  ycbcr[0].width = yuv_w;
  ycbcr[0].height = yuv_h;
  ycbcr[0].stride = yuv_w;
  ycbcr[1].width = yuv_w;
  ycbcr[1].stride = ycbcr[1].width;
  ycbcr[1].height = yuv_h;
  ycbcr[2].width = ycbcr[1].width;
  ycbcr[2].stride = ycbcr[1].stride;
  ycbcr[2].height = ycbcr[1].height;

  if(encoderInfo->pixel_fmt == TH_PF_420)
  {
    //Chroma is decimated by 2 in both directions
    ycbcr[1].width = yuv_w >> 1;
    ycbcr[2].width = yuv_w >> 1;
    ycbcr[1].height = yuv_h >> 1;
    ycbcr[2].height = yuv_h >> 1;
  }else if(encoderInfo->pixel_fmt == TH_PF_422)
  {
    ycbcr[1].width = yuv_w >> 1;
    ycbcr[2].width = yuv_w >> 1;
  }else if(encoderInfo->pixel_fmt != TH_PF_422)
  {
    //Then we have an unknown pixel format
    //We don't know how long the arrays are!
    fprintf(stderr, "[theora_write_frame] Unknown pixel format in writeFrame!\n");
    return -1;
  }

  ycbcr[0].data = yuv_y;
  ycbcr[1].data = yuv_u;
  ycbcr[2].data = yuv_v;

  /* Theora is a one-frame-in,one-frame-out system; submit a frame
     for compression and pull out the packet */
  if(th_encode_ycbcr_in(encoderContext, ycbcr)) {
    fprintf(stderr, "[theora_write_frame] Error: could not encode frame\n");
    return -1;
  }

  if(!th_encode_packetout(encoderContext, last, &op)) {
    fprintf(stderr, "[theora_write_frame] Error: could not read packets\n");
    return -1;
  }

  ogg_stream_packetin(&theoraStreamState, &op);
  ssize_t bytesWritten = 0;
  int pagesOut = 0;
  while(ogg_stream_pageout(&theoraStreamState, &og)) {
    pagesOut ++;
    bytesWritten = write(outputFd, og.header, og.header_len);
    if(bytesWritten != og.header_len)
    {
      fprintf(stderr, "[theora_write_frame] Error: Could not write to file\n");
      return -1;
    }
    bytesWritten = write(outputFd, og.body, og.body_len);
    if(bytesWritten != og.body_len)
    {
      bytesWritten = fprintf(stderr, "[theora_write_frame] Error: Could not write to file\n");
      return -1;
    }
  }
  return pagesOut;
}

其中encoderInfo是用於初始化編碼器的th_info結構(對於我來說,數據部分是靜態的)。

在最后一幀上,在th_encode_packetout()上設置最后一幀將確保流正確終止。

一旦完成,只需確保清理(主要關閉fds)。 th_info_clear()將清除th_info結構,th_encode_free()將釋放您的編碼器上下文。

顯然,您需要先將位圖轉換為YUV平面,然后才能將它們傳遞給theora_write_frame()。

希望這個對你有幫助。 祝好運!

這是libtheora API示例代碼

這是一個顯示如何使用theora二進制文件的指南。 當編碼器讀取視頻的原始未壓縮“yuv4mpeg”數據時,您也可以通過將視頻幀傳輸到編碼器來使用應用程序中的數據

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM