OSDN Git Service

implement PesFile::OpenFile() in TsToPes
[tsremuxcpp/developing01.git] / src / Mkv.cc
index 7a92e9d..d3541ea 100644 (file)
 
 namespace TsRemux
 {
-  static const signed long long vsint_subtr[] = {
+  static const Int64 vsint_subtr[] = {
     0x3fLL, 0x1ffffLL, 0xfffffLL, 0x7ffffffLL, 0x3ffffffffLL,
     0x1ffffffffffLL, 0xffffffffffffffLL, 0x7fffffffffffffLL };
 
-EbmlElement::EbmlElement(signed long long id, signed long long size, signed long long pos, Stream& fs)
+EbmlElement::EbmlElement(Int64 id, Int64 size, Int64 pos, boost::shared_ptr<Stream> fs)
 {
-    return;
+       SetId(id);
+       SetSize(size);
+       SetPos(pos);
+       SetStream(fs);
 }
 
-EbmlElement* EbmlElement::ParseEbml(Stream& fs)
-{
-    
-    return NULL;
+boost::shared_ptr<EbmlElement> EbmlElement::ParseEbml(boost::shared_ptr<Stream> fs)
+{
+       Int64 pos = fs.get()->Position;
+       EbmlElement ebml = null;
+       if (!fs || fs.Length == 0)
+               return null;
+       int b = fs.ReadByte();
+       if (b == -1)
+               goto cleanup;
+       int len = VintLength((byte)b);
+       if ((fs.Length - fs.Position) < (Int64)len)
+               goto cleanup;
+       fs.Position -= 1;
+       Int64 id = 0;
+       for (int i = 0; i < len; i++)
+       {
+               id <<= 8;
+               id |= (byte)fs.ReadByte();
+       }
+       b = fs.ReadByte();
+       if (b == -1)
+               goto cleanup;
+       len = VintLength((byte)b);
+       if ((fs.Length - fs.Position) < (Int64)len)
+               goto cleanup;
+       fs.Position -= 1;
+       Int64 size = VintToInt64(fs);
+       if ((fs.Length - fs.Position) < size)
+               goto cleanup;
+       ebml = new EbmlElement(id, size, fs.Position, fs);
+       
+cleanup:
+       fs.Position = pos;
+       return ebml;
 }
 
-char EbmlElement::VintLength(char vint)
+byte EbmlElement::VintLength(byte vint)
 {
-    return 'A';
+       byte len = 1;
+       for (int i = 7; (((vint >> i) & 0x01) == 0) && i >= 0; i--)
+               len++;
+       return len;
 }
 
-signed long long EbmlElement::VintToInt64(Stream& fs)
+Int64 EbmlElement::VintToInt64(boost::shared_ptr<Stream> fs)
 {
-    return 1;
+       byte b = (byte)fs.ReadByte();
+       int len = VintLength(b);
+       Int64 ret = (((1 << (8 - len)) - 1) & b) << (8 * (len - 1));
+       for (int i = 1; i < len; i++)
+               ret += (((byte)fs.ReadByte()) << (8 * (len - 1 - i)));
+       return ret;
 }
 
 MkvPesFile::MkvPesFile(BackgroundWorker& bw)
 {
-    return;
+       Clusters = new SortedList<long, EbmlElement>();
+       TrackList = new Dictionary<ushort, TrackInfo>();
+       CurrentIndex = -1;
 }
 
-TrackInfo::TrackInfo(unsigned short pid, std::string codec, char* data, EbmlElement& info)
+TrackInfo::TrackInfo(ushort pid, std::string codec, pByte data, EbmlElement& info)
 {
-    return;
+       this.pid = pid;
+       this.codec = codec;
+       this.data = data;
+       this.info = info;
 }
 
 PesPacket* MkvPesFile::GetNextPesPackets(void)
 {
-    return NULL;
+       if (CurrentIndex >= Clusters.Keys.Count)
+               return null;
+       EbmlElement cluster = Clusters[Clusters.Keys[CurrentIndex]];
+       EbmlElement[] blocks = cluster.Children;
+       List<PesPacket> packList = new List<PesPacket>();
+       Int64 clock = GetClusterClock(cluster);
+       if (pcrDelegate != null)
+               pcrDelegate(clock * (Constants.MPEG2TS_CLOCK_RATE / 1000));
+       foreach (EbmlElement bl in blocks)
+       {
+               EbmlElement block = null;
+               switch (bl.Id)
+               {
+                       case 0xa0: // block group
+                               EbmlElement[] cbls = bl.Children;
+                               foreach (EbmlElement bl2 in cbls)
+                               if (bl2.Id == 0xa1)
+                               {
+                                       block = bl2;
+                                       break;
+                               }
+                               break;
+                       case 0xa3:
+                               block = bl;
+                               break;
+               }
+               if (null != block)
+               {
+                       Stream stm = block.DataStream;
+                       Int64 endPos = stm.Position + block.Size;
+                       Int64 track = EbmlElement.VintToInt64(stm);
+                       Int16 time = (short)stm.ReadByte();
+                       time <<= 8;
+                       time += (short)stm.ReadByte();
+                       Int64 pts = clock + time;
+                       pts *= 90;
+                       byte flags = (byte)stm.ReadByte();
+                       LacingType lacing = (LacingType)((flags >> 1) & 0x03);
+                       if (lacing != LacingType.NoLacing && lacing != LacingType.FixedSizeLacing)
+                               throw new FormatException("Variable lacing is not yet supported");
+                       if (lacing == LacingType.FixedSizeLacing)
+                               stm.Position += 1;
+                       byte[] data = new byte[endPos - stm.Position];
+                       stm.Read(data, 0, (int)(endPos - stm.Position));
+                       if (data.Length > 0 && TrackList.ContainsKey((ushort)track))
+                       {
+                               TrackInfo ti = TrackList[(ushort)track];
+                               if (ptsDelegate != null)
+                                       ptsDelegate(pts, ti.pid);
+                               switch (sis[(ushort)track - 1].StreamType)
+                               {
+                                       case ElementaryStreamTypes.AUDIO_STREAM_AC3:
+                                               packList.Add(BuildAc3Pes(pts, data, ti.pid));
+                                               break;
+                                       case ElementaryStreamTypes.AUDIO_STREAM_DTS:
+                                               packList.Add(BuildDtsPes(pts, data, ti.pid));
+                                               break;
+                                       case ElementaryStreamTypes.VIDEO_STREAM_MPEG2:
+                                               packList.Add(BuildMpeg2Pes(pts, data, ti.pid));
+                                               break;
+                                       case ElementaryStreamTypes.VIDEO_STREAM_H264:
+                                               packList.Add(BuildAvcPes(pts, data, ti.pid));
+                                               break;
+                                       case ElementaryStreamTypes.VIDEO_STREAM_VC1:
+                                               packList.Add(BuildVc1Pes(pts, data, ti.pid));
+                                               break;
+                               }
+                       }
+               }
+       }
+       CurrentIndex++;
+       if(packList.Count == 0)
+               return null;
+       return packList.ToArray();
 }
 
-void MkvPesFile::Seek(signed long pcr)
+void MkvPesFile::Seek(Int32 pcr)
 {
     return;
 }
@@ -57,25 +176,25 @@ unsigned long long MkvPesFile::GetClusterClock(EbmlElement cluster)
     return 1;
 }
 
-PesPacket MkvPesFile::BuildAc3Pes(signed long long timestamp, char data[], unsigned short pid)
+PesPacket MkvPesFile::BuildAc3Pes(Int64 timestamp, pByte data, ushort pid)
 {
     PesPacket ret;
     return ret; 
 }
 
-PesPacket MkvPesFile::BuildMpeg2Pes(signed long long timestamp, char data[], unsigned short pid)
+PesPacket MkvPesFile::BuildMpeg2Pes(Int64 timestamp, pByte data, ushort pid)
 {
     PesPacket ret;
     return ret; 
 }
 
-PesPacket MkvPesFile::BuildAvcPes(signed long long timestamp, char data[], unsigned short pid)
+PesPacket MkvPesFile::BuildAvcPes(Int64 timestamp, pByte data, ushort pid)
 {
     PesPacket ret;
     return ret; 
 }
 
-PesPacket MkvPesFile::BuildVc1Pes(signed long long timestamp, char data[], unsigned short pid)
+PesPacket MkvPesFile::BuildVc1Pes(Int64 timestamp, pByte data, ushort pid)
 {
     PesPacket ret;
     return ret;