Frage

Wie schreibe ich Bitmaps als Frames zu OGG Theora in C C ++?

Einige Beispiele mit Quelle wären ein Rost!)

War es hilfreich?

Lösung

Hier ist die libheora api und Beispielcode.

Hier ist ein Micro Howto Das zeigt, wie die Theora -Binärdateien verwendet werden. Wie der Encoder liest rohe, unkomprimierte 'yuv4mpeg' Daten für Video Sie können das auch aus Ihrer App verwenden, indem Sie die Videorahmen in den Encoder leiten.

Andere Tipps

Die gesamte Lösung ist ein wenig lang als Code -Beispiel zu veröffentlichen. Wenn Sie jedoch Libheora von xiPh.org herunterladen, gibt es ein Beispiel PNG2Theora. Alle Bibliotheksfunktionen, die ich kurz vorstellen werde, finden Sie in der Dokumentation auf XIPH.org für Theora und OGG.

  1. Rufen Sie th_info_init () an, um eine Th_info -Struktur zu initialisieren, und richten Sie dann Ihre Ausgabeparameter ein, indem Sie die entsprechenden Mitglieder darin zuweisen.
  2. Verwenden Sie diese Struktur in einem Aufruf an th_encode_alloc (), um einen Encoder -Kontext zu erhalten
  3. Initialisieren Sie einen OGG -Stream mit ogg_stream_init ()
  4. Initialisieren Sie eine leere TH_Comment -Struktur mit Th_Comment_init

Iterieren Sie die folgenden:

  1. Rufen Sie th_encode_flushheader mit dem Encoder -Kontext, der leeren Kommentarstruktur und einem OGG_PACKET auf.
  2. Senden Sie das resultierende Paket mit ogg_stream_packetin () an den OGG -Stream.

Bis th_encode_flushheader 0 (oder einen Fehlercode) zurückgibt.

Rufen Sie nun wiederholt ogg_stream_pageout () an, jedes Mal, wenn Sie die Seite und die Seite schreiben.

Sie können jetzt Frames in den Encoder schreiben. So hat ich es gemacht:

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;
}

Wobei Encoderinfo die Th_info -Struktur ist, mit der der Encoder initialisiert wird (statisch im Datenabschnitt für mich).

Wenn Sie in Ihrem letzten Frame den letzten Frame auf th_encode_packetout () festlegen, wird sichergestellt, dass der Stream ordnungsgemäß endet.

Sobald Sie fertig sind, stellen Sie einfach sicher, dass Sie aufräumen (hauptsächlich FDS schließen). th_info_clear () löscht die TH_INFO -Struktur und th_encode_free () befreien Ihren Encoder -Kontext.

Offensichtlich müssen Sie Ihre Bitmap in YUV -Flugzeuge umwandeln, bevor Sie sie an theora_write_frame () weitergeben können.

Ich hoffe, das ist etwas Hilfe. Viel Glück!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top