ogg packets get lost

Yorn <[email protected]>
Newsgroups gmane.comp.multimedia.ogg.theora.devel
Organization streamnik
Message-ID <[email protected]>
Hi,

I am actually working on a c++ wrapper for ogg/theora. It will be a small 
library to easily create command line tools to cut/cat video-files and to 
extract and join the video and audio stream etc.

However, I started the project and found some very strange behaviors:
I stored some ogg_packet objects (which are created on the heap) in a list.
When I make several calls to ogg_stream_pagein() and ogg_stream_packetout(), 
the packets are accidentally overwritten by some nonsense.

I am not sure what really happens, but I guess the libogg writers wanted to 
reduce the memory copy to a minimum, so that there are pointers (packet), 
which will be reused or whatever.

My question is: how do you (other developers) solve this problem? Creating a 
copy of the ogg_packet (including the areas, where the packet pointer directs 
to) would be a way. However I think I have to do the same for the ogg_pages!? 
Or are there any other, easier tricks to solve this problem?

Thanks in advance
Yorn

PS: I added the demo file, I created to figure out the problem

_______________________________________________
theora-dev mailing list
[email protected]
http://lists.xiph.org/mailman/listinfo/theora-dev
testStream.cpp (text/x-c++src, 5.1 KB)
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <list>

#include <ogg/ogg.h>

#define BUNCHSIZE 7096
#define uint32 unsigned int
#define int32  int

/* create a fancy debug output of the data */
std::string convertToString(ogg_packet* packet)
{
  std::stringstream stream;
  stream << "Packet: size=" << packet->bytes << " bos=" << packet->b_o_s << " eof="
         << packet->e_o_s << " granulePos=" << packet->granulepos << " packetNo="
         << packet->packetno;

  for (int32 c(0); c<packet->bytes; ++c) {
    if ((c%16) == 0)
      stream << std::endl;
    stream << " " << std::hex;
    if (((unsigned char) packet->packet[c]) < 16)
      stream << "0";
    stream << (unsigned int) ((unsigned char) packet->packet[c]);
  }

  stream << std::dec << std::endl;

  return(stream.str());
}

int main(int argc, char* argv[])
{
  if (argc != 2) {
    std::cerr << "usage: "<<argv[0]<<" <filename>\n";
    return(-1);
  }

  FILE* fileDescriptor;
  if (! (fileDescriptor = fopen(argv[1], "r"))) {
    std::cerr << "Error: could not open file <"<<argv[1]<<">\n";
    return(-1);
  }

  ogg_sync_state oggSyncState;
  ogg_sync_init(&oggSyncState);

  /* read a bunch of data from file and place it into the ogg buffer */

  char* buffer = ogg_sync_buffer(&oggSyncState, BUNCHSIZE);

  int realSize;
  if ( (realSize = fread(buffer, 1, BUNCHSIZE, fileDescriptor)) < 0) {
    std::cerr << "Can not read any data from file\n";
    fclose(fileDescriptor);
    return(-1);
  }

  ogg_sync_wrote(&oggSyncState, realSize);

  bool moreData(true);
  std::vector<ogg_page*> oggPageList;

  /* grap the first few pages (this is only an example)*/

  while (moreData) {

    /* extract ogg page */
    ogg_page* oggPage = new ogg_page;
    int retval = ogg_sync_pageout(&oggSyncState, oggPage);

    switch (retval) {

     case -1:
      std::cerr << "OggDecoder::getNextPages: stream is not in sync - skipping bytes\n";
      /* no break */

     case 1:
      oggPageList.push_back(oggPage);
      break;

     case 0:
     default:
      delete oggPage;
      moreData = false;
      break;

    }
  }

  /* we believe that the first two pages are the bos pages for theora and vorbis */
  ogg_stream_state oggTheoraStreamState;
  ogg_stream_state oggVorbisStreamState;

  int32 theoraSerial(ogg_page_serialno(oggPageList[0]));
  int32 vorbisSerial(ogg_page_serialno(oggPageList[1]));

  ogg_stream_init(&oggTheoraStreamState, theoraSerial);
  ogg_stream_init(&oggVorbisStreamState, vorbisSerial);

  /* we have a number of pages in our list, now extract the packets */
  std::list<ogg_packet*> oggTheoraPacketList;
  std::list<ogg_packet*> oggVorbisPacketList;


  for(unsigned int i(0); i<oggPageList.size(); ++i) {

    /* handle theora information */
    if (ogg_page_serialno(oggPageList[i]) == theoraSerial) {

      /* insert data into the corresponding stream */
      if (ogg_stream_pagein(&oggTheoraStreamState, oggPageList[i]) != -1) {

        int32 retValue;

        while(1==1) {

          /* try to get the next ogg packet within this stream */
          ogg_packet* oggPacket = new ogg_packet;
          retValue = ogg_stream_packetout(&oggTheoraStreamState, oggPacket);

          /* is there no new packet available stop the loop */
          if (retValue == 0) {
            delete oggPacket;
            break;
          }

          /* report if stream is out of sync */
          if (retValue == -1)
            std::cerr << "stream is not in sync\n";

          std::cout << convertToString(oggPacket);

          oggTheoraPacketList.push_back(oggPacket);
        }
      }
      else
        std::cerr << "can not import page\n";

    }

    /* handle vorbis information */
    if (ogg_page_serialno(oggPageList[i]) == vorbisSerial) {

      /* insert data into the corresponding stream */
      if (ogg_stream_pagein(&oggVorbisStreamState, oggPageList[i]) != -1) {

        int32 retValue;

        while(1==1) {

          /* try to get the next ogg packet within this stream */
          ogg_packet* oggPacket = new ogg_packet;
          retValue = ogg_stream_packetout(&oggVorbisStreamState, oggPacket);

          /* is there no new packet available stop the loop */
          if (retValue == 0) {
            delete oggPacket;
            break;
          }

          /* report if stream is out of sync */
          if (retValue == -1)
            std::cerr << "stream is not in sync\n";

          std::cout << convertToString(oggPacket);

          oggVorbisPacketList.push_back(oggPacket);
        }
      }
      else
        std::cerr << "can not import page\n";

    }

  }

  std::cout << "\n\n Theora -----------------------------------------------------------\n\n";

  std::list<ogg_packet*>::iterator theoraIt = oggTheoraPacketList.begin();

  for(; theoraIt!=oggTheoraPacketList.end(); ++theoraIt) {
    std::cout << convertToString(*theoraIt);
  }

  std::cout << "\n\n Vorbis -----------------------------------------------------------\n\n";

  std::list<ogg_packet*>::iterator vorbisIt = oggVorbisPacketList.begin();

  for(; vorbisIt!=oggVorbisPacketList.end(); ++vorbisIt) {
    std::cout << convertToString(*vorbisIt);
  }

  // delete all packets and pages
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.