[matroska] r770 - trunk/DvdMenuXtractor

[email protected]
Newsgroups gmane.comp.multimedia.matroska.cvs
Message-ID <[email protected]>
Author: robux4
Date: 2004-09-09 15:29:53 +0400 (Thu, 09 Sep 2004)
New Revision: 770

Modified:
   trunk/DvdMenuXtractor/DvdMenuXtractor.cpp
Log:
code factorisation, better handling of start/stop timecodes

Modified: trunk/DvdMenuXtractor/DvdMenuXtractor.cpp
===================================================================
--- trunk/DvdMenuXtractor/DvdMenuXtractor.cpp	2004-09-09 08:58:31 UTC (rev 769)
+++ trunk/DvdMenuXtractor/DvdMenuXtractor.cpp	2004-09-09 11:29:53 UTC (rev 770)
@@ -869,6 +869,10 @@
 		return result;
 	}
 
+	uint64_t OutputProgram(int lvl, wxTextFile & XmlFile, const pgc_program_map_t * program, uint64_t start_time)
+	{
+	}
+	
 	uint64_t OutputPGC(int lvl, wxTextFile & XmlFile, const pgc_t * pgc, uint64_t start_time, uint16_t pgc_num, unsigned char pgc_type)
 	{
 		static unsigned char _PrivatePGC[] = {0x20, 0x00, 0x00, 0x00};
@@ -890,15 +894,77 @@
 		// PGC commands
 		AddCommands(lvl, XmlFile, pgc->command_tbl);
 
-		// TODO: handle the PROGRAMS in the PGC
+		// TODO: handle the PROGRAMS/Cells in the PGC
+		for (int i=0; i< pgc->nr_of_programs; i++)
+		{
+			XmlFile.AddLine(IndentString(lvl)+"<!-- Program #"+wxString::Format("%d",i)+" in this PGC -->");
+			XmlFile.AddLine(IndentString(lvl)+"<ChapterAtom>");
+				lvl++;
+				// TODO
+				OutputProgram(lvl, XmlFile, &pgc->program_map[i], start_time);
+				lvl--;
+			XmlFile.AddLine(IndentString(lvl)+"</ChapterAtom>");
+		}
 
-		// TODO: PGC start/end times
-		XmlFile.AddLine(IndentString(lvl)+"<ChapterTimeStart>00:00:00.000000000</ChapterTimeStart>");
-		XmlFile.AddLine(IndentString(lvl)+"<ChapterTimeEnd>00:00:00.000000000</ChapterTimeEnd>");
+		// PGC start/end times
+		DisplayTime(lvl, XmlFile, start_time, start_time+ DvdTimecodeToNano(pgc->playback_time));
 		lvl--;
-		return start_time;
+		return start_time + DvdTimecodeToNano(pgc->playback_time);
 	}
+	
+// Macro to convert Binary Coded Decimal to Decimal
+#define BCD2D(__x__) (((__x__ & 0xf0) >> 4) * 10 + (__x__ & 0x0f))
 
+	uint64_t DvdTimecodeToNano(dvd_time_t dtime)
+	{
+		uint64_t nano_duration = 0;
+		nano_duration += uint64_t(BCD2D(dtime.hour)) * 60 * 60 * 1000000000;
+		nano_duration += uint64_t(BCD2D(dtime.minute)) * 60 * 1000000000;
+		nano_duration += uint64_t(BCD2D(dtime.second)) * 1000000000;
+
+		float fps;
+		switch((dtime.frame_u & 0xc0) >> 6) 
+		{
+		case 1:
+			fps = 25.0;
+			break;
+		case 3:
+			fps = 29.97;
+			break;
+		default:
+			fps = 2500.0;
+			assert(0);
+			break;
+		}
+		double _ms = BCD2D(dtime.frame_u&0x3f) * 1000.0 / fps;
+		nano_duration += uint64_t(_ms * 1000000.0);
+		
+		return nano_duration;
+	}
+	
+	/// times in nanoseconds
+	void DisplayTime(int lvl, wxTextFile & XmlFile, uint64_t start_time, uint64_t end_time)
+	{
+		int hour, min, sec;
+		uint32_t nano;
+		
+		nano = start_time % 1000000000;
+		start_time /= 1000000000;
+		sec = start_time % 60;
+		start_time /= 60;
+		min = start_time % 60;
+		hour = start_time / 60;
+		XmlFile.AddLine(IndentString(lvl)+"<ChapterTimeStart>"+wxString::Format("%02d:%02d:%02d.%09d", hour, min, sec, nano)+"</ChapterTimeStart>");
+		
+		nano = end_time % 1000000000;
+		end_time /= 1000000000;
+		sec = end_time % 60;
+		end_time /= 60;
+		min = end_time % 60;
+		hour = end_time / 60;
+		XmlFile.AddLine(IndentString(lvl)+"<ChapterTimeEnd>"+wxString::Format("%02d:%02d:%02d.%09d", hour, min, sec, nano)+"</ChapterTimeEnd>");
+	}
+
 	void GenerateXMLScript()
 	{
 		CellListElem* cle;
@@ -923,6 +989,7 @@
 		XmlFile.AddLine("");
 
 		int lvl = 0, i,j;
+		uint64_t timecode_startA = 0, timecode_endA = 0;
 
 		XmlFile.AddLine("<Chapters>");
 		lvl++;
@@ -941,8 +1008,7 @@
 					wxString _myUID = CreateUID();
 					XmlFile.AddLine(IndentString(lvl)+"<ChapterUID>"+_myUID+"</ChapterUID>");
 					// the First Play PGC has no cell and no time
-					XmlFile.AddLine(IndentString(lvl)+"<ChapterTimeStart>00:00:00.000000000</ChapterTimeStart>");
-					XmlFile.AddLine(IndentString(lvl)+"<ChapterTimeEnd>00:00:00.000000000</ChapterTimeEnd>");
+					DisplayTime(lvl, XmlFile, timecode_startA, timecode_endA);
 					// display the UID for the lazy rippers
 					XmlFile.AddLine(IndentString(lvl)+"<ChapterDisplay>");
 						lvl++;
@@ -958,6 +1024,8 @@
 				lvl--;
 			}
 			
