matroska.c
资源名称:tcpmp.rar [点击查看]
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:15k
源码类别:
Windows CE
开发平台:
C/C++
- /*****************************************************************************
- *
- * This program is free software ; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: matroska.c 548 2006-01-08 22:41:57Z picard $
- *
- * The Core Pocket Media Player
- * Copyright (c) 2004-2005 Gabor Kovacs
- *
- ****************************************************************************/
- #include "../common/common.h"
- #include "matroska.h"
- #include "MatroskaParser/MatroskaParser.h"
- typedef struct matroska
- {
- format_base Format;
- InputStream IO;
- MatroskaFile* File;
- } matroska;
- #define MK(p) ((matroska*)((char*)(p)-OFS(matroska,IO)))
- static void AudioTrackMS(format_stream* s,TrackInfo* Info)
- {
- s->Fragmented = 1;
- Format_WaveFormatMem(s,Info->CodecPrivate,Info->CodecPrivateSize);
- }
- static void AudioTrack(format_stream* s,TrackInfo* Info,int Format,bool_t PacketBased)
- {
- PacketFormatClear(&s->Format);
- s->Format.Type = PACKET_AUDIO;
- s->Format.Format.Audio.Format = Format;
- s->Format.Format.Audio.Channels = Info->Audio.Channels;
- s->Format.Format.Audio.SampleRate = mkv_TruncFloat(Info->Audio.SamplingFreq);
- s->Format.Format.Audio.Bits = Info->Audio.BitDepth;
- s->Fragmented = !PacketBased;
- if (PacketBased)
- s->Format.Format.Audio.Flags |= PCM_PACKET_BASED;
- PacketFormatDefault(&s->Format);
- }
- static void SetPacketRate(format_stream* s,TrackInfo* Info)
- {
- if (Info->DefaultDuration)
- {
- longlong v = Info->DefaultDuration;
- s->Format.PacketRate.Num = 1000000000;
- while (v > MAX_INT)
- {
- v >>= 1;
- s->Format.PacketRate.Num >>= 1;
- }
- s->Format.PacketRate.Den = (int)v;
- }
- }
- static NOINLINE void VideoAspect(format_stream* s,TrackInfo* Info)
- {
- if (Info->Video.PixelWidth>0 && Info->Video.PixelHeight>0 &&
- Info->Video.DisplayWidth>0 && Info->Video.DisplayHeight>0)
- s->Format.Format.Video.Aspect = (int)((ASPECT_ONE*(int64_t)Info->Video.DisplayWidth*(int64_t)Info->Video.PixelHeight)/
- ((int64_t)Info->Video.PixelWidth*(int64_t)Info->Video.DisplayHeight));
- }
- static NOINLINE void VideoTrackMS(format_stream* s,TrackInfo* Info)
- {
- Format_BitmapInfoMem(s,Info->CodecPrivate,Info->CodecPrivateSize);
- VideoAspect(s,Info);
- SetPacketRate(s,Info);
- }
- static NOINLINE void SubtitleTrack(format_stream* s,int FourCC)
- {
- PacketFormatClear(&s->Format);
- s->Format.Type = PACKET_SUBTITLE;
- s->Format.Format.Subtitle.FourCC = FourCC;
- }
- static NOINLINE void VideoTrack(format_stream* s,TrackInfo* Info,int FourCC)
- {
- PacketFormatClear(&s->Format);
- s->Format.Type = PACKET_VIDEO;
- s->Format.Format.Video.Pixel.Flags = PF_FOURCC;
- s->Format.Format.Video.Pixel.FourCC = FourCC;
- s->Format.Format.Video.Width = Info->Video.PixelWidth;
- s->Format.Format.Video.Height = Info->Video.PixelHeight;
- s->Format.Format.Video.Aspect = ASPECT_ONE;
- VideoAspect(s,Info);
- SetPacketRate(s,Info);
- }
- static NOINLINE void AddChapter(pin* Comment,ulonglong Start,struct ChapterDisplay* p,int No)
- {
- tchar_t s[256];
- stprintf_s(s,TSIZEOF(s),T("CHAPTER%02dNAME="),No);
- UTF8ToTcs(s+tcslen(s),TSIZEOF(s)-tcslen(s),p->String);
- Comment->Node->Set(Comment->Node,Comment->No,s,sizeof(s));
- BuildChapter(s,TSIZEOF(s),No,Start,1000000);
- Comment->Node->Set(Comment->Node,Comment->No,s,sizeof(s));
- }
- static NOINLINE void AddAttachment(pin* Comment,Attachment *At)
- {
- tchar_t MimeType[32];
- StrToTcs(MimeType,TSIZEOF(MimeType),At->MimeType);
- if (tcsnicmp(MimeType,T("image"),5)==0)
- {
- tchar_t s[256];
- stprintf_s(s,TSIZEOF(s),T("%s=:%d:%d:%s"),PlayerComment(COMMENT_COVER),(int)At->Position,(int)At->Length,MimeType);
- Comment->Node->Set(Comment->Node,Comment->No,s,sizeof(s));
- }
- }
- static int AddChapters(pin* Comment,Chapter *Ch,int No)
- {
- uint32_t i,j;
- if (Ch)
- for (i=0;i<Ch->nChildren;++i)
- {
- for (j=0;j<Ch->Children[i].nDisplay;++i)
- if (Ch->Children[i].Display[j].String)
- {
- AddChapter(Comment,Ch->Children[i].Start,
- &Ch->Children[i].Display[j],No++);
- break;
- }
- No = AddChapters(Comment,&Ch->Children[i],No);
- }
- return No;
- }
- static void AddComment(pin* Comment,tchar_t* Name,char* Value)
- {
- if (Comment->Node && Value)
- {
- tchar_t s[256];
- tcscpy_s(s,TSIZEOF(s),Name);
- tcscat_s(s,TSIZEOF(s),T("="));
- UTF8ToTcs(s+tcslen(s),TSIZEOF(s)-tcslen(s),Value);
- Comment->Node->Set(Comment->Node,Comment->No,s,sizeof(s));
- }
- }
- static void BuildConfig(format_stream* s,const char* CodecID,int OutputFreq)
- {
- static const int Rates[12] = {96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000};
- int Rate;
- int Profile;
- uint8_t* Config;
- int Len = 2;
- bool_t SBR = 0;
- if (OutputFreq > s->Format.Format.Audio.SampleRate)
- {
- if (OutputFreq > 24000)
- OutputFreq >>= 1;
- s->Format.Format.Audio.SampleRate = OutputFreq;
- SBR = 1;
- }
- for (Rate=0;Rate<11;++Rate)
- if (s->Format.Format.Audio.SampleRate >= Rates[Rate])
- break;
- if (strcmp(CodecID+12, "MAIN")==0)
- Profile = 1;
- else if (strcmp(CodecID+12, "SSR")==0)
- Profile = 3;
- else if (strcmp(CodecID+12, "LTP")==0)
- Profile = 4;
- else if (strcmp(CodecID+12, "SBR")==0)
- Profile = 5;
- else if (strcmp(CodecID+12, "LC/SBR")==0 || SBR)
- {
- Profile = 2;
- Len = 5;
- }
- else
- Profile = 2; //assuming LC
- if (PacketFormatExtra(&s->Format,Len))
- {
- Config = (uint8_t*)s->Format.Extra;
- Config[0] = (uint8_t)(Profile << 3);
- Config[0] |= (uint8_t)(Rate >> 1);
- Config[1] = (uint8_t)(Rate << 7);
- Config[1] |= (uint8_t)(s->Format.Format.Audio.Channels << 3);
- if (Len>2)
- {
- if (s->Format.Format.Audio.SampleRate <= 24000)
- s->Format.Format.Audio.SampleRate <<= 1;
- for (Rate=0;Rate<11;++Rate)
- if (s->Format.Format.Audio.SampleRate >= Rates[Rate])
- break;
- Config[2] = 0x56;
- Config[3] = 0xE5;
- Config[4] = 0x80;
- Config[4] |= (uint8_t)(Rate << 3);
- }
- }
- }
- static int Init(matroska* p)
- {
- unsigned n,Count;
- SegmentInfo* Info;
- p->File = mkv_Open(&p->IO,NULL,0);
- if (!p->File)
- return ERR_INVALID_DATA;
- Info = mkv_GetFileInfo(p->File);
- if (Info)
- p->Format.Duration = (tick_t)((Info->Duration * TICKSPERSEC) / 1000000000);
- Count = mkv_GetNumTracks(p->File);
- for (n=0;n<Count;++n)
- {
- format_stream* s = Format_AddStream(&p->Format,sizeof(format_stream));
- if (s)
- {
- TrackInfo *Info = mkv_GetTrackInfo(p->File,n);
- if (Info)
- {
- int CodecPrivateSize = Info->CodecPrivateSize;
- if (strcmp(Info->CodecID, "V_MS/VFW/FOURCC")==0)
- {
- VideoTrackMS(s,Info);
- CodecPrivateSize = 0;
- }
- else if (strncmp(Info->CodecID, "V_REAL/RV", 9)==0)
- VideoTrack(s,Info,LOAD32LE(Info->CodecID+7));
- else if (strncmp(Info->CodecID, "V_MPEG4/ISO/AVC", 14)==0)
- {
- VideoTrack(s,Info,FOURCC('A','V','C','1'));
- s->Format.Format.Video.Pixel.Flags |= PF_PTS;
- }
- else if (strncmp(Info->CodecID, "V_MPEG4/ISO", 11)==0)
- VideoTrack(s,Info,FOURCC('M','P','4','V'));
- else if (strcmp(Info->CodecID, "V_MPEG4/MS/V3")==0)
- VideoTrack(s,Info,FOURCC('M','P','4','3'));
- else if (strcmp(Info->CodecID, "V_MPEG1")==0 || strcmp(Info->CodecID, "V_MPEG2")==0)
- VideoTrack(s,Info,FOURCC('M','P','E','G'));
- else if (strcmp(Info->CodecID, "V_MJPEG")==0)
- VideoTrack(s,Info,FOURCC('M','J','P','G'));
- else if (strcmp(Info->CodecID, "A_MPEG/L3")==0)
- AudioTrack(s,Info,AUDIOFMT_MP3,0);
- else if (strcmp(Info->CodecID, "A_MPEG/L2")==0 || strcmp(Info->CodecID, "A_MPEG/L1")==0)
- AudioTrack(s,Info,AUDIOFMT_MP2,0);
- else if (strcmp(Info->CodecID, "A_PCM/INT/LIT")==0)
- AudioTrack(s,Info,AUDIOFMT_PCM,0);
- else if (strstr(Info->CodecID, "A_AC3")!=NULL || strcmp(Info->CodecID, "A_DTS")==0)
- AudioTrack(s,Info,AUDIOFMT_A52,0);
- else if (strstr(Info->CodecID, "A_AAC")!=NULL)
- {
- AudioTrack(s,Info,AUDIOFMT_AAC,1);
- if (!CodecPrivateSize)
- BuildConfig(s,Info->CodecID,mkv_TruncFloat(Info->Audio.OutputSamplingFreq));
- }
- else if (strcmp(Info->CodecID, "A_VORBIS")==0)
- AudioTrack(s,Info,AUDIOFMT_VORBIS_PACKET,1);
- else if (strcmp(Info->CodecID, "A_QUICKTIME/QDM2")==0)
- AudioTrack(s,Info,AUDIOFMT_QDESIGN2,1);
- else if (strcmp(Info->CodecID, "A_TTA1")==0)
- AudioTrack(s,Info,AUDIOFMT_TTA,1);
- else if (strcmp(Info->CodecID, "A_MS/ACM")==0)
- {
- AudioTrackMS(s,Info);
- CodecPrivateSize = 0;
- }
- else if (strcmp(Info->CodecID, "S_TEXT/UTF8")==0)
- SubtitleTrack(s,SUBTITLE_UTF8);
- else if (strcmp(Info->CodecID, "S_TEXT/SSA")==0)
- SubtitleTrack(s,SUBTITLE_SSA);
- else if (strcmp(Info->CodecID, "S_TEXT/ASS")==0)
- SubtitleTrack(s,SUBTITLE_ASS);
- else if (strcmp(Info->CodecID, "S_TEXT/USF")==0)
- SubtitleTrack(s,SUBTITLE_USF);
- if (CodecPrivateSize && PacketFormatExtra(&s->Format,CodecPrivateSize))
- memcpy(s->Format.Extra,Info->CodecPrivate,s->Format.ExtraLength);
- }
- Format_PrepairStream(&p->Format,s);
- AddComment(&s->Comment,T("TITLE"),Info->Name);
- AddComment(&s->Comment,T("LANGUAGE"),Info->Language);
- }
- }
- if (p->Format.StreamCount)
- {
- pin* Comment = &p->Format.Streams[0]->Comment;
- Tag* Tags;
- Chapter* Ch;
- Attachment* At;
- mkv_GetTags(p->File,&Tags,&Count);
- if (Tags && Comment->Node)
- for (n=0;n<Count;++n,++Tags)
- {
- uint32_t i;
- for (i=0;i<Tags->nSimpleTags;++i)
- {
- tchar_t s[256];
- UTF8ToTcs(s,TSIZEOF(s),Tags->SimpleTags[i].Name);
- tcscat_s(s,TSIZEOF(s),T("="));
- UTF8ToTcs(s+tcslen(s),TSIZEOF(s)-tcslen(s),Tags->SimpleTags[i].Value);
- Comment->Node->Set(Comment->Node,Comment->No,s,sizeof(s));
- }
- }
- mkv_GetAttachments(p->File,&At,&Count);
- if (Count>0)
- for (n=0;n<Count;++n)
- AddAttachment(Comment,At+n);
- mkv_GetChapters(p->File,&Ch,&Count);
- if (Count>0 && Info)
- AddChapters(Comment,Ch,1);
- }
- mkv_SetTrackMask(p->File,0);
- p->Format.HeaderLoaded = 1;
- return ERR_NONE;
- }
- static void Done(matroska* p)
- {
- if (p->File)
- {
- mkv_Close(p->File);
- p->File = NULL;
- }
- }
- static int ReadPacket(matroska* p, format_reader* Reader, format_packet* Packet)
- {
- ulonglong Start,End;
- void* Ref;
- ulonglong Pos;
- unsigned int Flags,Track,Size;
- int Result = mkv_ReadFrame(p->File,0,&Track,&Start,&End,&Pos,&Size,&Ref,&Flags);
- if (Result == EOF)
- return ERR_END_OF_FILE;
- if (Result != 0)
- return ERR_INVALID_DATA;
- Packet->Data = (format_ref*)Ref;
- Packet->Key = (Flags & FRAME_KF) != 0;
- Packet->Stream = p->Format.Streams[Track];
- if (!(Flags & FRAME_UNKNOWN_START))
- {
- Packet->RefTime = (tick_t)((Start * TICKSPERSEC) / 1000000000);
- if (Packet->Stream->Format.Type == PACKET_SUBTITLE && !(Flags & FRAME_UNKNOWN_END))
- Packet->EndRefTime = (tick_t)((End * TICKSPERSEC) / 1000000000);
- }
- return ERR_NONE;
- }
- static int Seek(matroska* p, tick_t Time, filepos_t FilePos,bool_t PrevKey)
- {
- if (Time < 0 && FilePos >= 0 && p->Format.Duration > 0 && p->Format.FileSize > 0)
- Time = Scale(FilePos, p->Format.Duration, p->Format.FileSize);
- if (Time >= 0)
- {
- p->Format.SyncRead = 0; // don't use partial buffers
- mkv_Seek(p->File,((ulonglong)Time * 1000000000 + (TICKSPERSEC/2))/TICKSPERSEC,PrevKey?MKVF_SEEK_TO_PREV_KEYFRAME:0);
- Format_AfterSeek(&p->Format);
- return ERR_NONE;
- }
- return ERR_NOT_SUPPORTED;
- }
- static int Read(struct InputStream *cc,ulonglong pos,void *buffer,int count)
- {
- format_reader* Reader = &MK(cc)->Format.Reader[0];
- if (Reader->FilePos != pos && Reader->Seek(Reader,(filepos_t)pos,SEEK_SET) != ERR_NONE)
- return -1;
- return Reader->Read(Reader,buffer,count);
- }
- static longlong Scan(struct InputStream *cc,ulonglong start,unsigned signature)
- {
- format_reader* Reader = &MK(cc)->Format.Reader[0];
- unsigned v = ~signature;
- int ch;
- if (Reader->FilePos != start && Reader->Seek(Reader,(filepos_t)start,SEEK_SET) != ERR_NONE)
- return -1;
- while ((ch = Reader->Read8(Reader)) >= 0)
- {
- v = ((v << 8) | ch) & 0xFFFFFFFF;
- if (v == signature)
- return Reader->FilePos - 4;
- }
- return -1;
- }
- static unsigned GetSize(struct InputStream *cc)
- {
- return MK(cc)->Format.Reader->BufferAvailable;
- }
- static const char* GetError(struct InputStream *cc)
- {
- return "";
- }
- static void* MemAlloc(struct InputStream *cc,size_t size)
- {
- return malloc(size);
- }
- static void* MemReAlloc(struct InputStream *cc,void *mem,size_t newsize)
- {
- return realloc(mem,newsize);
- }
- static void MemFree(struct InputStream *cc,void *mem)
- {
- free(mem);
- }
- static int Progress(struct InputStream *cc,ulonglong cur,ulonglong max)
- {
- return 1;
- }
- static int IOReadCh(struct InputStream *IO)
- {
- return MK(IO)->Format.Reader->Read8(MK(IO)->Format.Reader);
- }
- static int IORead(struct InputStream *IO,void *buffer,int count)
- {
- return MK(IO)->Format.Reader->Read(MK(IO)->Format.Reader,buffer,count);
- }
- static void IOSeek(struct InputStream *IO,longlong where,int how)
- {
- MK(IO)->Format.Reader->Seek(MK(IO)->Format.Reader,(filepos_t)where,how);
- }
- static longlong IOTell(struct InputStream *IO)
- {
- return MK(IO)->Format.Reader->FilePos;
- }
- static void* IOMakeRef(struct InputStream *IO,int count)
- {
- return MK(IO)->Format.Reader->ReadAsRef(MK(IO)->Format.Reader,count);
- }
- static void IOReleaseRef(struct InputStream *IO,void* ref)
- {
- Format_ReleaseRef(&MK(IO)->Format,(format_ref*)ref);
- }
- static int Create(matroska* p)
- {
- p->Format.Init = (fmtfunc)Init;
- p->Format.Done = (fmtvoid)Done;
- p->Format.Seek = (fmtseek)Seek;
- p->Format.ReadPacket = (fmtreadpacket) ReadPacket;
- p->IO.read = Read;
- p->IO.scan = Scan;
- p->IO.getsize = GetSize;
- p->IO.geterror = GetError;
- p->IO.memalloc = MemAlloc;
- p->IO.memrealloc = MemReAlloc;
- p->IO.memfree = MemFree;
- p->IO.progress = Progress;
- p->IO.ioread = IORead;
- p->IO.ioreadch = IOReadCh;
- p->IO.ioseek = IOSeek;
- p->IO.iotell = IOTell;
- p->IO.makeref = IOMakeRef;
- p->IO.releaseref = IOReleaseRef;
- return ERR_NONE;
- }
- static const nodedef Matroska =
- {
- sizeof(matroska),
- MATROSKA_ID,
- FORMATBASE_CLASS,
- PRI_DEFAULT,
- (nodecreate)Create,
- };
- void Matroska_Init()
- {
- NodeRegisterClass(&Matroska);
- }
- void Matroska_Done()
- {
- NodeUnRegisterClass(MATROSKA_ID);
- }