Question

Comment écrire des bitmaps comme cadres à Ogg Theora en C \ C ++?

Quelques exemples avec la source serait grille!)

Était-ce utile?

La solution

Voici le API libtheora et exemple de code .

Voici un micro howto qui montre comment utiliser la binaires Theora. Comme l'encodeur lit brutes non compressées, les données « yuv4mpeg » pour la vidéo vous pouvez utiliser que de votre application aussi en canalisant les images vidéo au codeur.

Autres conseils

La solution complète est un peu long pour poster ici comme un exemple de code, mais si vous téléchargez libtheora de Xiph.org, il est un exemple png2theora. Toutes les fonctions de la bibliothèque que je vais parler se trouvent dans la documentation sur Xiph.org pour Theora et ogg.

  1. Appel th_info_init () pour initialiser une structure th_info, puis configurer les paramètres de sortie vous en affectant les membres appropriés à cet égard.
  2. Utilisez cette structure dans un appel à th_encode_alloc () pour obtenir un contexte codeur
  3. Initialiser un courant d'ogg, avec ogg_stream_init ()
  4. Initialiser une structure th_comment vierge à l'aide th_comment_init

itérer les éléments suivants:

  1. Appel th_encode_flushheader avec le contexte de l'encodeur, la structure de commentaire vide et un ogg_packet.
  2. Envoyer le paquet résultant au flux ogg avec ogg_stream_packetin ()

Jusqu'à th_encode_flushheader la valeur 0 (ou un code d'erreur)

Maintenant, appelez à plusieurs reprises ogg_stream_pageout (), à chaque fois que l'écriture du page.header puis page.body à un fichier de sortie, jusqu'à ce qu'il retourne 0. appeler maintenant ogg_stream_flush et écrire la page qui le fichier.

Vous pouvez maintenant écrire images à l'encodeur. Voici comment je l'ai fait:

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

Où encoderInfo est la structure de th_info utilisé pour initialiser le codeur (statique dans la section de données pour moi).

Sur votre dernière image, le réglage de la dernière image sur th_encode_packetout () fera en sorte que le flux se termine correctement.

Une fois que vous avez terminé, il suffit de nettoyer (principalement la fermeture fds). th_info_clear () efface la structure th_info et th_encode_free () libérera votre contexte du codeur.

De toute évidence, vous devrez convertir votre bitmap en plans YUV avant de pouvoir les transmettre à theora_write_frame ().

Espérons que cela est d'un peu d'aide. Bonne chance!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top