+			timecode_startA = timecode_endA;
+			
 			// Language Units
 			if (IfoFile->LanguageUnits() && IfoFile->LanguageUnits()->nr_of_lus)
 			{
@@ -967,8 +1035,8 @@
 					lvl++;
 					wxString _myUIDa = CreateUID();
 					XmlFile.AddLine(IndentString(lvl)+"<ChapterUID>"+_myUIDa+"</ChapterUID>");
-					XmlFile.AddLine(IndentString(lvl)+"<ChapterTimeStart>00:00:00.000000000</ChapterTimeStart>");
 					XmlFile.AddLine(IndentString(lvl)+"<ChapterProcessPrivate>"+encodebase64(_PrivateVM,2)+"</ChapterProcessPrivate>");
+					uint64_t timecode_startB = timecode_startA, timecode_endB = timecode_startA;
 					for (i=0 ;i<IfoFile->LanguageUnits()->nr_of_lus; i++)
 					{
 						XmlFile.AddLine(IndentString(lvl)+"<!-- Language Units -->");
@@ -983,7 +1051,6 @@
 
 							wxString _myUIDb = CreateUID();
 							XmlFile.AddLine(IndentString(lvl)+"<ChapterUID>"+_myUIDb+"</ChapterUID>");
-							XmlFile.AddLine(IndentString(lvl)+"<ChapterTimeStart>00:00:00.000000000</ChapterTimeStart>");
 							XmlFile.AddLine(IndentString(lvl)+"<ChapterProcessPrivate>"+encodebase64(_PrivateLU,4)+"</ChapterProcessPrivate>");
 							// display the UID for the lazy rippers
 							XmlFile.AddLine(IndentString(lvl)+"<ChapterDisplay>");
@@ -994,25 +1061,28 @@
 							
 							if (_LU.pgcit)
 							{
-								uint64_t timecode = 0;
 								for (j=0; j<_LU.pgcit->nr_of_pgci_srp; j++)
 								{
 									const pgci_srp_t &_PGC_SRP = _LU.pgcit->pgci_srp[j];
-									XmlFile.AddLine(IndentString(lvl)+"<!-- PGC type "+GetPGCType(_PGC_SRP.entry_id)+" -->");
+									XmlFile.AddLine("\n"+IndentString(lvl)+"<!-- PGC type "+GetPGCType(_PGC_SRP.entry_id)+" -->");
 									XmlFile.AddLine(IndentString(lvl)+"<ChapterAtom>");
-									timecode += OutputPGC(lvl, XmlFile, _PGC_SRP.pgc, timecode, j, _PGC_SRP.entry_id);
+									timecode_endB = OutputPGC(lvl, XmlFile, _PGC_SRP.pgc, timecode_endB, j, _PGC_SRP.entry_id);
 									XmlFile.AddLine(IndentString(lvl)+"</ChapterAtom>");
 								}
 							}
-
+						DisplayTime(lvl, XmlFile, timecode_startB, timecode_endB);
+						timecode_startB = timecode_endB;
+						timecode_endA = timecode_endB;
 						lvl--;
 					}
 					XmlFile.AddLine(IndentString(lvl)+"</ChapterAtom>");
+					DisplayTime(lvl, XmlFile, timecode_startA, timecode_endA);
 					lvl--;
 				XmlFile.AddLine(IndentString(lvl)+"</ChapterAtom>");
 				lvl--;
 			}
 
+			timecode_startA = timecode_endA;
 
 			// Write the Video Manager
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.