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
}