[ogg-dev] How to fix broken ogg/theora files

yorn at gmx.net yorn at gmx.net
Wed Dec 10 09:32:08 PST 2008


I added a patch which should work with the actual release 0.5 of the OggVideoTools, which can be found here: http://dev.streamnik.de/files.html

Please let me know, if it there is any trouble with it.
- Yorn

> I haven't been on this list until now, so I wasn't aware of this problem
> until last night ;-) - sorry for that. 
> 
> I am working on a patch for oggCut for that issue (looks good actually but
> I would like to do some testing befor I can release a patch.)
> 
> Normal players are not effected by the page time misordering, so I took
> this issue as "minor". The reason for the misordering is that oggCut works on
> per-packet basis. Therefor there is usually a small time offset between
> the audio and video.
> The packet are delivered to the muxer in the way they are received from
> the demuxer, so in some cases, the packets will not be in the right order any
> more and therefor the packets are not ordered correctly.
> 
> I give an additional buffer (500ms) to oggCut, so that packets can be
> reordered. I think this will solve the problem.
> 
> BTW oggCut cuts at keyframes, if you want to cut a video 100% perfect, I
> would suggest to use a video cut program.
> 
> - Yorn
> 
> 
> _______________________________________________
> ogg-dev mailing list
> ogg-dev at xiph.org
> http://lists.xiph.org/mailman/listinfo/ogg-dev
-------------- next part --------------
Index: oggCut.cpp
===================================================================
RCS file: /home/CVS/OggVideoTools/src/oggCut.cpp,v
retrieving revision 1.2
diff -r1.2 oggCut.cpp
31a32,43
> struct ListElement {
>   double time;
>   OggPacket packet;
>   ListElement(double _time, OggPacket _packet) :
>     time(_time), packet(_packet)
>   {
>   }
> };
> 
> static std::list<ListElement> packetList;
> static double bufferTime(0.5); // buffer 500 ms
> 
34,43c46,77
<   std::cerr << "usage: " << progName << "[options]\n"
<             << "Options are:\n"
<             << " -i input    : Input file\n"
<             << " -o output   : Output file\n"
<             << " -s time     : Start time in milliseconds from start\n"
<             << "               if no start time is given, 0 is assumed\n"
<             << " -e time     : End time in milliseconds\n"
<             << "               if no end time or -1 is given, the end of the\n"
<             << "               file is assumed as the end\n"
<             << " -l length   : Length of the cut area\n";
---
>   std::cerr << "usage: "<< progName << "[options]\n"<< "Options are:\n"
>       << " -i input    : Input file\n"<< " -o output   : Output file\n"
>       << " -s time     : Start time in milliseconds from start\n"
>       << "               if no start time is given, 0 is assumed\n"
>       << " -e time     : End time in milliseconds\n"
>       << "               if no end time or -1 is given, the end of the\n"
>       << "               file is assumed as the end\n"
>       << " -l length   : Length of the cut area\n";
> }
> 
> void bufferedOutput(StreamMux& streamMux, double time, OggPacket packet)
> {
>   ListElement elem(time, packet);
> 
>   std::list<ListElement>::iterator iter(packetList.begin());
>   while ((iter != packetList.end()) && (elem.time < iter->time))
>     ++iter;
>   packetList.insert(iter, elem);
> 
>   double lastTime(packetList.front().time);
>   while ((lastTime - packetList.back().time) > bufferTime) {
>     streamMux << packetList.back().packet;
>     packetList.pop_back();
>   }
> }
> 
> void flushBuffer(StreamMux& streamMux)
> {
>   while (!packetList.empty()) {
>     streamMux << packetList.back().packet;
>     packetList.pop_back();
>   }
59c93
<   switch (opt) {
---
>     switch (opt) {
62,63c96,97
<     printHelpScreen(programName);
<     exit(-1);
---
>       printHelpScreen(programName);
>       exit(-1);
66,67c100,101
<     inputFile = std::string(optarg);
<     break;
---
>       inputFile = std::string(optarg);
>       break;
70,71c104,105
<     outputFile = std::string(optarg);
<     break;
---
>       outputFile = std::string(optarg);
>       break;
74,75c108,109
<     startTime = atoi(optarg);
<     break;
---
>       startTime = atoi(optarg);
>       break;
78,79c112,113
<     endTime = atoi(optarg);
<     break;
---
>       endTime = atoi(optarg);
>       break;
82,83c116,117
<     length = atoi(optarg); // yes, I know the atoi bug
<     break;
---
>       length = atoi(optarg); // yes, I know the atoi bug
>       break;
85c119
<   }
---
>     }
90,91c124,126
<     std::cerr << "Error: please define an input and output file with -i and -o\n\n";
<     return(-1);
---
>     std::cerr
>         << "Error: please define an input and output file with -i and -o\n\n";
>     return (-1);
96c131
<     return(-1);
---
>     return (-1);
102,103c137
<     }
<     else {
---
>     } else {
106c140
<         return(-1);
---
>         return (-1);
123c157
<     return(-1);
---
>     return (-1);
132a167,170
>   /* create the time synchronizer */
>   std::vector<double> offset;
>   offset.resize(streamConfigList.size());
> 
135c173,176
<     std::cerr << streamConfigList[i].parameter->toString();
---
>     StreamConfig& conf(streamConfigList[i]);
>     std::cerr << "Stream No: "<<(int)conf.streamNo<<"(0x"<<std::hex
>         << conf.serialNo<<std::dec<<")\n"
>         << streamConfigList[i].parameter->toString();
137a179
>     offset[i] = -1;
143a186
>   double beginTime(0);
148c191
<   while(1==1) {
---
>   while (streamSerializer.available()) {
155,158c198,205
<       if ((!foundTheora) || ((packet.getStreamType() == ogg_theora) &&
<           (!(packet.data()[0] & 0x40))))
<         startMarker = true;
< 
---
>       if (!startMarker) {
>         if ((!foundTheora) || ((packet.getStreamType() == ogg_theora)
>             &&(!(packet.data()[0] & 0x40)))) {
>           startMarker = true;
>           beginTime = time;
>           offset[packet.getStreamNo()] = time;
>         }
>       }
161,162c208,217
<         // std::cerr << packet.print(2);
<         streamMux << packet;
---
> 
>         /* if this stream has no offset calculated, do it now */
>         if (offset[packet.getStreamNo()] < 0) {
>           offset[packet.getStreamNo()] = time;
>           /*          std::cout << "offset for stream <"<<(int)packet.getStreamNo()
>            <<"> is "<<offset[packet.getStreamNo()] - beginTime <<std::endl;
>            */
>         }
> 
>         bufferedOutput(streamMux, (time - offset[packet.getStreamNo()]), packet);
167a223
>       flushBuffer(streamMux);
Index: streamMux.cpp
===================================================================
RCS file: /home/CVS/OggVideoTools/src/streamMux.cpp,v
retrieving revision 1.3
diff -r1.3 streamMux.cpp
49c49
<  : repository(_repository)
---
>  : timeOfLastPage(0.0), repository(_repository)
133c133
<     OggPage nextPage = outputPageList.front();
---
>     OggPage nextPage = outputPageList.back().page;
146a147
>     outputPageList.pop_back();
148d148
<     outputPageList.pop_front();
156d155
< 
163c162
<     OggPage nextPage = outputPageList.front();
---
>     OggPage nextPage = outputPageList.back().page;
171d169
< //      std::cout << nextPage.print(3);
180c178
<     outputPageList.pop_front();
---
>     outputPageList.pop_back();
220,221d217
< //  std::cout << "write page <" << streamList[nextID].nextPage.serialno() << "> with time <"<<nextTime<<">\n";
< 
223c219,229
<   outputPageList.push_back(streamList[nextID].nextPage);
---
>   OutputElement elem(streamList[nextID].nextPage, streamList[nextID].nextTime);
> 
>   std::list<OutputElement>::iterator iter(outputPageList.begin());
> 
>   // -1 is a problem!
>   if (elem.time < 0) {
>       elem.time = timeOfLastPage; // should we care for the stream No?
>   }
> 
>   while((iter != outputPageList.end()) && (elem.time < iter->time))
>     ++iter;
225c231,235
<   // mark the entry as free
---
>   outputPageList.insert(iter, elem);
> 
>   timeOfLastPage = elem.time;
> 
>   // page has been added to the output list, mark the entry as free
267,268d276
< //    std::cerr << "configuring stream <" << i <<">\n";
< 
303,307d310
< 
< //  std::cout << "inserting packet to stream <"<<(int)packet.getStreamNo()<<"> with time "
< //            << entry.posInterpreter->getActTime()<<"\n";
< 
< 
Index: streamMux.h
===================================================================
RCS file: /home/CVS/OggVideoTools/src/streamMux.h,v
retrieving revision 1.2
diff -r1.2 streamMux.h
72a73,81
>     struct OutputElement {
>       OggPage page;
>       double  time;
>       OutputElement(OggPage _page, double _time)
>         : page(_page), time(_time) {}
>     };
> 
>     double           timeOfLastPage;
> 
77c86,87
<     std::list<OggPage> outputPageList;
---
>     //std::list<OggPage> outputPageList;
>     std::list<OutputElement> outputPageList;


More information about the ogg-dev mailing list