[matroska] r1297 - trunk/foo_input_matroska
[email protected] Sun, 10 Jun 2007 19:33:52 +0400 (MSD)
| Newsgroups | gmane.comp.multimedia.matroska.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: ayana
Date: 2007-06-10 19:33:45 +0400 (Sun, 10 Jun 2007)
New Revision: 1297
Modified:
trunk/foo_input_matroska/DbgOut.cpp
trunk/foo_input_matroska/container_matroska_impl.cpp
trunk/foo_input_matroska/matroska_parser.cpp
Log:
fix EOL style
Modified: trunk/foo_input_matroska/DbgOut.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/foo_input_matroska/DbgOut.cpp 2007-06-10 15:32:41 UTC (rev 1296=
)
+++ trunk/foo_input_matroska/DbgOut.cpp 2007-06-10 15:33:45 UTC (rev 1297=
)
@@ -1,73 +1,73 @@
-/**
- * Part of the foobar2000 Matroska plugin
- *
- * Copyright (C) Jory Stone - 2003
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING=
THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PU=
RPOSE.
- *
-*/
-
-#include "DbgOut.h"
-
-#ifdef DEBUG_OUT_PUT
-#include <stdio.h>
-#include <wchar.h>
-#include <stdarg.h>
-
-static DWORD g_dwTimeOffset =3D timeGetTime();
-
-void WINAPI DbgStringOut(const TCHAR *pFormat,...)
-{ =09
- TCHAR szInfo[2000];
-
- // Format the variable length parameter list
- va_list va;
- va_start(va, pFormat);
-
- lstrcpy(szInfo, TEXT("foo_input_matroska - "));
- wsprintf(szInfo + lstrlen(szInfo),
- TEXT("(tid %x) %8d : "),
- GetCurrentThreadId(), timeGetTime() - g_dwTimeOffset);
-
- _vstprintf(szInfo + lstrlen(szInfo), pFormat, va);
- lstrcat(szInfo, TEXT("\r\n"));
- OutputDebugString(szInfo);
-
- va_end(va);
-};
-
-#ifdef UNICODE
-void WINAPI DbgLogInfo(const CHAR *pFormat,...)
-{
- TCHAR szInfo[2000];
-
- // Format the variable length parameter list
- va_list va;
- va_start(va, pFormat);
-
- lstrcpy(szInfo, TEXT("foo_input_matroska - "));
- wsprintf(szInfo + lstrlen(szInfo),
- TEXT("(tid %x) %8d : "),
- GetCurrentThreadId(), timeGetTime() - g_dwTimeOffset);
-
- CHAR szInfoA[2000];
- WideCharToMultiByte(CP_ACP, 0, szInfo, -1, szInfoA, sizeof(szInfoA)/=
sizeof(CHAR), 0, 0);
-
- wvsprintfA(szInfoA + lstrlenA(szInfoA), pFormat, va);
- lstrcatA(szInfoA, "\r\n");
-
- WCHAR wszOutString[2000];
- MultiByteToWideChar(CP_ACP, 0, szInfoA, -1, wszOutString, sizeof(wsz=
OutString)/sizeof(WCHAR));
- DbgOutString(wszOutString);
-
- va_end(va);
-}
-#endif
-#endif
-
+/**
+ * Part of the foobar2000 Matroska plugin
+ *
+ * Copyright (C) Jory Stone - 2003
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING=
THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PU=
RPOSE.
+ *
+*/
+
+#include "DbgOut.h"
+
+#ifdef DEBUG_OUT_PUT
+#include <stdio.h>
+#include <wchar.h>
+#include <stdarg.h>
+
+static DWORD g_dwTimeOffset =3D timeGetTime();
+
+void WINAPI DbgStringOut(const TCHAR *pFormat,...)
+{ =09
+ TCHAR szInfo[2000];
+
+ // Format the variable length parameter list
+ va_list va;
+ va_start(va, pFormat);
+
+ lstrcpy(szInfo, TEXT("foo_input_matroska - "));
+ wsprintf(szInfo + lstrlen(szInfo),
+ TEXT("(tid %x) %8d : "),
+ GetCurrentThreadId(), timeGetTime() - g_dwTimeOffset);
+
+ _vstprintf(szInfo + lstrlen(szInfo), pFormat, va);
+ lstrcat(szInfo, TEXT("\r\n"));
+ OutputDebugString(szInfo);
+
+ va_end(va);
+};
+
+#ifdef UNICODE
+void WINAPI DbgLogInfo(const CHAR *pFormat,...)
+{
+ TCHAR szInfo[2000];
+
+ // Format the variable length parameter list
+ va_list va;
+ va_start(va, pFormat);
+
+ lstrcpy(szInfo, TEXT("foo_input_matroska - "));
+ wsprintf(szInfo + lstrlen(szInfo),
+ TEXT("(tid %x) %8d : "),
+ GetCurrentThreadId(), timeGetTime() - g_dwTimeOffset);
+
+ CHAR szInfoA[2000];
+ WideCharToMultiByte(CP_ACP, 0, szInfo, -1, szInfoA, sizeof(szInfoA)/=
sizeof(CHAR), 0, 0);
+
+ wvsprintfA(szInfoA + lstrlenA(szInfoA), pFormat, va);
+ lstrcatA(szInfoA, "\r\n");
+
+ WCHAR wszOutString[2000];
+ MultiByteToWideChar(CP_ACP, 0, szInfoA, -1, wszOutString, sizeof(wsz=
OutString)/sizeof(WCHAR));
+ DbgOutString(wszOutString);
+
+ va_end(va);
+}
+#endif
+#endif
+
Property changes on: trunk/foo_input_matroska/DbgOut.cpp
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/foo_input_matroska/container_matroska_impl.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/foo_input_matroska/container_matroska_impl.cpp 2007-06-10 15:32=
:41 UTC (rev 1296)
+++ trunk/foo_input_matroska/container_matroska_impl.cpp 2007-06-10 15:33=
:45 UTC (rev 1297)
@@ -1,40 +1,40 @@
-#include "container_matroska_impl.h"
-
-/**
- * container_matroska
- */
-
-void container_matroska_impl::open(const char * p_path, bool p_info_only=
, foobar2000_io::abort_callback &p_abort) {
- cleanup();
- if (!is_our_path(p_path)) {
- throw exception_io_unsupported_format();
- }
- m_path =3D p_path;
- m_abort =3D &p_abort;
- service_ptr_t<file> file_ptr;
- try {
- filesystem::g_open_read(file_ptr, m_path, *m_abort);
- matroska_parser_ptr parser =3D matroska_parser_ptr(new MatroskaA=
udioParser(file_ptr, *m_abort));
- parser->Parse(p_info_only);
- for (t_size i =3D 0; i !=3D parser->GetAttachmentList().get_coun=
t(); ++i) {
- MatroskaAttachment & item =3D parser->GetAttachmentList().ge=
t_item(i);
- matroska::attachment attachment(this, *m_abort, item.FileNam=
e.GetUTF8().c_str(), item.MimeType.c_str(), item.Description.GetUTF8().c_=
str(),
- static_cast<t_size>(item.SourceDataLength), static_cast<=
t_sfilesize>(item.SourceStartPos));
- m_attachment_list.add_item(attachment);
- }
- } catch (...) {
- throw exception_io_unsupported_format();
- }
-}
-
-void container_matroska_impl::open_file(service_ptr_t<file> & p_out, con=
st filesystem::t_open_mode p_mode) const {
- filesystem::g_open(p_out, m_path, p_mode, *m_abort);
-}
-
-void container_matroska_impl::get_display_path(pfc::string_base & p_out)=
const {
- p_out =3D m_path;
-}
-
-const matroska::attachment_list * container_matroska_impl::get_attachmen=
t_list() const {
- return reinterpret_cast<const matroska::attachment_list *>(&m_attach=
ment_list);
-}
+#include "container_matroska_impl.h"
+
+/**
+ * container_matroska
+ */
+
+void container_matroska_impl::open(const char * p_path, bool p_info_only=
, foobar2000_io::abort_callback &p_abort) {
+ cleanup();
+ if (!is_our_path(p_path)) {
+ throw exception_io_unsupported_format();
+ }
+ m_path =3D p_path;
+ m_abort =3D &p_abort;
+ service_ptr_t<file> file_ptr;
+ try {
+ filesystem::g_open_read(file_ptr, m_path, *m_abort);
+ matroska_parser_ptr parser =3D matroska_parser_ptr(new MatroskaA=
udioParser(file_ptr, *m_abort));
+ parser->Parse(p_info_only);
+ for (t_size i =3D 0; i !=3D parser->GetAttachmentList().get_coun=
t(); ++i) {
+ MatroskaAttachment & item =3D parser->GetAttachmentList().ge=
t_item(i);
+ matroska::attachment attachment(this, *m_abort, item.FileNam=
e.GetUTF8().c_str(), item.MimeType.c_str(), item.Description.GetUTF8().c_=
str(),
+ static_cast<t_size>(item.SourceDataLength), static_cast<=
t_sfilesize>(item.SourceStartPos));
+ m_attachment_list.add_item(attachment);
+ }
+ } catch (...) {
+ throw exception_io_unsupported_format();
+ }
+}
+
+void container_matroska_impl::open_file(service_ptr_t<file> & p_out, con=
st filesystem::t_open_mode p_mode) const {
+ filesystem::g_open(p_out, m_path, p_mode, *m_abort);
+}
+
+void container_matroska_impl::get_display_path(pfc::string_base & p_out)=
const {
+ p_out =3D m_path;
+}
+
+const matroska::attachment_list * container_matroska_impl::get_attachmen=
t_list() const {
+ return reinterpret_cast<const matroska::attachment_list *>(&m_attach=
ment_list);
+}
Property changes on: trunk/foo_input_matroska/container_matroska_impl.cpp
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/foo_input_matroska/matroska_parser.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/foo_input_matroska/matroska_parser.cpp 2007-06-10 15:32:41 UTC =
(rev 1296)
+++ trunk/foo_input_matroska/matroska_parser.cpp 2007-06-10 15:33:45 UTC =
(rev 1297)
@@ -1,2651 +1,2651 @@
-/*
- * Part of the foobar2000 Matroska plugin
- *
- * Copyright (C) Jory 'jcsston' Stone (jcsston at toughguy net) - 2003-=
2004
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING =
THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PUR=
POSE.
- *
- */
-
-/*!
- \file matroska_parser.cpp
- \version $Id$
- \brief An audio slated Matroska Reader+Parser
- \author Jory Stone <jcsston @ toughguy.net>
-*/
-
-#include "matroska_parser.h"
-
-#include <string>
-using std::string;
-
-using namespace LIBEBML_NAMESPACE;=09
-using namespace LIBMATROSKA_NAMESPACE;
-
-static const char * rg_fields[]=3D
-{
- "REPLAYGAIN_GAIN",
- "REPLAYGAIN_PEAK"
-};
-
-static const char * rg_track_fields[]=3D
-{
- "REPLAYGAIN_TRACK_GAIN",
- "REPLAYGAIN_TRACK_PEAK"
-};
-
-static const char * rg_album_fields[]=3D
-{
- "REPLAYGAIN_ALBUM_GAIN",
- "REPLAYGAIN_ALBUM_PEAK"
-};
-
-#define MATROSKA_TAG_IDX 0
-#define FOOBAR2K_TAG_IDX 1
-
-static const char * chapter_tag_mapping[][2] =3D
-{
- { "PART_NUMBER", "TRACKNUMBER" },
- { "DATE_RELEASED", "DATE" },
- //{ "LEAD_PERFORMER", "PERFORMER" },
- //{ "ACCOMPANIMENT", "BAND" },
- //{ "LYRICIST", "WRITER" }
-};
-
-static const char * edition_tag_mapping[][2] =3D
-{
- { "TITLE", "ALBUM" },
- { "CATALOG_NUMBER", "CATALOG" },
- { "TOTAL_PARTS", "TOTALTRACKS" },
- //{ "PART_NUMBER", "DISCNUMBER" },
- //{ "TOTAL_DISCS", "TOTALDISCS" }
-};
-
-static const char * hidden_edition_field[] =3D
-{
- "___DUMMY___",
-};
-
-static const char * hidden_chapter_field[] =3D
-{
- "CDAUDIO_TRACK_FLAGS",
-};
-
-bool starts_with(const string &s, const char *start) {
- return strncmp(s.c_str(), start, strlen(start)) =3D=3D 0;
-};
-
-uint64 MatroskaAudioParser::SecondsToTimecode(double seconds)
-{
- return (uint64)floor(seconds * 1000000000);
-};
-
-double MatroskaAudioParser::TimecodeToSeconds(uint64 code,unsigned sampl=
erate_hint)
-{
- return ((double)(int64)code / 1000000000);
-};
-
-
-MatroskaAudioFrame::MatroskaAudioFrame()=20
-{
- timecode =3D 0;
- duration =3D 0;
- add_id =3D 0;
-};
-
-MatroskaAttachment::MatroskaAttachment()
-{
- FileName =3D L"";
- MimeType =3D "";
- Description =3D L"";
- SourceFilename =3D L"";
- SourceStartPos =3D 0;
- SourceDataLength =3D 0;
-};
-
-void MatroskaAudioFrame::Reset()
-{
- timecode =3D 0;
- duration =3D 0;
- add_id =3D 0;
-};
-
-MatroskaSimpleTag::MatroskaSimpleTag()
-{
- name =3D L"";
- value =3D L"";
- language =3D "und";
- defaultFlag =3D 1;
- hidden =3D false;
- removalPending =3D false;
-};
-
-MatroskaTagInfo::MatroskaTagInfo()
-{
- targetTrackUID =3D 0;
- targetEditionUID =3D 0;
- targetChapterUID =3D 0;
- targetAttachmentUID =3D 0;
- targetTypeValue =3D 0;
-};
-
-void MatroskaTagInfo::SetTagValue(const char *name, const char *value, i=
nt index)
-{
- for (size_t s =3D 0; s < tags.size(); s++)
- {
- MatroskaSimpleTag ¤tSimpleTag =3D tags.at(s);
- if (strcmpi(currentSimpleTag.name.GetUTF8().c_str(), name) =3D=3D 0) =
=09
- {
- if(index =3D=3D 0)
- {
- currentSimpleTag.value.SetUTF8(value);
- currentSimpleTag.removalPending =3D false;
- return;
- }
- index--;
- }
- }
-
- // If we are here then we didn't find this tag in the vector already
- MatroskaSimpleTag newSimpleTag;
- newSimpleTag.name.SetUTF8(name);
- newSimpleTag.value.SetUTF8(value);=09
- newSimpleTag.removalPending =3D false;
- tags.push_back(newSimpleTag);
-};
-
-void MatroskaTagInfo::RemoveMarkedTags()
-{
- for (int i =3D tags.size()-1; i >=3D 0; i--)
- {
- MatroskaSimpleTag &simpleTag =3D tags.at(i);
- if(simpleTag.removalPending =3D=3D true)
- {
- tags.erase(tags.begin() + i);
- }
- }
-}
-
-void MatroskaTagInfo::MarkAllAsRemovalPending()
-{
- for (int i =3D tags.size()-1; i >=3D 0; i--)
- {
- MatroskaSimpleTag &simpleTag =3D tags.at(i);
- simpleTag.removalPending =3D true;
- }
-}
-
-MatroskaChapterDisplayInfo::MatroskaChapterDisplayInfo() {
- string =3D L"";
-};
-
-MatroskaChapterInfo::MatroskaChapterInfo() {
- chapterUID =3D 0;
- timeStart =3D 0;
- timeEnd =3D 0;
-}
-
-MatroskaEditionInfo::MatroskaEditionInfo() {
- editionUID =3D 0;
-}
-
-MatroskaTrackInfo::MatroskaTrackInfo() {
- trackNumber =3D 0;
- trackUID =3D 0; =09
- duration =3D 0;
-
- channels =3D 1;
- samplesPerSec =3D 0;
- samplesOutputPerSec =3D 0;
- bitsPerSample =3D 0;
- avgBytesPerSec =3D 0;
- defaultDuration =3D 0;
-
- name =3D L"";
-
- codecPrivateReady =3D false;
-};
-
-MatroskaAudioParser::MatroskaAudioParser(service_ptr_t<file> input, abor=
t_callback & p_abort)=20
- : m_IOCallback(input, p_abort),
- m_InputStream(m_IOCallback)
-{
- m_TimecodeScale =3D TIMECODE_SCALE;
- m_FileDate =3D 0;
- m_Duration =3D 0;
- m_CurrentTimecode =3D 0;
- //m_ElementLevel0 =3D NULL;
- //UpperElementLevel =3D 0;
- m_CurrentEdition =3D 0;
- m_CurrentChapter =3D 0;
- m_FileSize =3D input->get_size(p_abort);
- m_TagPos =3D 0;
- m_TagSize =3D 0;
- m_TagScanRange =3D 1024 * 64;
- m_CurrentTrackNo =3D 0;
-};
-
-MatroskaAudioParser::~MatroskaAudioParser() {
- //if (m_ElementLevel0 !=3D NULL)
- // _DELETE(m_ElementLevel0);
- //delete m_ElementLevel0;
-=09
- while (!m_Queue.empty()) {
- MatroskaAudioFrame *currentPacket =3D m_Queue.front();
- //delete currentPacket;
- _DELETE(currentPacket);
- m_Queue.pop();
- }
-};
-
-int MatroskaAudioParser::Parse(bool bInfoOnly, bool bBreakAtClusters)=20
-{
- try {
- int UpperElementLevel =3D 0;
- bool bAllowDummy =3D false;
- // Elements for different levels
- ElementPtr ElementLevel1;
- ElementPtr ElementLevel2;
- ElementPtr ElementLevel3;
- ElementPtr ElementLevel4;
- ElementPtr ElementLevel5;
- ElementPtr NullElement;
-
- // Be sure we are at the beginning of the file
- m_IOCallback.setFilePointer(0);
- // Find the EbmlHead element. Must be the first one.
- m_ElementLevel0 =3D ElementPtr(m_InputStream.FindNextID(EbmlHead::Clas=
sInfos, 0xFFFFFFFFFFFFFFFFL));
- if (m_ElementLevel0 =3D=3D NullElement) {
- return 1;
- }
- //We must have found the EBML head :)
- m_ElementLevel0->SkipData(m_InputStream, m_ElementLevel0->Generic().Co=
ntext);
- //delete m_ElementLevel0;
- //_DELETE(m_ElementLevel0);
-
- // Next element must be a segment
- m_ElementLevel0 =3D ElementPtr(m_InputStream.FindNextID(KaxSegment::Cl=
assInfos, 0xFFFFFFFFFFFFFFFFL));
- if (m_ElementLevel0 =3D=3D NullElement) {
- //No segment/level 0 element found.
- return 1;
- }
- if (!(EbmlId(*m_ElementLevel0) =3D=3D KaxSegment::ClassInfos.GlobalId)=
) {
- //delete m_ElementLevel0;
- //m_ElementLevel0 =3D NULL;
- //_DELETE(m_ElementLevel0);
- return 1;
- }
-
- UpperElementLevel =3D 0;
- // We've got our segment, so let's find the tracks
- ElementLevel1 =3D ElementPtr(m_InputStream.FindNextElement(m_ElementLe=
vel0->Generic().Context, UpperElementLevel, 0xFFFFFFFFFFFFFFFFL, true, 1)=
);
- while (ElementLevel1 !=3D NullElement) {
- if (UpperElementLevel > 0) {
- break;
- }
- if (UpperElementLevel < 0) {
- UpperElementLevel =3D 0;
- }
-
- if (EbmlId(*ElementLevel1) =3D=3D KaxSeekHead::ClassInfos.GlobalId) {
- if (m_IOCallback.seekable()) {
- Parse_MetaSeek(ElementLevel1, bInfoOnly);
- if (m_TagPos =3D=3D 0) {
- // Search for them at the end of the file
- if (m_TagScanRange > 0)
- {
- m_IOCallback.setFilePointer(m_FileSize - m_TagScanRange);
- uint64 init_pos =3D m_IOCallback.getFilePointer();
- /*
- BM Search
- */
- binary buf[1024*64];
- binary pat[3]; pat[0] =3D 0x54; pat[1] =3D 0xc3; pat[2] =3D 0x67;
- uint64 s_pos =3D m_IOCallback.getFilePointer();
- m_IOCallback.read(buf, m_TagScanRange);
- MatroskaSearch search(buf, pat);
- int pos =3D search.Match();
- if (pos !=3D -1) {
- do {
- m_IOCallback.setFilePointer(s_pos+pos+3);
- uint64 startPos =3D m_IOCallback.getFilePointer();
- m_IOCallback.setFilePointer(-4, seek_current);
- ElementPtr levelUnknown =3D ElementPtr(m_InputStream.FindNextID=
(KaxTags::ClassInfos, 0xFFFFFFFFFFFFFFFFL));
- if ((levelUnknown !=3D NullElement)=20
- && (m_FileSize >=3D startPos + levelUnknown->GetSize())=20
- && (EbmlId(*levelUnknown) =3D=3D KaxTags::ClassInfos.GlobalId)=
)
- {
- Parse_Tags(static_cast<KaxTags *>(levelUnknown.get()));
- break;
- }
- m_IOCallback.setFilePointer(s_pos);
- pos =3D search.Match(pos+1);
- } while (pos !=3D -1);
- /*
- ~BM Search
- */
- } else {
- m_IOCallback.setFilePointer(init_pos);
- binary Buffer[4];
- while (m_IOCallback.read(Buffer, 3) >=3D 3)
- {//0x18
- if ((Buffer[0] =3D=3D 0x54) && (Buffer[1] =3D=3D 0xc3) && (Buff=
er[2] =3D=3D 0x67))
- {
- uint64 startPos =3D m_IOCallback.getFilePointer();
-
- //seek back 3 bytes, so libmatroska can find the Tags element =
Ebml ID
- m_IOCallback.setFilePointer(-4, seek_current);
-
- ElementPtr levelUnknown =3D ElementPtr(m_InputStream.FindNextI=
D(KaxTags::ClassInfos, 0xFFFFFFFFFFFFFFFFL));
- if ((levelUnknown !=3D NullElement)=20
- && (m_FileSize >=3D startPos + levelUnknown->GetSize())=20
- && (EbmlId(*levelUnknown) =3D=3D KaxTags::ClassInfos.GlobalId=
))
- {
- Parse_Tags(static_cast<KaxTags *>(levelUnknown.get()));
- //_DELETE(levelUnknown);
- break;
- }
- //_DELETE(levelUnknown);
-
- //Restore the file pos
- m_IOCallback.setFilePointer(startPos);
- }
- //seek back 2 bytes
- m_IOCallback.setFilePointer(-2, seek_current);
- }
- }
- } else {
- //m_TagPos =3D m_FileSize;
- }
- }
- }
- }else if (EbmlId(*ElementLevel1) =3D=3D KaxInfo::ClassInfos.GlobalId)=
{
- // General info about this Matroska file
- ElementLevel2 =3D ElementPtr(m_InputStream.FindNextElement(ElementLe=
vel1->Generic().Context, UpperElementLevel, 0xFFFFFFFFFFFFFFFFL, bAllowDu=
mmy));
- while (ElementLevel2 !=3D NullElement) {
- if (UpperElementLevel > 0) {
- break;
- }
- if (UpperElementLevel < 0) {
- UpperElementLevel =3D 0;
- }
-
- if (EbmlId(*ElementLevel2) =3D=3D KaxTimecodeScale::ClassInfos.Glob=
alId) {
- KaxTimecodeScale &TimeScale =3D *static_cast<KaxTimecodeScale *>(E=
lementLevel2.get());
- TimeScale.ReadData(m_InputStream.I_O());
-
- //matroskaGlobalTrack->SetTimecodeScale(uint64(TimeScale));
- m_TimecodeScale =3D uint64(TimeScale);
- } else if (EbmlId(*ElementLevel2) =3D=3D KaxDuration::ClassInfos.Gl=
obalId) {
- KaxDuration &duration =3D *static_cast<KaxDuration *>(ElementLevel=
2.get());
- duration.ReadData(m_InputStream.I_O());
-
- // it's in milliseconds? -- in nanoseconds.
- m_Duration =3D double(duration) * m_TimecodeScale;
-
- } else if (EbmlId(*ElementLevel2) =3D=3D KaxDateUTC::ClassInfos.Glo=
balId) {
- KaxDateUTC & DateUTC =3D *static_cast<KaxDateUTC *>(ElementLevel2.=
get());
- DateUTC.ReadData(m_InputStream.I_O());
- =09
- m_FileDate =3D DateUTC.GetEpochDate();
-
- } else if (EbmlId(*ElementLevel2) =3D=3D KaxSegmentFilename::ClassI=
nfos.GlobalId) {
- KaxSegmentFilename &tag_SegmentFilename =3D *static_cast<KaxSegmen=
tFilename *>(ElementLevel2.get());
- tag_SegmentFilename.ReadData(m_InputStream.I_O());
-
- m_SegmentFilename =3D *static_cast<EbmlUnicodeString *>(&tag_Segme=
ntFilename);
-
- } else if (EbmlId(*ElementLevel2) =3D=3D KaxMuxingApp::ClassInfos.G=
lobalId) {
- KaxMuxingApp &tag_MuxingApp =3D *static_cast<KaxMuxingApp *>(Eleme=
ntLevel2.get());
- tag_MuxingApp.ReadData(m_InputStream.I_O());
-
- m_MuxingApp =3D *static_cast<EbmlUnicodeString *>(&tag_MuxingApp);
-
- } else if (EbmlId(*ElementLevel2) =3D=3D KaxWritingApp::ClassInfos.=
GlobalId) {
- KaxWritingApp &tag_WritingApp =3D *static_cast<KaxWritingApp *>(El=
ementLevel2.get());
- tag_WritingApp.ReadData(m_InputStream.I_O());
- =09
- m_WritingApp =3D *static_cast<EbmlUnicodeString *>(&tag_WritingApp=
);
-
- } else if (EbmlId(*ElementLevel2) =3D=3D KaxTitle::ClassInfos.Globa=
lId) {
- KaxTitle &Title =3D *static_cast<KaxTitle*>(ElementLevel2.get());
- Title.ReadData(m_InputStream.I_O());
- m_FileTitle =3D UTFstring(Title).c_str();
- }
-
- if (UpperElementLevel > 0) { // we're coming from ElementLevel3
- UpperElementLevel--;
- //delete ElementLevel2;
- ElementLevel2 =3D ElementLevel3;
- if (UpperElementLevel > 0)
- break;
- } else {
- ElementLevel2->SkipData(m_InputStream, ElementLevel2->Generic().Co=
ntext);
- //delete ElementLevel2;
- //_DELETE(ElementLevel2);
- ElementLevel2 =3D ElementPtr(m_InputStream.FindNextElement(Element=
Level1->Generic().Context, UpperElementLevel, 0xFFFFFFFFFFFFFFFFL, bAllow=
Dummy));
- }
- }
- }else if (EbmlId(*ElementLevel1) =3D=3D KaxChapters::ClassInfos.Globa=
lId) {
- Parse_Chapters(static_cast<KaxChapters *>(ElementLevel1.get()));
- }else if (EbmlId(*ElementLevel1) =3D=3D KaxTags::ClassInfos.GlobalId)=
{
- Parse_Tags(static_cast<KaxTags *>(ElementLevel1.get()));
- } else if (EbmlId(*ElementLevel1) =3D=3D KaxTracks::ClassInfos.Global=
Id) {
- // Yep, we've found our KaxTracks element. Now find all tracks
- // contained in this segment.=20
- KaxTracks *Tracks =3D static_cast<KaxTracks *>(ElementLevel1.get());
- EbmlElement* tmpElement =3D ElementLevel2.get();
- Tracks->Read(m_InputStream, KaxTracks::ClassInfos.Context, UpperElem=
entLevel, tmpElement, bAllowDummy);
-
- unsigned int Index0;
- for (Index0 =3D 0; Index0 < Tracks->ListSize(); Index0++) {
- if ((*Tracks)[Index0]->Generic().GlobalId =3D=3D KaxTrackEntry::Cla=
ssInfos.GlobalId) {
- KaxTrackEntry &TrackEntry =3D *static_cast<KaxTrackEntry *>((*Trac=
ks)[Index0]);
- // Create a new MatroskaTrack
- MatroskaTrackInfo newTrack;
- =09
- unsigned int Index1;
- for (Index1 =3D 0; Index1 < TrackEntry.ListSize(); Index1++) {
- if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrackNumber:=
:ClassInfos.GlobalId) {
- KaxTrackNumber &TrackNumber =3D *static_cast<KaxTrackNumber*>(Tr=
ackEntry[Index1]);
- newTrack.trackNumber =3D TrackNumber;
-
- } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrack=
UID::ClassInfos.GlobalId) {
- KaxTrackUID &TrackUID =3D *static_cast<KaxTrackUID*>(TrackEntry[=
Index1]);
- newTrack.trackUID =3D TrackUID;
-
- } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrack=
Type::ClassInfos.GlobalId) {
- KaxTrackType &TrackType =3D *static_cast<KaxTrackType*>(TrackEnt=
ry[Index1]);
- if (uint8(TrackType) !=3D track_audio) {
- newTrack.trackNumber =3D 0xFFFF;
- break;
- }
-
- } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrack=
TimecodeScale::ClassInfos.GlobalId) {
- KaxTrackTimecodeScale &TrackTimecodeScale =3D *static_cast<KaxTr=
ackTimecodeScale*>(TrackEntry[Index1]);
- // TODO: Support Tracks with different timecode scales?
- //newTrack->TrackTimecodeScale =3D TrackTimecodeScale;
-
- } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrack=
DefaultDuration::ClassInfos.GlobalId) {
- KaxTrackDefaultDuration &TrackDefaultDuration =3D *static_cast<K=
axTrackDefaultDuration*>(TrackEntry[Index1]);
- newTrack.defaultDuration =3D uint64(TrackDefaultDuration);
-
- } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxCodec=
ID::ClassInfos.GlobalId) {
- KaxCodecID &CodecID =3D *static_cast<KaxCodecID*>(TrackEntry[Ind=
ex1]);
- newTrack.codecID =3D std::string(CodecID);
-
- } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxCodec=
Private::ClassInfos.GlobalId) {
- KaxCodecPrivate &CodecPrivate =3D *static_cast<KaxCodecPrivate*>=
(TrackEntry[Index1]);
- newTrack.codecPrivate.resize(CodecPrivate.GetSize()); =09
- memcpy(&newTrack.codecPrivate[0], CodecPrivate.GetBuffer(), Code=
cPrivate.GetSize());
-
- } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrack=
FlagDefault::ClassInfos.GlobalId) {
- KaxTrackFlagDefault &TrackFlagDefault =3D *static_cast<KaxTrackF=
lagDefault*>(TrackEntry[Index1]);
- //newTrack->FlagDefault =3D TrackFlagDefault;
- /* Matroska2
- } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrack=
FlagEnabled::ClassInfos.GlobalId) {
- KaxTrackFlagEnabled &TrackFlagEnabled =3D *static_cast<KaxTrackF=
lagEnabled*>(TrackEntry[Index1]);
- //newTrack->FlagEnabled =3D TrackFlagEnabled;
- */
- } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrack=
FlagLacing::ClassInfos.GlobalId) {
- KaxTrackFlagLacing &TrackFlagLacing =3D *static_cast<KaxTrackFla=
gLacing*>(TrackEntry[Index1]);
- //newTrack->FlagLacing =3D TrackFlagLacing;
-
- } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrack=
Language::ClassInfos.GlobalId) {
- KaxTrackLanguage &TrackLanguage =3D *static_cast<KaxTrackLanguag=
e*>(TrackEntry[Index1]);
- newTrack.language =3D std::string(TrackLanguage);
-
- } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrack=
MaxCache::ClassInfos.GlobalId) {
- KaxTrackMaxCache &TrackMaxCache =3D *static_cast<KaxTrackMaxCach=
e*>(TrackEntry[Index1]);
- //newTrack->MaxCache =3D TrackMaxCache;
-
- } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrack=
MinCache::ClassInfos.GlobalId) {
- KaxTrackMinCache &TrackMinCache =3D *static_cast<KaxTrackMinCach=
e*>(TrackEntry[Index1]);
- //newTrack->MinCache =3D TrackMinCache;
-
- } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrack=
Name::ClassInfos.GlobalId) {
- KaxTrackName &TrackName =3D *static_cast<KaxTrackName*>(TrackEnt=
ry[Index1]);
- newTrack.name =3D TrackName;
-
- } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrack=
Audio::ClassInfos.GlobalId) {
- KaxTrackAudio &TrackAudio =3D *static_cast<KaxTrackAudio*>(Track=
Entry[Index1]);
-
- unsigned int Index2;
- for (Index2 =3D 0; Index2 < TrackAudio.ListSize(); Index2++) {
- if (TrackAudio[Index2]->Generic().GlobalId =3D=3D KaxAudioBitDe=
pth::ClassInfos.GlobalId) {
- KaxAudioBitDepth &AudioBitDepth =3D *static_cast<KaxAudioBitDe=
pth*>(TrackAudio[Index2]);
- newTrack.bitsPerSample =3D AudioBitDepth;
- /* Matroska2
- } else if (TrackAudio[Index2]->Generic().GlobalId =3D=3D KaxAud=
ioPosition::ClassInfos.GlobalId) {
- KaxAudioPosition &AudioPosition =3D *static_cast<KaxAudioPosit=
ion*>(TrackAudio[Index2]);
-
- // TODO: Support multi-channel?
- //newTrack->audio->ChannelPositionSize =3D AudioPosition.GetSi=
ze();
- //newTrack->audio->ChannelPosition =3D new binary[AudioPositio=
n.GetSize()+1];
- //memcpy(newTrack->audio->ChannelPosition, AudioPosition.GetBu=
ffer(), AudioPosition.GetSize());
- */
- } else if (TrackAudio[Index2]->Generic().GlobalId =3D=3D KaxAud=
ioChannels::ClassInfos.GlobalId) {
- KaxAudioChannels &AudioChannels =3D *static_cast<KaxAudioChann=
els*>(TrackAudio[Index2]);
- newTrack.channels =3D AudioChannels;
-
- } else if (TrackAudio[Index2]->Generic().GlobalId =3D=3D KaxAud=
ioOutputSamplingFreq::ClassInfos.GlobalId) {
- KaxAudioOutputSamplingFreq &AudioOutputSamplingFreq =3D *stati=
c_cast<KaxAudioOutputSamplingFreq*>(TrackAudio[Index2]);
- newTrack.samplesOutputPerSec =3D AudioOutputSamplingFreq;
-
- } else if (TrackAudio[Index2]->Generic().GlobalId =3D=3D KaxAud=
ioSamplingFreq::ClassInfos.GlobalId) {
- KaxAudioSamplingFreq &AudioSamplingFreq =3D *static_cast<KaxAu=
dioSamplingFreq*>(TrackAudio[Index2]);
- newTrack.samplesPerSec =3D AudioSamplingFreq;
- }
- }
- }
- }
- if (newTrack.trackNumber !=3D 0xFFFF)
- m_Tracks.push_back(newTrack);
- }
- }
- } else if (EbmlId(*ElementLevel1) =3D=3D KaxCluster::ClassInfos.Globa=
lId) {
- if (bBreakAtClusters) {
- m_IOCallback.setFilePointer(ElementLevel1->GetElementPosition());
- //delete ElementLevel1;
- //ElementLevel1 =3D NULL;
- //_DELETE(ElementLevel1);
- break;
- }
- } else if (EbmlId(*ElementLevel1) =3D=3D KaxAttachments::ClassInfos.G=
lobalId) {
- // Yep, we've found our KaxAttachment element. Now find all attached=
files
- // contained in this segment.
-#if 1
- ElementLevel2 =3D ElementPtr(m_InputStream.FindNextElement(ElementLe=
vel1->Generic().Context, UpperElementLevel, 0xFFFFFFFFL, true, 1));
- while (ElementLevel2 !=3D NullElement) {
- if (UpperElementLevel > 0) {
- break;
- }
- if (UpperElementLevel < 0) {
- UpperElementLevel =3D 0;
- }
- if (EbmlId(*ElementLevel2) =3D=3D KaxAttached::ClassInfos.GlobalId)=
{
- // We actually found a attached file entry :D
- MatroskaAttachment newAttachment;
-
- ElementLevel3 =3D ElementPtr(m_InputStream.FindNextElement(Element=
Level2->Generic().Context, UpperElementLevel, 0xFFFFFFFFL, true, 1));
- while (ElementLevel3 !=3D NullElement) {
- if (UpperElementLevel > 0) {
- break;
- }
- if (UpperElementLevel < 0) {
- UpperElementLevel =3D 0;
- }
-
- // Now evaluate the data belonging to this track
- if (EbmlId(*ElementLevel3) =3D=3D KaxFileName::ClassInfos.GlobalI=
d) {
- KaxFileName &attached_filename =3D *static_cast<KaxFileName *>(E=
lementLevel3.get());
- attached_filename.ReadData(m_InputStream.I_O());
- newAttachment.FileName =3D UTFstring(attached_filename);
-
- } else if (EbmlId(*ElementLevel3) =3D=3D KaxMimeType::ClassInfos.=
GlobalId) {
- KaxMimeType &attached_mime_type =3D *static_cast<KaxMimeType *>(=
ElementLevel3.get());
- attached_mime_type.ReadData(m_InputStream.I_O());
- newAttachment.MimeType =3D std::string(attached_mime_type);
-
- } else if (EbmlId(*ElementLevel3) =3D=3D KaxFileDescription::Clas=
sInfos.GlobalId) {
- KaxFileDescription &attached_description =3D *static_cast<KaxFil=
eDescription *>(ElementLevel3.get());
- attached_description.ReadData(m_InputStream.I_O());
- newAttachment.Description =3D UTFstring(attached_description);
-
- } else if (EbmlId(*ElementLevel3) =3D=3D KaxFileData::ClassInfos.=
GlobalId) {
- KaxFileData &attached_data =3D *static_cast<KaxFileData *>(Eleme=
ntLevel3.get());
-
- //We don't what to read the data into memory because it could be=
very large
- //attached_data.ReadData(m_InputStream.I_O());
-
- //Instead we store the Matroska filename, the start of the data =
and the length, so we can read it
- //later at the users request. IMHO This will save a lot of memor=
y
- newAttachment.SourceStartPos =3D attached_data.GetElementPositio=
n() + attached_data.HeadSize();
- newAttachment.SourceDataLength =3D attached_data.GetSize();
- }
-
- if (UpperElementLevel > 0) { // we're coming from ElementLevel4
- UpperElementLevel--;
- ElementLevel3 =3D ElementLevel4;
- if (UpperElementLevel > 0)
- break;
- } else {
- ElementLevel3->SkipData(m_InputStream, ElementLevel3->Generic().=
Context);
- ElementLevel3 =3D ElementPtr(m_InputStream.FindNextElement(Eleme=
ntLevel2->Generic().Context, UpperElementLevel, 0xFFFFFFFFL, true, 1));
- } =09
- } // while (ElementLevel3 !=3D NULL)
- //m_AttachmentList.push_back(newAttachment);
- m_AttachmentList.add_item(newAttachment);
- }
-
- if (UpperElementLevel > 0) { // we're coming from ElementLevel3
- UpperElementLevel--;
- ElementLevel2 =3D ElementLevel3;
- if (UpperElementLevel > 0)
- break;
- } else {
- ElementLevel2->SkipData(m_InputStream, ElementLevel2->Generic().Co=
ntext);
- ElementLevel2 =3D ElementPtr(m_InputStream.FindNextElement(Element=
Level1->Generic().Context, UpperElementLevel, 0xFFFFFFFFL, true, 1));
- }
- } // while (ElementLevel2 !=3D NULL)
-#endif
- }
- =09
- if (UpperElementLevel > 0) { // we're coming from ElementLevel2
- UpperElementLevel--;
- //delete ElementLevel1;
- //_DELETE(ElementLevel1);
- ElementLevel1 =3D ElementLevel2;
- if (UpperElementLevel > 0)
- break;
- } else {
- ElementLevel1->SkipData(m_InputStream, ElementLevel1->Generic().Cont=
ext);
- //delete ElementLevel1;
- //ElementLevel1 =3D NULL;
- //_DELETE(ElementLevel1);
-
- ElementLevel1 =3D ElementPtr(m_InputStream.FindNextElement(m_Element=
Level0->Generic().Context, UpperElementLevel, 0xFFFFFFFFFFFFFFFFL, true, =
1));
- }
- } // while (ElementLevel1 !=3D NULL)
- //_DELETE(ElementLevel3);
- //_DELETE(ElementLevel2);
- //_DELETE(ElementLevel1);
- } catch (std::exception &) {
- return 1;
-
- } catch (...) {
- return 1;
- }
-
- CountClusters();
- return 0;
-};
-
-//int MatroskaAudioParser::WriteTags(const file_info & info)
-int MatroskaAudioParser::WriteTags()
-{
- KaxTags & MyKaxTags =3D GetChild<KaxTags>(*static_cast<EbmlMaster *>(m_=
ElementLevel0.get()));
-
- // On to writing :)
- if (m_TagPos =3D=3D 0) {
- // Ok, we need to append the tags onto the end of the file, no existin=
g tag element
- m_TagPos =3D m_FileSize;
- } else {
- =09
- }=09
-
- //Start going through the list and adding tags
- KaxTag *MyKaxTag_last =3D NULL;
- for(size_t current_tag_track =3D 0; current_tag_track < m_Tags.size(); =
current_tag_track++) {
- KaxTag *MyKaxTag =3D NULL;
- if (MyKaxTag_last !=3D NULL)
- {
- MyKaxTag =3D &GetNextChild<KaxTag>(MyKaxTags, *MyKaxTag_last);
- MyKaxTag_last =3D MyKaxTag;
- }else {
- MyKaxTag =3D &GetChild<KaxTag>(MyKaxTags);
- MyKaxTag_last =3D MyKaxTag;
- }
- MatroskaTagInfo ¤tTag =3D m_Tags.at(current_tag_track);
- //The Targets group
- KaxTagTargets & MyKaxTagTargets =3D GetChild<KaxTagTargets>(*MyKaxTag)=
;
- if (currentTag.targetTrackUID !=3D 0) {
- KaxTagTrackUID & MyKaxTagTrackUID =3D GetChild<KaxTagTrackUID>(MyKaxT=
agTargets);
- *static_cast<EbmlUInteger *>(&MyKaxTagTrackUID) =3D currentTag.target=
TrackUID;
- }
- if (currentTag.targetEditionUID !=3D 0) {
- KaxTagEditionUID & MyKaxTagEditionUID =3D GetChild<KaxTagEditionUID>(=
MyKaxTagTargets);
- *static_cast<EbmlUInteger *>(&MyKaxTagEditionUID) =3D currentTag.targ=
etEditionUID;
- }
- if (currentTag.targetChapterUID !=3D 0) {
- KaxTagChapterUID & MyKaxTagChapterUID =3D GetChild<KaxTagChapterUID>(=
MyKaxTagTargets);
- *static_cast<EbmlUInteger *>(&MyKaxTagChapterUID) =3D currentTag.targ=
etChapterUID;
- }
- if (currentTag.targetAttachmentUID !=3D 0) {
- KaxTagAttachmentUID & MyKaxTagAttachmentUID =3D GetChild<KaxTagAttach=
mentUID>(MyKaxTagTargets);
- *static_cast<EbmlUInteger *>(&MyKaxTagAttachmentUID) =3D currentTag.t=
argetAttachmentUID;
- }
- if(currentTag.targetTypeValue !=3D 0) {
- KaxTagTargetTypeValue& MyKaxTagTargetTypeValue =3D GetChild<KaxTagTar=
getTypeValue>(MyKaxTagTargets);
- *static_cast<EbmlUInteger *>(&MyKaxTagTargetTypeValue) =3D currentTag=
.targetTypeValue;
- if(!currentTag.targetType.empty())
- {
- KaxTagTargetType& MyKaxTagTargetType =3D GetChild<KaxTagTargetType>(=
MyKaxTagTargets);
- *static_cast<EbmlString *>(&MyKaxTagTargetType) =3D currentTag.targe=
tType; =09
- }
- }
- =09
- // Add the millions of simple tags we can have ;)
- KaxTagSimple *MySimpleTag_last =3D NULL;
- for(size_t st =3D 0; st < currentTag.tags.size(); st++) {
- KaxTagSimple *MySimpleTag =3D NULL;
- if (MySimpleTag_last !=3D NULL)
- {
- MySimpleTag =3D &GetNextChild<KaxTagSimple>(*MyKaxTag, *MySimpleTag_=
last);
- MySimpleTag_last =3D MySimpleTag;
- }else {
- MySimpleTag =3D &GetChild<KaxTagSimple>(*MyKaxTag);
- MySimpleTag_last =3D MySimpleTag;
- }
- MatroskaSimpleTag ¤tSimpleTag =3D currentTag.tags.at(st);
-
- KaxTagName & MyKaxTagName =3D GetChild<KaxTagName>(*MySimpleTag);
- *static_cast<EbmlUnicodeString *>(&MyKaxTagName) =3D currentSimpleTag=
.name;
-
- KaxTagString & MyKaxTagString =3D GetChild<KaxTagString>(*MySimpleTag=
);
- *static_cast<EbmlUnicodeString *>(&MyKaxTagString) =3D currentSimpleT=
ag.value;
- =09
- KaxTagLangue& MyKaxTagLangue =3D GetChild<KaxTagLangue>(*MySimpleTag)=
;
- *static_cast<EbmlString *>(&MyKaxTagLangue) =3D currentSimpleTag.lang=
uage;
-
- KaxTagDefault& MyKaxTagDefault =3D GetChild<KaxTagDefault>(*MySimpleT=
ag);
- *static_cast<EbmlUInteger *>(&MyKaxTagDefault) =3D currentSimpleTag.d=
efaultFlag; =09
- }
-
- m_IOCallback.setFilePointer(m_TagPos);
- // Now we write the tags to the file
- EbmlVoid & Dummy =3D GetChild<EbmlVoid>(*static_cast<EbmlMaster *>(m_E=
lementLevel0.get()));
- uint64 size_of_tags =3D m_TagSize;
- MyKaxTags.UpdateSize(true);
- if (size_of_tags < MyKaxTags.GetSize())
- size_of_tags =3D MyKaxTags.GetSize();
-
- Dummy.SetSize(size_of_tags+8); // Size of the previous tag element
- uint64 pos =3D m_IOCallback.getFilePointer();
- if (pos =3D=3D 0)
- //We don't want to overwrite the EBML header :P
- return 2;
- Dummy.Render(m_IOCallback);
- m_IOCallback.setFilePointer(Dummy.GetElementPosition());
- pos =3D m_IOCallback.getFilePointer();
- if (pos =3D=3D 0)
- //We don't want to overwrite the EBML header :P
- return 2;
-
- MyKaxTags.Render(m_IOCallback);
- =09
- //l0->UpdateSize(false, true);
- std::auto_ptr<KaxSegment> new_segment(new KaxSegment);
- KaxSegment * segment =3D (KaxSegment *)m_ElementLevel0.get();
-
- m_IOCallback.setFilePointer(segment->GetElementPosition());
- new_segment->WriteHead(m_IOCallback, segment->HeadSize() - 4);
- m_IOCallback.setFilePointer(0, seek_end);
- int ret =3D new_segment->ForceSize(m_IOCallback.getFilePointer() - seg=
ment->HeadSize() - segment->GetElementPosition());
- if (!ret) {=20
- segment->OverwriteHead(m_IOCallback);
- /*("Wrote the element at the end of the file but could "
- "not update the segment size. Therefore the elemen=
t "
- "will not be visible. Aborting the process. The fi=
le "
- "has been changed!")*/
- m_IOCallback.setFilePointer(segment->HeadSize() - segment->GetElement=
Position());
- m_IOCallback.truncate();
-
- return 1;
- } else {
- new_segment->OverwriteHead(m_IOCallback);
-
- }
-
- }
- return 0;
-};
-
-static const char* foobar2k_to_matroska_edition_tag(const char * name)
-{
- if (!stricmp_utf8(name, "ALBUM"))
- return "TITLE";
- else if (!stricmp_utf8(name, "SUBALBUM"))
- return "SUBTITLE";
- else if (starts_with(name, "ALBUM ")) {
- static char newname[255];
- ZeroMemory(newname,255);
- strncpy(newname,name+6,254);
- name =3D newname;
- }
- for (int i =3D 0; i < tabsize(edition_tag_mapping); i++)
- if (!stricmp_utf8(name, edition_tag_mapping[i][FOOBAR2K_TAG_IDX]))
- return edition_tag_mapping[i][MATROSKA_TAG_IDX];
- return name;
-}
-
-static const char* foobar2k_to_matroska_chapter_tag(const char * name)
-{
- for (int i =3D 0; i < tabsize(chapter_tag_mapping); i++)
- if (!stricmp_utf8(name, chapter_tag_mapping[i][FOOBAR2K_TAG_IDX]))
- return chapter_tag_mapping[i][MATROSKA_TAG_IDX];
- return name;
-}
-
-int meta_get_num(const file_info &info, const char* name, int idx)
-{
- assert(pfc::is_valid_utf8(name));
- int n, m =3D min(info.meta_get_count(), idx);
- int rv =3D 0;
- for(n=3D0; n<m; n++)
- {
- if (!stricmp_utf8(name, info.meta_enum_name(n)))
- rv++;
- }
- return rv;
-}
-
-bool isEditionTag(const char * name) {
- if (starts_with(name, "ALBUM") ||
- starts_with(name, "SUBALBUM") ||
- starts_with(name, "DISCID") ||
- starts_with(name, "CATALOG"))
- {
- return true;
- } else {
- return false;
- }
-}
-
-void MatroskaAudioParser::SetTags(const file_info &info)
-{
- int i, idx;
- const char *name, *value;=09
-
- if (m_Chapters.size() =3D=3D 0)
- { =09
- // No chapters, works on track
- MatroskaTagInfo *trackTag;
- trackTag =3D FindTagWithTrackUID(m_Tracks.at(m_CurrentTrackNo).trackUI=
D);
- if (trackTag =3D=3D NULL) {
- // The tag doesn't exist yet
- MatroskaTagInfo tempTag;
- tempTag.targetTrackUID =3D m_Tracks.at(m_CurrentTrackNo).trackUID;
- m_Tags.push_back(tempTag);
- trackTag =3D &m_Tags.at(m_Tags.size()-1);
- }
- //if(trackTag->targetTypeValue =3D=3D 0)
- // trackTag->targetTypeValue =3D 50;
- trackTag->targetTypeValue =3D 30;
- trackTag->MarkAllAsRemovalPending();
- int metaDataCount =3D info.meta_get_count();
- for (i =3D 0; i < metaDataCount; i++)
- {
- for (int j =3D 0; j !=3D info.meta_enum_value_count(i); ++j) {
- name =3D info.meta_enum_name(i);
- value =3D info.meta_enum_value(i, j);
- //idx =3D meta_get_num(info, name, i);
- idx =3D j;
- name =3D foobar2k_to_matroska_chapter_tag(name);
- if ((name !=3D NULL) && (value !=3D NULL)) {
- trackTag->SetTagValue(name, value, idx);
- }
- }
- }
- // Add the replay_gain tags
- replaygain_info rg =3D info.get_replaygain();
- if (rg.is_track_gain_present()) {
- char tmp[rg.text_buffer_size];
- pfc::float_to_string(tmp, rg.text_buffer_size, rg.m_track_gain, 7);
- value =3D (const char*)tmp;
- } else {
- value =3D NULL;
- }
- if (value)
- trackTag->SetTagValue("REPLAYGAIN_GAIN", value);
- if (rg.is_track_peak_present()) {
- char tmp[rg.text_buffer_size];
- pfc::float_to_string(tmp, rg.text_buffer_size, rg.m_track_peak, 7);
- value =3D (const char*)tmp;
- } else {
- value =3D NULL;
- }
- if (value)
- trackTag->SetTagValue("REPLAYGAIN_PEAK", value);
- trackTag->RemoveMarkedTags();
- }
-=09
- // Set global track tags as album tags
- if ((m_Chapters.size() > 0) && (m_CurrentChapter !=3D NULL))
- {
- MatroskaTagInfo *trackTag;
- trackTag =3D FindTagWithTrackUID(m_Tracks.at(m_CurrentTrackNo).trackUI=
D);
- if (trackTag =3D=3D NULL)
- {
- MatroskaTagInfo tempTag;
- tempTag.targetTrackUID =3D m_Tracks.at(m_CurrentTrackNo).trackUID; =09
- m_Tags.push_back(tempTag);
- trackTag =3D &m_Tags.at(m_Tags.size()-1);
- }
- if(trackTag->targetTypeValue =3D=3D 0)
- trackTag->targetTypeValue =3D 50;
- trackTag->MarkAllAsRemovalPending();
- int metaDataCount =3D info.meta_get_count();
- for (i =3D 0; i < metaDataCount; i++)
- {
- for (int j =3D 0; j !=3D info.meta_enum_value_count(i); ++j) {
- name =3D info.meta_enum_name(i);
- value =3D info.meta_enum_value(i, j);
- //idx =3D meta_get_num(info, name, i);
- idx =3D j;
- if (isEditionTag(name))
- {
- name =3D foobar2k_to_matroska_edition_tag(name);
- } else {
- name =3D NULL;
- }
- if ((name !=3D NULL) && (value !=3D NULL)) {
- trackTag->SetTagValue(name, value, idx);
- }
- }
- }
- replaygain_info rg =3D info.get_replaygain();
- if (rg.is_album_gain_present()) {
- char tmp[rg.text_buffer_size];
- pfc::float_to_string(tmp, rg.text_buffer_size, rg.m_album_gain, 7);
- value =3D (const char*)tmp;
- } else {
- value =3D NULL;
- }
- if (value)
- trackTag->SetTagValue("REPLAYGAIN_GAIN", value);
- if (rg.is_album_peak_present()) {
- char tmp[rg.text_buffer_size];
- pfc::float_to_string(tmp, rg.text_buffer_size, rg.m_album_peak, 7);
- value =3D (const char*)tmp;
- } else {
- value =3D NULL;
- }
- if (value)
- trackTag->SetTagValue("REPLAYGAIN_PEAK", value);
- trackTag->RemoveMarkedTags();
- }
-
-
- //If there's not only a track, set all the chapter tags
- if ((m_Chapters.size() > 0) && (m_CurrentChapter !=3D NULL))
- {
- // Ok we add the tags to tag with chapter+track UID's
- MatroskaTagInfo *chapterTag; =09
- chapterTag =3D FindTagWithChapterUID(m_CurrentChapter->chapterUID,
- m_Tracks.at(m_CurrentTrackNo).trackUID);
- if (chapterTag =3D=3D NULL)
- {
- MatroskaTagInfo tempTag;
- tempTag.targetTrackUID =3D m_Tracks.at(m_CurrentTrackNo).trackUID;
- tempTag.targetChapterUID =3D m_CurrentChapter->chapterUID;
- m_Tags.push_back(tempTag);
- chapterTag =3D &m_Tags.at(m_Tags.size()-1);
- }
- if(chapterTag->targetTypeValue =3D=3D 0)
- chapterTag->targetTypeValue =3D 30;
- chapterTag->MarkAllAsRemovalPending();
- int metaDataCount =3D info.meta_get_count();
- for (i =3D 0; i < metaDataCount; i++)
- {
- for (int j =3D 0; j !=3D info.meta_enum_value_count(i); ++j) {
- name =3D info.meta_enum_name(i);
- value =3D info.meta_enum_value(i, j);
- //idx =3D meta_get_num(info, name, i);
- idx =3D j;
- if (isEditionTag(name))
- {
- name =3D NULL;
- } else {
- name =3D foobar2k_to_matroska_chapter_tag(name);
- }
- if ((name !=3D NULL) && (value !=3D NULL)) {
- chapterTag->SetTagValue(name, value, idx);
- }
- }
- }
- replaygain_info rg =3D info.get_replaygain();
- if (rg.is_track_gain_present()) {
- char tmp[rg.text_buffer_size];
- pfc::float_to_string(tmp, rg.text_buffer_size, rg.m_track_gain, 7);
- value =3D (const char*)tmp;
- } else {
- value =3D NULL;
- }
- if (value)
- chapterTag->SetTagValue("REPLAYGAIN_GAIN", value);
- if (rg.is_track_peak_present()) {
- char tmp[rg.text_buffer_size];
- pfc::float_to_string(tmp, rg.text_buffer_size, rg.m_track_peak, 7);
- value =3D (const char*)tmp;
- } else {
- value =3D NULL;
- }
- if (value)
- chapterTag->SetTagValue("REPLAYGAIN_PEAK", value);
- chapterTag->RemoveMarkedTags();
- }
-};
-
-MatroskaTagInfo *MatroskaAudioParser::FindTagWithTrackUID(uint64 trackUI=
D)=20
-{
- MatroskaTagInfo *foundTag =3D NULL;
-
- for (size_t t =3D 0; t < m_Tags.size(); t++)
- {
- MatroskaTagInfo& currentTag =3D m_Tags.at(t);
- if (currentTag.targetTrackUID =3D=3D trackUID &&
- currentTag.targetEditionUID =3D=3D 0 &&
- currentTag.targetChapterUID =3D=3D 0 &&
- currentTag.targetAttachmentUID =3D=3D 0)
- {
- foundTag =3D ¤tTag;
- break;
- }
- }
-
- return foundTag;
-};
-
-MatroskaTagInfo *MatroskaAudioParser::FindTagWithEditionUID(uint64 editi=
onUID, uint64 trackUID)
-{
- MatroskaTagInfo *foundTag =3D NULL;
-
- for (size_t t =3D 0; t < m_Tags.size(); t++)
- {
- MatroskaTagInfo ¤tTag =3D m_Tags.at(t);
- if (currentTag.targetEditionUID =3D=3D editionUID &&
- (trackUID =3D=3D 0 || (currentTag.targetTrackUID =3D=3D trackUID)))
- {
- foundTag =3D ¤tTag;
- break;
- }
- }
-
- return foundTag;
-};
-
-MatroskaTagInfo *MatroskaAudioParser::FindTagWithChapterUID(uint64 chapt=
erUID, uint64 trackUID)
-{
- MatroskaTagInfo *foundTag =3D NULL;
-
- for (size_t t =3D 0; t < m_Tags.size(); t++)
- {
- MatroskaTagInfo ¤tTag =3D m_Tags.at(t);
- if (currentTag.targetChapterUID =3D=3D chapterUID &&
- (trackUID =3D=3D 0 || (currentTag.targetTrackUID =3D=3D trackUID)))
- {
- foundTag =3D ¤tTag;
- break;
- }
- }
-
- return foundTag;
-};
-
-double MatroskaAudioParser::GetDuration() {=20
- if (m_CurrentChapter !=3D NULL) {
- return TimecodeToSeconds(m_CurrentChapter->timeEnd - m_CurrentChapter-=
>timeStart);
- };
- return m_Duration / 1000000000.0;
- if (m_Tracks.size() !=3D 0) {
- return m_Tracks.at(m_CurrentTrackNo).defaultDuration * (int64)m_Timeco=
deScale;
- }
-};
-
-int32 MatroskaAudioParser::GetFirstAudioTrack()
-{
- for (uint16 t =3D 0; t < m_Tracks.size(); t++)
- {
- MatroskaTrackInfo ¤tTrack =3D m_Tracks.at(t);
- if (!strncmp(currentTrack.codecID.c_str(),"A_",2)) return t;
- }
- return -1;
-}
-
-uint32 MatroskaAudioParser::GetAudioTrackCount()
-{
- uint32 count =3D 0;
- for (uint16 t =3D 0; t < m_Tracks.size(); t++)
- {
- MatroskaTrackInfo ¤tTrack =3D m_Tracks.at(t);
- if (!strncmp(currentTrack.codecID.c_str(),"A_",2))
- count++;
- }
- return count;
-}
-
-uint32 MatroskaAudioParser::GetAudioTrackIndex(uint32 index)
-{
- uint32 idx =3D 0;
- for (uint16 t =3D 0; t < m_Tracks.size(); t++)
- {
- MatroskaTrackInfo ¤tTrack =3D m_Tracks.at(t);
- if (!strncmp(currentTrack.codecID.c_str(),"A_",2))
- {
- if(t =3D=3D index)
- break;
- idx++;
- }
- }
- return idx;
-}
-
-static bool is_rg_field(const char * name)
-{
- int m;
- for (m =3D 0; m < tabsize(rg_fields); m++)
- {
- if (!stricmp_utf8(name,rg_fields[m])) return true;
- }
- return false;
-}
-
-static bool is_hidden_edition_field(const char * name)
-{
- for (int i =3D 0; i < tabsize(hidden_edition_field); i++)
- if (!stricmp_utf8(name, hidden_edition_field[i]))
- return true;
- return false;
-}
-
-static bool is_hidden_chapter_field(const char * name)
-{
- for (int i =3D 0; i < tabsize(hidden_chapter_field); i++)
- if (!stricmp_utf8(name, hidden_chapter_field[i]))
- return true;
- return false;
-}
-
-static const char* matroska_to_foobar2k_edition_tag(const char * name)
-{
- for (int i =3D 0; i < tabsize(edition_tag_mapping); i++)
- if (!stricmp_utf8(name, edition_tag_mapping[i][MATROSKA_TAG_IDX]))
- return edition_tag_mapping[i][FOOBAR2K_TAG_IDX];
- return name;
-}
-
-static const char* matroska_to_foobar2k_chapter_tag(const char * name)
-{
- for (int i =3D 0; i < tabsize(chapter_tag_mapping); i++)
- if (!stricmp_utf8(name, chapter_tag_mapping[i][MATROSKA_TAG_IDX]))
- return chapter_tag_mapping[i][FOOBAR2K_TAG_IDX];
- return name;
-}
-
-static void convert_matroska_to_foobar2k_tag(pfc::string_base & p_out, c=
onst char * p_name)
-{
- pfc::string8 name(p_name);
- //name.replace_char('_', ' ');
- p_out =3D name;
-}
-
-static bool IsTagNamed(const MatroskaSimpleTag ¤tSimpleTag, const =
char * name)
-{
- return !stricmp_utf8(currentSimpleTag.name.GetUTF8().c_str(), name);
-}
-
-static bool IsTagValued(const MatroskaSimpleTag ¤tSimpleTag, const=
char * value)
-{
- return !strcmp(currentSimpleTag.value.GetUTF8().c_str(), value);
-}
-
-static bool AreTagsNameEqual(const MatroskaSimpleTag &tag1, const Matros=
kaSimpleTag &tag2)
-{
- return !stricmp_utf8(tag1.name.GetUTF8().c_str(), tag2.name.GetUTF8().c=
_str());
-}
-
-static bool AreTagsValueEqual(const MatroskaSimpleTag &tag1, const Matro=
skaSimpleTag &tag2)
-{
- return !strcmp(tag1.value.GetUTF8().c_str(), tag2.value.GetUTF8().c_str=
());
-}
-
-static bool AreTagsEqual(const MatroskaSimpleTag &tag1, const MatroskaSi=
mpleTag &tag2)
-{
- return AreTagsNameEqual(tag1,tag2) && AreTagsValueEqual(tag1,tag2);
-}
-
-const MatroskaSimpleTag* GetTagWithName(MatroskaTagInfo *SimpleTags, con=
st char * name)
-{
- if(SimpleTags =3D=3D NULL)
- return NULL;
-
- for (size_t s =3D 0; s < SimpleTags->tags.size(); s++)
- {
- const MatroskaSimpleTag ¤tSimpleTag =3D SimpleTags->tags.at(s); =
=09
- if(IsTagNamed(currentSimpleTag, name))
- return ¤tSimpleTag;
- }
- return NULL;
-}
-
-bool TagExistsAtEditionLevel(MatroskaTagInfo *TrackTags, const char * na=
me)
-{
- if(TrackTags =3D=3D NULL)
- return false;
-
- for (size_t s =3D 0; s < TrackTags->tags.size(); s++)
- {
- const MatroskaSimpleTag ¤tSimpleTag =3D TrackTags->tags.at(s); =09
- if(IsTagNamed(currentSimpleTag,name))
- return true;
- }
- return false;
-}
-
-bool TagExistsAtChapterLevel(MatroskaTagInfo *ChapterTags, const char * =
name)
-{
- if(ChapterTags =3D=3D NULL)
- return false;
-
- for (size_t s =3D 0; s < ChapterTags->tags.size(); s++)
- {
- const MatroskaSimpleTag ¤tSimpleTag =3D ChapterTags->tags.at(s);=
=09
- if(IsTagNamed(currentSimpleTag,name))
- return true;
- }
- return false;
-}
-
-bool MatroskaAudioParser::AreTagsIdenticalAtAllLevels(const char * name)
-{
- const MatroskaSimpleTag* ReferenceTag =3D NULL;
- bool AtLeastOneChapter =3D false;
-
- for (size_t i =3D 0; i < m_Tags.size(); i++)
- {
- MatroskaTagInfo ¤tTags =3D m_Tags.at(i);
- if(ReferenceTag =3D=3D NULL)
- {
- AtLeastOneChapter =3D true;
- ReferenceTag =3D GetTagWithName(¤tTags, name);
- } else {
- const MatroskaSimpleTag* TagToCheck =3D GetTagWithName(¤tTags, =
name);
- if(TagToCheck && !AreTagsValueEqual(*ReferenceTag,*TagToCheck))
- return false; =09
- }
- }
- return AtLeastOneChapter;
-}
-
-bool MatroskaAudioParser::AreTagsIdenticalAtEditionLevel(const char * na=
me)
-{
- const MatroskaSimpleTag* ReferenceTag =3D NULL;
- bool AtLeastOneChapter =3D false;
-
- for (size_t i =3D 0; i < m_Tags.size(); i++)
- {
- MatroskaTagInfo ¤tTags =3D m_Tags.at(i);
- if (currentTags.targetChapterUID =3D=3D 0)
- {
- // Chapter tags
- if(ReferenceTag =3D=3D NULL)
- {
- AtLeastOneChapter =3D true;
- ReferenceTag =3D GetTagWithName(¤tTags, name);
- } else {
- const MatroskaSimpleTag* TagToCheck =3D GetTagWithName(¤tTags,=
name);
- if(TagToCheck && !AreTagsValueEqual(*ReferenceTag,*TagToCheck))
- return false; =09
- }
- }
- }
- return AtLeastOneChapter;
-}
-
-bool MatroskaAudioParser::AreTagsIdenticalAtChapterLevel(const char * na=
me)
-{
- const MatroskaSimpleTag* ReferenceTag =3D NULL;
- bool AtLeastOneChapter =3D false;
-
- for (size_t i =3D 0; i < m_Tags.size(); i++)
- {
- MatroskaTagInfo ¤tTags =3D m_Tags.at(i);
- if (currentTags.targetChapterUID !=3D 0)
- {
- // Chapter tags
- if(ReferenceTag =3D=3D NULL)
- {
- AtLeastOneChapter =3D true;
- ReferenceTag =3D GetTagWithName(¤tTags, name);
- } else {
- const MatroskaSimpleTag* TagToCheck =3D GetTagWithName(¤tTags,=
name);
- if(TagToCheck && !AreTagsValueEqual(*ReferenceTag,*TagToCheck))
- return false; =09
- }
- }
- }
- return AtLeastOneChapter;
-}
-
-void MatroskaAudioParser::SetAlbumTags(file_info & info,
- MatroskaTagInfo* AlbumTags,
- MatroskaTagInfo* TrackTags)
-{
- if (AlbumTags =3D=3D NULL)
- return;
-
- for (size_t s =3D 0; s < AlbumTags->tags.size(); s++)
- {
- MatroskaSimpleTag &simpleTag =3D AlbumTags->tags.at(s);
- =09
- if (is_rg_field(simpleTag.name.GetUTF8().c_str()))
- {
- if(IsTagNamed(simpleTag, "REPLAYGAIN_GAIN"))
- {
- info.info_set_replaygain("replaygain_album_gain", simpleTag.value.Ge=
tUTF8().c_str());
- if (TrackTags =3D=3D NULL) info.info_set_replaygain("replaygain_trac=
k_gain", simpleTag.value.GetUTF8().c_str());
- } else if(IsTagNamed(simpleTag, "REPLAYGAIN_PEAK")) {
- info.info_set_replaygain("replaygain_album_peak", simpleTag.value.Ge=
tUTF8().c_str());
- if (TrackTags =3D=3D NULL) info.info_set_replaygain("replaygain_trac=
k_peak", simpleTag.value.GetUTF8().c_str());
- }
- }
- else if (is_hidden_edition_field(simpleTag.name.GetUTF8().c_str()))
- {
- // Ignored tag, will be rewrited later
- simpleTag.hidden =3D true;
- }
- else if(IsTagNamed(simpleTag,"TITLE"))
- {
- // Special case for Edition/TITLE
- if(TagExistsAtChapterLevel(TrackTags, "ALBUM"))
- {
- info.meta_add("ALBUM TITLE", simpleTag.value.GetUTF8().c_str());
- } else {
- info.meta_add("ALBUM", simpleTag.value.GetUTF8().c_str());
- }
- }
- /*
- else if(IsTagNamed(simpleTag,"SUBTITLE"))
- {
- // Special case for Edition/SUBTITLE
- if(TagExistsAtChapterLevel(TrackTags, "SUBALBUM"))
- {
- info.meta_add("ALBUM SUBTITLE", simpleTag.value.GetUTF8().c_str());
- } else {
- info.meta_add("SUBALBUM", simpleTag.value.GetUTF8().c_str());
- }
- }
- */
- else if (IsTagNamed(simpleTag, "DISCID") ||
- IsTagNamed(simpleTag, "CATALOG_NUMBER") ||
- IsTagNamed(simpleTag, "TOTAL_PARTS") ||
- IsTagNamed(simpleTag, "PART_NUMBER") ||
- IsTagNamed(simpleTag, "TOTAL_DISCS"))
- {
- info.meta_add(matroska_to_foobar2k_edition_tag(simpleTag.name.GetUTF8=
().c_str()), simpleTag.value.GetUTF8().c_str());
- }
- /*else if (IsTagNamed(simpleTag,"COMMENTS"))
- {
- info.meta_add("ALBUM COMMENT", simpleTag.value.GetUTF8().c_str());
- }*/
- else if((!AreTagsIdenticalAtAllLevels(simpleTag.name.GetUTF8().c_str()=
))
- || (!TagExistsAtChapterLevel(TrackTags, simpleTag.name.GetUTF8().c_st=
r())))
- {
- // Prefix tag with "ALBUM "
- char newTagName[255] =3D "ALBUM ";
- strncat(newTagName, matroska_to_foobar2k_edition_tag(simpleTag.name.G=
etUTF8().c_str()),255);
- pfc::string8 new_tagname;
- convert_matroska_to_foobar2k_tag(new_tagname, newTagName);
- info.meta_add(new_tagname, simpleTag.value.GetUTF8().c_str());
- }
- else=20
- {
- // Ignored tag, will be rewrited later
- simpleTag.hidden =3D true;
- }
- }
-}
-
-void MatroskaAudioParser::SetTrackTags(file_info &info, MatroskaTagInfo*=
TrackTags)
-{
- if(TrackTags =3D=3D NULL)
- return;
-
- for (size_t s =3D 0; s < TrackTags->tags.size(); s++)
- {
- MatroskaSimpleTag &simpleTag =3D TrackTags->tags.at(s);
- =09
- if (is_rg_field(simpleTag.name.GetUTF8().c_str()))
- {
- if(IsTagNamed(simpleTag, "REPLAYGAIN_GAIN"))
- {
- info.info_set_replaygain("replaygain_track_gain", simpleTag.value.Ge=
tUTF8().c_str());
- } else if(IsTagNamed(simpleTag, "REPLAYGAIN_PEAK")) {
- info.info_set_replaygain("replaygain_track_peak", simpleTag.value.Ge=
tUTF8().c_str());
- }
- }
- else if (is_hidden_chapter_field(simpleTag.name.GetUTF8().c_str()))
- {
- // Ignore tag
- simpleTag.hidden =3D true;
- }
- /*else if(IsTagNamed(simpleTag,"COMMENTS"))
- {
- info.meta_add("COMMENT", simpleTag.value.GetUTF8().c_str());
- }*/
- else if(IsTagNamed(simpleTag,"ALBUM"))
- {
- if(!TagExistsAtEditionLevel(TrackTags, "TITLE") && AreTagsIdenticalAt=
ChapterLevel("ALBUM")) {
- info.meta_add("ALBUM", simpleTag.value.GetUTF8().c_str());
- } else {
- info.meta_add("ORIGINAL ALBUM", simpleTag.value.GetUTF8().c_str());
- }
- }
- else
- {
- pfc::string8 new_tagname;
- convert_matroska_to_foobar2k_tag(new_tagname, matroska_to_fo=
obar2k_chapter_tag(simpleTag.name.GetUTF8().c_str()));
- info.meta_add(new_tagname, simpleTag.value.GetUTF8().c_str());=09
- }
- }
-}
-
-bool MatroskaAudioParser::SetFB2KInfo(file_info &info, t_uint32 p_subson=
g)
-{
- if (m_MuxingApp.length() > 0)
- info.info_set("MUXING_APP", m_MuxingApp.GetUTF8().c_str());
- if (m_WritingApp.length() > 0)
- info.info_set("WRITING_APP", m_WritingApp.GetUTF8().c_str());
- if (m_FileTitle.length() > 0)
- info.info_set("TITLE", m_FileTitle.GetUTF8().c_str());
-
- // pregap
- try {
- if (m_Chapters.at(p_subsong).subChapters.size() > 1) {
- double pregap =3D TimecodeToSeconds(m_Chapters.at(p_subsong).subChapt=
ers.at(1).timeStart - m_Chapters.at(p_subsong).subChapters.at(0).timeStar=
t);
- info.info_set("pregap", cuesheet_format_index_time(pregap));
- }
- } catch (std::out_of_range & e) {
- }
-
- MatroskaTagInfo *TrackTags =3D FindTagWithTrackUID(m_Tracks.at(m_Curren=
tTrackNo).trackUID);
- MatroskaTagInfo *ChapterTags =3D NULL;
- if(m_CurrentChapter !=3D NULL)
- {
- ChapterTags =3D FindTagWithChapterUID(m_CurrentChapter->chapterUID,
- m_Tracks.at(m_CurrentTrackNo).trackUID);
- }
-
- MatroskaTagInfo *EditionTags =3D NULL;
- if(m_CurrentEdition !=3D NULL)
- {
- EditionTags =3D FindTagWithEditionUID(m_CurrentEdition->editionUID,
- m_Tracks.at(m_CurrentTrackNo).trackUID);
- }
- if(EditionTags !=3D NULL && EditionTags->targetTypeValue =3D=3D 50)
- {
- SetAlbumTags(info, EditionTags, ChapterTags);
- }
-
- if(TrackTags !=3D NULL)
- {
- if(TrackTags->targetTypeValue =3D=3D 50)
- {
- SetAlbumTags(info, TrackTags, ChapterTags);
- SetTrackTags(info, ChapterTags);
- } else if (TrackTags->targetTypeValue =3D=3D 30) {
- SetTrackTags(info, TrackTags);
- }
- }
-=09
- // Last chance,
- if(m_CurrentChapter !=3D NULL)
- {
- // If TITLE tag is empty we get it from the chapter name
- if ( (m_CurrentChapter->display.size() > 0) &&
- ((info.meta_get("TITLE", 0) =3D=3D NULL) ||
- (strlen(info.meta_get("TITLE", 0)) =3D=3D 0) ) )
- {
- info.meta_set("TITLE", m_CurrentChapter->display.at(0).string.GetUTF8=
().c_str());
- }
- if ((info.meta_get("TRACKNUMBER", 0) =3D=3D NULL) || (strlen(info.meta=
_get("TRACKNUMBER", 0)) =3D=3D 0))
- {
- //char trackNumberString[32];
- pfc::string8 trackNumberString;
-#ifdef MULTITRACK =09
- //wsprintf((LPWSTR)trackNumberString, (LPCWSTR)"%d",
- // (p_subsong % m_Chapters.size()) +1);
- trackNumberString << ((p_subsong % m_Chapters.size()) +1);
-#else
- wsprintf(trackNumberString, "%d",p_subsong+1);
-#endif
- info.meta_set("TRACKNUMBER", trackNumberString);
- }
- if ((info.meta_get("ALBUM", 0) =3D=3D NULL) || (strlen(info.meta_get("=
ALBUM", 0)) =3D=3D 0))
- {
- if(m_FileTitle.length() > 0)
- info.meta_set("ALBUM", m_FileTitle.GetUTF8().c_str());
- }
- }
-
- return true;
-};
-
-void MatroskaAudioParser::MarkHiddenTags()
-{
- // We call MatroskaAudioParser::SetFB2KInfo with a dummy file_info that
- // do nothing, so we will only mark hidden tags.
- // Hidden tag will be copied to keep track of them.
- // This is needed cause tag are read and written in 2 different instanc=
es
- file_info_impl info;
- SetFB2KInfo(info, 0);
-};
-
-void MatroskaAudioParser::SetCurrentTrack(uint32 newTrackNo)
-{
- m_CurrentTrackNo =3D newTrackNo;
- // Clear the current queue (we are changing tracks)
- while (!m_Queue.empty())
- m_Queue.pop();
-};
-
-void MatroskaAudioParser::SetSubSong(int subsong)
-{
- // As we don't (yet?) use several Editions, select the first (default) =
one as the current one.
- m_CurrentEdition =3D NULL;
- m_CurrentChapter =3D NULL;
- if(m_Editions.size() > 0)
- m_CurrentEdition =3D &m_Editions.at(0);
- if (m_Chapters.size() > subsong)
- m_CurrentChapter =3D &m_Chapters.at(subsong);
-=09
-};
-
-int32 MatroskaAudioParser::GetAvgBitrate()=20
-{=20
- double ret =3D 0;
- ret =3D static_cast<double>(int64(m_FileSize)) / 1024;
- ret =3D ret / (m_Duration / 1000000000.0);
- ret =3D ret * 8;
- return static_cast<int32>(ret);
-};
-
-bool MatroskaAudioParser::skip_frames_until(double destination,unsigned =
& frames,double & last_timecode_delta,unsigned hint_samplerate)
-{
- unsigned done =3D 0;
- unsigned last_laced =3D 0;
-
- double last_time;
- {
- uint64 last_timecode =3D get_current_frame_timecode();
- if (last_timecode =3D=3D (uint64)(-1)) return false;
- last_time =3D TimecodeToSeconds(last_timecode,hint_samplerate);
- }
-
- for(;;)
- {
- while (!m_Queue.empty()) {
- MatroskaAudioFrame *currentPacket =3D m_Queue.front();
- double packet_time =3D TimecodeToSeconds(currentPacket->timecode,hint=
_samplerate);
- if (packet_time > destination)
- {
- if (done=3D=3D0) return false;
- last_timecode_delta =3D destination - last_time;
- frames =3D done - last_laced;
- return true;
- }
- last_time =3D packet_time;
- done +=3D (last_laced =3D currentPacket->dataBuffer.size());
- //delete currentPacket;
- _DELETE(currentPacket);
- m_Queue.pop();
- }
- if (FillQueue()!=3D0)
- return false;
- }
-}
-
-
-void MatroskaAudioParser::flush_queue()
-{
- while (!m_Queue.empty()) {
- MatroskaAudioFrame *currentPacket =3D m_Queue.front();
- //delete currentPacket;
- _DELETE(currentPacket);
- m_Queue.pop();
- }
-}
-
-uint64 MatroskaAudioParser::get_current_frame_timecode()
-{
- if (m_Queue.empty())
- {
- if (FillQueue()!=3D0) return -1;
- if (m_Queue.empty()) return -1;
- }
- return m_Queue.front()->timecode;
-}
-
-bool MatroskaAudioParser::Seek(double seconds,unsigned & frames_to_skip,=
double & time_to_skip,unsigned samplerate_hint)
-{
- int64 ret =3D 0;
-
- if (m_CurrentChapter !=3D NULL) {
- seconds +=3D (double)(int64)m_CurrentChapter->timeStart / 1000000000; =
// ns -> seconds
- }
-
- uint64 seekToTimecode =3D SecondsToTimecode(seconds);
-=09
- flush_queue();
- m_CurrentTimecode =3D seekToTimecode;
-
- if (!skip_frames_until(seconds,frames_to_skip,time_to_skip,samplerate_h=
int)) return false;
-
- flush_queue();
- m_CurrentTimecode =3D seekToTimecode;
- if (FillQueue()!=3D0) return false;
- return true;
-
-};
-
-MatroskaAudioFrame * MatroskaAudioParser::ReadSingleFrame()
-{
- for(;;)
- {
- if (!m_Queue.empty()) {
- MatroskaAudioFrame *newFrame =3D m_Queue.front(); =09
- m_Queue.pop();
- return newFrame;
- } else {
- if (FillQueue()!=3D0)
- return 0;
- }
- }
-};
-
-MatroskaAudioFrame * MatroskaAudioParser::ReadFirstFrame()
-{
- m_CurrentTimecode =3D 0;
- return ReadSingleFrame();
-};
-
-typedef boost::shared_ptr<EbmlId> EbmlIdPtr;
-
-void MatroskaAudioParser::Parse_MetaSeek(ElementPtr metaSeekElement, boo=
l bInfoOnly)=20
-{
- TIMER;
- uint64 lastSeekPos =3D 0;
- uint64 endSeekPos =3D 0;
- ElementPtr l2;
- ElementPtr l3;
- ElementPtr NullElement;
- int UpperElementLevel =3D 0;
-
- if (metaSeekElement =3D=3D NullElement)
- return;
-
- l2 =3D ElementPtr(m_InputStream.FindNextElement(metaSeekElement->Generi=
c().Context, UpperElementLevel, 0xFFFFFFFFFFFFFFFFL, true, 1));
- while (l2 !=3D NullElement) {
- if (UpperElementLevel > 0) {
- break;
- }
- if (UpperElementLevel < 0) {
- UpperElementLevel =3D 0;
- }
- if (bInfoOnly) {
- if (m_ClusterIndex.size() >=3D 1) break;
- }
-
- if (EbmlId(*l2) =3D=3D KaxSeek::ClassInfos.GlobalId) {
- //Wow we found the SeekEntries, time to speed up reading ;)
- l3 =3D ElementPtr(m_InputStream.FindNextElement(l2->Generic().Context=
, UpperElementLevel, 0xFFFFFFFFFFFFFFFFL, true, 1));
-
- EbmlIdPtr id;
- while (l3 !=3D NullElement) {
- if (UpperElementLevel > 0) {
- break;
- }
- if (UpperElementLevel < 0) {
- UpperElementLevel =3D 0;
- }
- if (bInfoOnly) {
- if (m_ClusterIndex.size() >=3D 1) break;
- }
-
- if (EbmlId(*l3) =3D=3D KaxSeekID::ClassInfos.GlobalId) {
- binary *b =3D NULL;
- uint16 s =3D 0;
- KaxSeekID &seek_id =3D static_cast<KaxSeekID &>(*l3);
- seek_id.ReadData(m_InputStream.I_O(), SCOPE_ALL_DATA);
- b =3D seek_id.GetBuffer();
- s =3D (uint16)seek_id.GetSize();
- id.reset();
- id =3D EbmlIdPtr(new EbmlId(b, s));
-
- } else if (EbmlId(*l3) =3D=3D KaxSeekPosition::ClassInfos.GlobalId) =
{
- KaxSeekPosition &seek_pos =3D static_cast<KaxSeekPosition &>(*l3);
- seek_pos.ReadData(m_InputStream.I_O()); =09
- lastSeekPos =3D uint64(seek_pos);
- if (endSeekPos < lastSeekPos)
- endSeekPos =3D uint64(seek_pos);
-
- if (*id =3D=3D KaxCluster::ClassInfos.GlobalId) {
- //NOTE1("Found Cluster Seek Entry Postion: %u", (unsigned long)las=
tSeekPos);
- //uint64 orig_pos =3D inputFile.getFilePointer();
- //MatroskaMetaSeekClusterEntry newCluster;
- cluster_entry_ptr newCluster(new MatroskaMetaSee=
kClusterEntry());
- newCluster->timecode =3D MAX_UINT64;
- newCluster->filePos =3D static_cast<KaxSegment *>(m_ElementLevel0.=
get())->GetGlobalPosition(lastSeekPos);
- m_ClusterIndex.push_back(newCluster);
-
- } else if (*id =3D=3D KaxSeekHead::ClassInfos.GlobalId) {
- NOTE1("Found MetaSeek Seek Entry Postion: %u", (unsigned long)last=
SeekPos);
- uint64 orig_pos =3D m_IOCallback.getFilePointer();
- m_IOCallback.setFilePointer(static_cast<KaxSegment *>(m_ElementLev=
el0.get())->GetGlobalPosition(lastSeekPos));
- =09
- ElementPtr levelUnknown =3D ElementPtr(m_InputStream.FindNextID(Ka=
xSeekHead::ClassInfos, 0xFFFFFFFFFFFFFFFFL)); =09
- Parse_MetaSeek(levelUnknown, bInfoOnly);
-
- m_IOCallback.setFilePointer(orig_pos);
- }
-
- } else {
-
- }
- l3->SkipData(m_InputStream, l3->Generic().Context);
- l3 =3D ElementPtr(m_InputStream.FindNextElement(l2->Generic().Contex=
t, UpperElementLevel, 0xFFFFFFFFFFFFFFFFL, true, 1));
- }
- } else {
-
- }
-
- if (UpperElementLevel > 0) { // we're coming from l3
- UpperElementLevel--;
- l2 =3D l3;
- if (UpperElementLevel > 0)
- break;
-
- } else {
- l2->SkipData(m_InputStream, l2->Generic().Context);
- l2 =3D ElementPtr(m_InputStream.FindNextElement(metaSeekElement->Gene=
ric().Context, UpperElementLevel, 0xFFFFFFFFFFFFFFFFL, true, 1));
- }
- }
- _TIMER("Parse_MetaSeek");
-}
-
-#define IS_ELEMENT_ID(__x__) (Element->Generic().GlobalId =3D=3D __x__::=
ClassInfos.GlobalId)
-
-void MatroskaAudioParser::Parse_Chapter_Atom(KaxChapterAtom *ChapterAtom=
)
-{
- Parse_Chapter_Atom(ChapterAtom, m_Chapters);
-}
-
-void MatroskaAudioParser::Parse_Chapter_Atom(KaxChapterAtom *ChapterAtom=
, std::vector<MatroskaChapterInfo> &p_chapters)
-{
- int i, j;
- EbmlElement *Element =3D NULL;
- MatroskaChapterInfo newChapter;
-
- NOTE("New chapter");
-
- for (i =3D 0; i < ChapterAtom->ListSize(); i++)
- {=09
- Element =3D (*ChapterAtom)[i];
- =09
- if (IS_ELEMENT_ID(KaxChapterUID))
- {
- newChapter.chapterUID =3D uint64(*static_cast<EbmlUInteger *>(Element=
));
- NOTE1("- UID : %I64d", newChapter.chapterUID);
- }
- else if(IS_ELEMENT_ID(KaxChapterTimeStart))
- { =09
- newChapter.timeStart =3D uint64(*static_cast<EbmlUInteger *>(Element)=
); // it's in ns
- NOTE1("- TimeStart : %I64d", newChapter.timeStart);
- }
- else if(IS_ELEMENT_ID(KaxChapterTimeEnd))
- {
- newChapter.timeEnd =3D uint64(*static_cast<EbmlUInteger *>(Element));=
// it's in ns
- NOTE1("- TimeEnd : %I64d", newChapter.timeEnd);
- }
- else if(IS_ELEMENT_ID(KaxChapterTrack))
- {
- KaxChapterTrack *ChapterTrack =3D (KaxChapterTrack *)Element;
- =09
- for (j =3D 0; j < ChapterTrack->ListSize(); j++)
- {
- Element =3D (*ChapterTrack)[j];
- if(IS_ELEMENT_ID(KaxChapterTrackNumber))
- {
- uint64 chapTrackNo =3D uint64(*static_cast<EbmlUInteger *>(Element)=
);
- newChapter.tracks.push_back(chapTrackNo);
- NOTE1("- TrackNumber : %I64d", chapTrackNo);
- }
- else if(IS_ELEMENT_ID(KaxChapterAtom))
- { =09
- // Ignore sub-chapter
- NOTE("ignore sub-chapter");
- //Parse_Chapter_Atom((KaxChapterAtom *)Element);
- }
- }
- }
- else if(IS_ELEMENT_ID(KaxChapterDisplay))
- {
- // A new chapter display string+lang+country
- MatroskaChapterDisplayInfo newChapterDisplay; =09
- KaxChapterDisplay *ChapterDisplay =3D (KaxChapterDisplay *)Element;
- =09
- for (j =3D 0; j < ChapterDisplay->ListSize(); j++) {
- Element =3D (*ChapterDisplay)[j];
- if(IS_ELEMENT_ID(KaxChapterString))
- {
- newChapterDisplay.string =3D UTFstring(*static_cast <EbmlUnicodeStr=
ing *>(Element)).c_str();
- NOTE1("- String : %s", newChapterDisplay.string.GetUTF8().c_str());
- }
- else if(IS_ELEMENT_ID(KaxChapterAtom))
- { =09
- // Ignore sub-chapter
- NOTE("ignore sub-chapter");
- //Parse_Chapter_Atom((KaxChapterAtom *)Element);
- }
- }
- // A emtpy string in a chapter display string is usless
- if (newChapterDisplay.string.length() > 0)
- newChapter.display.push_back(newChapterDisplay);
- }
- else if(IS_ELEMENT_ID(KaxChapterAtom))
- {
- /*
- // Ignore sub-chapter
- NOTE("ignore sub-chapter");
- //Parse_Chapter_Atom((KaxChapterAtom *)Element);
- */
- Parse_Chapter_Atom((KaxChapterAtom *)Element, newChapter.subChapters)=
;
- }
- }
- if ((newChapter.chapterUID !=3D 0) && !FindChapterUID(newChapter.chapte=
rUID))
- p_chapters.push_back(newChapter);
-}
-
-void MatroskaAudioParser::Parse_Chapters(KaxChapters *chaptersElement)
-{
- int i, j;=09
- EbmlElement *Element =3D NULL;=09
- int UpperEltFound =3D 0;
-
- NOTE("New edition");
-
- if (chaptersElement =3D=3D NULL)
- return;
-
- chaptersElement->Read(m_InputStream, KaxChapters::ClassInfos.Context,
- UpperEltFound, Element, true);
-
- for (i =3D 0; i < chaptersElement->ListSize(); i++)
- {
- Element =3D (*chaptersElement)[i];
- if(IS_ELEMENT_ID(KaxEditionEntry))
- {
- MatroskaEditionInfo newEdition;
- KaxEditionEntry *edition =3D (KaxEditionEntry *)Element;
- for (j =3D 0; j < edition->ListSize(); j++)
- {
- Element =3D (*edition)[j];
- if(IS_ELEMENT_ID(KaxEditionUID))
- {
- // A new edition :)
- newEdition.editionUID =3D uint64(*static_cast<EbmlUInteger *>(Eleme=
nt));
- NOTE1("- UID : %I64d", newEdition.editionUID);
- }
- else if(IS_ELEMENT_ID(KaxChapterAtom))
- {
- // A new chapter :)
- Parse_Chapter_Atom((KaxChapterAtom *)Element);
- }
- }
- if ((newEdition.editionUID !=3D 0) && !FindEditionUID(newEdition.edit=
ionUID))
- m_Editions.push_back(newEdition);
- }
- }
- FixChapterEndTimes();
-}
-
-void MatroskaAudioParser::Parse_Tags(KaxTags *tagsElement)
-{
- int i, j, k;
- EbmlElement *Element =3D NULL;
- int UpperEltFound =3D 0;
-
- if (tagsElement =3D=3D NULL)
- return;
-
- m_TagPos =3D tagsElement->GetElementPosition();
- m_TagSize =3D tagsElement->GetSize();
-
- tagsElement->Read(m_InputStream, KaxTags::ClassInfos.Context, UpperEltF=
ound, Element, true);
-
- for (i =3D 0; i < tagsElement->ListSize(); i++)
- {
- Element =3D (*tagsElement)[i];
- if(IS_ELEMENT_ID(KaxTag))
- {
- MatroskaTagInfo newTag;
- newTag.targetTypeValue =3D 50;
- KaxTag *tagElement =3D (KaxTag*)Element;
- NOTE("New Tag");
- for (j =3D 0; j < tagElement->ListSize(); j++)
- {
- Element =3D (*tagElement)[j];
- if(IS_ELEMENT_ID(KaxTagTargets))
- {
- KaxTagTargets *tagTargetsElement =3D (KaxTagTargets*)Element; =09
- for (k =3D 0; k < tagTargetsElement->ListSize(); k++)
- {
- Element =3D (*tagTargetsElement)[k];
- if(IS_ELEMENT_ID(KaxTagTrackUID))
- {
- newTag.targetTrackUID =3D uint64(*static_cast<EbmlUInteger *>(Ele=
ment));
- NOTE1("- TargetTrackUID : %I64d", newTag.targetTrackUID);
- }
- else if(IS_ELEMENT_ID(KaxTagEditionUID))
- {
- newTag.targetEditionUID =3D uint64(*static_cast<EbmlUInteger *>(E=
lement));
- NOTE1("- TargetEditionUID : %I64d", newTag.targetEditionUID);
- }
- else if(IS_ELEMENT_ID(KaxTagChapterUID))
- {
- newTag.targetChapterUID =3D uint64(*static_cast<EbmlUInteger *>(E=
lement));
- NOTE1("- TargetChapterUIDUID : %I64d", newTag.targetChapterUID);
- }
- else if(IS_ELEMENT_ID(KaxTagAttachmentUID))
- {
- newTag.targetAttachmentUID =3D uint64(*static_cast<EbmlUInteger *=
>(Element));
- NOTE1("- TargetAttachmentUID : %I64d", newTag.targetAttachmentUID=
);
- }
- else if(IS_ELEMENT_ID(KaxTagTargetTypeValue))
- {
- newTag.targetTypeValue =3D uint32(*static_cast<EbmlUInteger *>(El=
ement));
- NOTE1("- TargetTypeValue : %d", newTag.targetTypeValue);
- }
- else if(IS_ELEMENT_ID(KaxTagTargetType))
- {
- newTag.targetType =3D std::string(*static_cast<KaxTagTargetType *=
>(Element));
- NOTE1("- TargetType : %s", newTag.targetType.c_str());
- }
- }
- }
- else if(IS_ELEMENT_ID(KaxTagSimple))
- {
- MatroskaSimpleTag newSimpleTag;
- KaxTagSimple *tagSimpleElement =3D (KaxTagSimple*)Element;
- NOTE("New SimpleTag");
- for (k =3D 0; k < tagSimpleElement->ListSize(); k++)
- {
- Element =3D (*tagSimpleElement)[k];
- if(IS_ELEMENT_ID(KaxTagName))
- {
- newSimpleTag.name =3D wcsupr((wchar_t *)UTFstring(*static_cast <E=
bmlUnicodeString *>(Element)).c_str());
- NOTE1("- Name : %s", newSimpleTag.name.GetUTF8().c_str());
- }
- else if(IS_ELEMENT_ID(KaxTagString))
- {
- newSimpleTag.value =3D UTFstring(*static_cast <EbmlUnicodeString =
*>(Element)).c_str();
- NOTE1("- Value : %s", newSimpleTag.value.GetUTF8().c_str());
- }
- else if(IS_ELEMENT_ID(KaxTagDefault))
- {
- newSimpleTag.defaultFlag =3D uint32(*static_cast<EbmlUInteger *>(=
Element));
- NOTE1("- TargetTypeValue : %d", newSimpleTag.default);
- }
- else if(IS_ELEMENT_ID(KaxTagLangue))
- {
- newSimpleTag.language =3D std::string(*static_cast <KaxTagLangue =
*>(Element));
- NOTE1("- Language : %s", newSimpleTag.language.c_str());
- }
- else if(IS_ELEMENT_ID(KaxTagSimple))
- {
- // ignore sub-tags
- // if we want "sub-tags" put this loop in another
- // function and call it recursively
- }
- }
- newTag.tags.push_back(newSimpleTag);
- }
- }
- m_Tags.push_back(newTag);
- }
- }
-};
-
-int MatroskaAudioParser::FillQueue()=20
-{
- flush_queue();
-
- NOTE("MatroskaAudioParser::FillQueue()");
-
- int UpperElementLevel =3D 0;
- bool bAllowDummy =3D false;
- // Elements for different levels
- ElementPtr ElementLevel1;
- ElementPtr ElementLevel2;
- ElementPtr ElementLevel3;
- ElementPtr ElementLevel4;
- ElementPtr ElementLevel5;
- ElementPtr NullElement;
- //m_framebuffer.set_size(0);
-
- if (m_IOCallback.seekable()) {
- cluster_entry_ptr currentCluster =3D FindCluster(m_CurrentTimecode);
- if (currentCluster.get() =3D=3D NULL)
- return 2;
- int64 clusterFilePos =3D currentCluster->filePos;
-
- //console::info(uStringPrintf("cluster %d", currentCluster->clusterNo)=
);
-
- m_IOCallback.setFilePointer(clusterFilePos);
- // Find the element data
- ElementLevel1 =3D ElementPtr(m_InputStream.FindNextID(KaxCluster::Clas=
sInfos, 0xFFFFFFFFFFFFFFFFL));
- if (ElementLevel1 =3D=3D NullElement)
- return 1;
-
- if (EbmlId(*ElementLevel1) =3D=3D KaxCluster::ClassInfos.GlobalId) {
- KaxCluster *SegmentCluster =3D static_cast<KaxCluster *>(ElementLevel=
1.get());
- uint32 ClusterTimecode =3D 0;
- MatroskaAudioFrame *prevFrame =3D NULL;
-
- // read blocks and discard the ones we don't care about
- ElementLevel2 =3D ElementPtr(m_InputStream.FindNextElement(ElementLev=
el1->Generic().Context, UpperElementLevel, ElementLevel1->ElementSize(), =
bAllowDummy));
- while (ElementLevel2 !=3D NullElement) {
- if (UpperElementLevel > 0) {
- break;
- }
- if (UpperElementLevel < 0) {
- UpperElementLevel =3D 0;
- }
- if (EbmlId(*ElementLevel2) =3D=3D KaxClusterTimecode::ClassInfos.Glo=
balId) { =09
- KaxClusterTimecode & ClusterTime =3D *static_cast<KaxClusterTimecod=
e*>(ElementLevel2.get());
- ClusterTime.ReadData(m_InputStream.I_O());
- ClusterTimecode =3D uint32(ClusterTime);
- currentCluster->timecode =3D ClusterTimecode * m_TimecodeScale;
- SegmentCluster->InitTimecode(ClusterTimecode, m_TimecodeScale);
- } else if (EbmlId(*ElementLevel2) =3D=3D KaxBlockGroup::ClassInfos.=
GlobalId) {
- //KaxBlockGroup & aBlockGroup =3D *static_cast<KaxBlockGroup*>(Elem=
entLevel2);
-
- // Create a new frame
- MatroskaAudioFrame *newFrame =3D new MatroskaAudioFrame;
-
- ElementLevel3 =3D ElementPtr(m_InputStream.FindNextElement(ElementL=
evel2->Generic().Context, UpperElementLevel, ElementLevel2->ElementSize()=
, bAllowDummy));
- while (ElementLevel3 !=3D NullElement) {
- if (UpperElementLevel > 0) {
- break;
- }
- if (UpperElementLevel < 0) {
- UpperElementLevel =3D 0;
- }
- if (EbmlId(*ElementLevel3) =3D=3D KaxBlock::ClassInfos.GlobalId) {=
=09
- KaxBlock & DataBlock =3D *static_cast<KaxBlock*>(ElementLevel3.ge=
t()); =09
- DataBlock.ReadData(m_InputStream.I_O());
- DataBlock.SetParent(*SegmentCluster);
-
- //NOTE4("Track # %u / %u frame%s / Timecode %I64d", DataBlock.Tra=
ckNum(), DataBlock.NumberFrames(), (DataBlock.NumberFrames() > 1)?"s":"",=
DataBlock.GlobalTimecode()/m_TimecodeScale);
- if (DataBlock.TrackNum() =3D=3D m_Tracks.at(m_CurrentTrackNo).tra=
ckNumber) { =09
- newFrame->timecode =3D DataBlock.GlobalTimecode();
-
- if (DataBlock.NumberFrames() > 1) {=09
- // The evil lacing has been used
- newFrame->duration =3D m_Tracks.at(m_CurrentTrackNo).defaultDur=
ation * DataBlock.NumberFrames();
-
- newFrame->dataBuffer.resize(DataBlock.NumberFrames());
- for (uint32 f =3D 0; f < DataBlock.NumberFrames(); f++) {
- DataBuffer &buffer =3D DataBlock.GetBuffer(f);
- newFrame->dataBuffer[f].resize(buffer.Size()); =09
- memcpy(&newFrame->dataBuffer[f][0], buffer.Buffer(), buffer.Si=
ze());
- }
- } else {
- // Non-lacing block =09
- newFrame->duration =3D m_Tracks.at(m_CurrentTrackNo).defaultDur=
ation;
-
- newFrame->dataBuffer.resize(1);
- DataBuffer &buffer =3D DataBlock.GetBuffer(0);
- newFrame->dataBuffer.at(0).resize(buffer.Size());
- =20
- memcpy(&newFrame->dataBuffer.at(0).at(0), buffer.Buffer(), buff=
er.Size());
- }
- } else {
- //newFrame->timecode =3D MAX_UINT64;
- }
- /*
- } else if (EbmlId(*ElementLevel3) =3D=3D KaxReferenceBlock::ClassI=
nfos.GlobalId) {
- KaxReferenceBlock & RefTime =3D *static_cast<KaxReferenceBlock*>(=
ElementLevel3);
- RefTime.ReadData(m_InputStream.I_O());
- newFrame->frameReferences.push_back(int32(RefTime));
- //wxLogDebug(" Reference frame at scaled (%d) timecode %ld\n", i=
nt32(RefTime), int32(int64(RefTime) * TimecodeScale));
- */
- } else if (EbmlId(*ElementLevel3) =3D=3D KaxBlockDuration::ClassIn=
fos.GlobalId) {
- KaxBlockDuration & BlockDuration =3D *static_cast<KaxBlockDuratio=
n*>(ElementLevel3.get());
- BlockDuration.ReadData(m_InputStream.I_O());
- newFrame->duration =3D uint64(BlockDuration);
- } else if (EbmlId(*ElementLevel3) =3D=3D KaxBloc=
kAdditions::ClassInfos.GlobalId) {
- ElementLevel4 =3D ElementPtr(m_InputStream.F=
indNextElement(ElementLevel3->Generic().Context, UpperElementLevel, 0xFFF=
FFFFFL, bAllowDummy));
- while (ElementLevel4 !=3D NullElement) {
- if (UpperElementLevel > 0) {
- break;
- }
- if (UpperElementLevel < 0) {
- UpperElementLevel =3D 0;
- }
- if (EbmlId(*ElementLevel4) =3D=3D KaxBlo=
ckMore::ClassInfos.GlobalId) {
- ElementLevel5 =3D ElementPtr(m_Input=
Stream.FindNextElement(ElementLevel4->Generic().Context, UpperElementLeve=
l, 0xFFFFFFFFL, bAllowDummy));
- while (ElementLevel5 !=3D NullElemen=
t) {
- if (UpperElementLevel > 0) {
- break;
- }
- if (UpperElementLevel < 0) {
- UpperElementLevel =3D 0;
- }
- if (EbmlId(*ElementLevel5) =3D=3D=
KaxBlockAddID::ClassInfos.GlobalId) {
- KaxBlockAddID & AddId =3D *s=
tatic_cast<KaxBlockAddID*>(ElementLevel5.get());
- AddId.ReadData(m_InputStream=
.I_O());
- newFrame->add_id =3D uint64(=
AddId);
- } else if (EbmlId(*ElementLevel5=
) =3D=3D KaxBlockAdditional::ClassInfos.GlobalId) {
- KaxBlockAdditional & DataBlo=
ckAdditional =3D *static_cast<KaxBlockAdditional*>(ElementLevel5.get()); =
=09
- DataBlockAdditional.ReadData(m_InputStream.I_O())=
; =09
- newFrame->additional_data_bu=
ffer.resize(DataBlockAdditional.GetSize());
- if (!newFrame->add_id) {
- newFrame->add_id =3D 1;
- }
- memcpy(&newFrame->additional=
_data_buffer.at(0), DataBlockAdditional.GetBuffer(), DataBlockAdditional.=
GetSize());
- }
- ElementLevel5->SkipData(m_InputS=
tream, ElementLevel5->Generic().Context);
- ElementLevel5 =3D ElementPtr(m_InputStream.FindNextEl=
ement(ElementLevel4->Generic().Context, UpperElementLevel, ElementLevel4-=
>ElementSize(), bAllowDummy));
- }
- }
- if (UpperElementLevel > 0) {
- UpperElementLevel--;
- ElementLevel4 =3D ElementLevel5;
- if (UpperElementLevel > 0)
- break;
- } else {
- ElementLevel4->SkipData(m_InputStream, ElementLevel4->Gen=
eric().Context);
- ElementLevel4 =3D ElementPtr(m_InputStream.FindNextElemen=
t(ElementLevel3->Generic().Context, UpperElementLevel, ElementLevel3->Ele=
mentSize(), bAllowDummy));
- }
- }
- }
- if (UpperElementLevel > 0) {
- UpperElementLevel--;
- ElementLevel3 =3D ElementLevel4;
- if (UpperElementLevel > 0)
- break;
- } else {
- ElementLevel3->SkipData(m_InputStream, ElementLevel3->Generic().C=
ontext);
-
- ElementLevel3 =3D ElementPtr(m_InputStream.FindNextElement(Elemen=
tLevel2->Generic().Context, UpperElementLevel, ElementLevel2->ElementSize=
(), bAllowDummy));
- } =09
- //newFrame =3D new MatroskaReadFrame();
- }
- if (newFrame->dataBuffer.size()>0) {
- m_Queue.push(newFrame);
- if (prevFrame !=3D NULL && prevFrame->duration =3D=3D 0) {
- prevFrame->duration =3D newFrame->timecode - prevFrame->timecode;
- //if (newFrame->duration =3D=3D 0)
- // newFrame->duration =3D prevFrame->duration;
- }
-
- // !!!!!!!!!!!!!!! HACK ALERT !!!!!!!!!!!!!!!!!!!!!!!!
- // This is an ugly hack to keep us from re-seeking to the same clu=
ster
- m_CurrentTimecode =3D newFrame->timecode + (newFrame->duration * 2=
);
- if (newFrame->duration =3D=3D 0) {
- m_CurrentTimecode +=3D (int64)m_Tracks.at(m_CurrentTrackNo).defau=
ltDuration * 2;
- }
- // !!!!!!!!!!!!!!! HACK ALERT !!!!!!!!!!!!!!!!!!!!!!!!
-
- prevFrame =3D newFrame;
- } else {
- hprintf(L"newFrame =3D=3D!! delete!!\n");
- _DELETE(newFrame);
- }
- }
-
- if (UpperElementLevel > 0) {
- UpperElementLevel--;
- //delete ElementLevel2;
- //_DELETE(ElementLevel2);
- ElementLevel2 =3D ElementLevel3;
- if (UpperElementLevel > 0)
- break;
- } else {
- ElementLevel2->SkipData(m_InputStream, ElementLevel2->Generic().Con=
text);
- //if (ElementLevel2 !=3D pChecksum)
- // delete ElementLevel2; =09
- //ElementLevel2 =3D NULL;
- //_DELETE(ElementLevel2);
-
- ElementLevel2 =3D ElementPtr(m_InputStream.FindNextElement(ElementL=
evel1->Generic().Context, UpperElementLevel, ElementLevel1->ElementSize()=
, bAllowDummy));
- }
- }
- }
- //_DELETE(ElementLevel3);
- //_DELETE(ElementLevel2);
- //_DELETE(ElementLevel1);
- //delete ElementLevel1;
- =09
- if (currentCluster->clusterNo < m_ClusterIndex.size()-1) {
- if (m_ClusterIndex.at(currentCluster->clusterNo+1)->timecode =3D=3D M=
AX_UINT64)
- m_ClusterIndex.at(currentCluster->clusterNo+1)->timecode =3D GetClus=
terTimecode(m_ClusterIndex.at(currentCluster->clusterNo+1)->filePos);
- m_CurrentTimecode =3D m_ClusterIndex.at(currentCluster->clusterNo+1)-=
>timecode;
- if(m_CurrentTimecode =3D=3D 0)
- {
- console::error(uStringPrintf("clusterNo : %d, m_ClusterIndex.size() =
: %d", currentCluster->clusterNo, m_ClusterIndex.size()));
- console::info("m_CurrentTimecode =3D=3D 0 (a)");
- }
- } else {
- m_CurrentTimecode =3D MAX_UINT64;
- }
- =09
- } else {
- // Find the element data
- ElementLevel1 =3D ElementPtr(m_InputStream.FindNextID(KaxCluster::Clas=
sInfos, 0xFFFFFFFFFFFFFFFFL));
- if (ElementLevel1 =3D=3D NullElement)
- return 1;
-
- if (EbmlId(*ElementLevel1) =3D=3D KaxCluster::ClassInfos.GlobalId) {
- KaxCluster *SegmentCluster =3D static_cast<KaxCluster *>(ElementLevel=
1.get());
- uint32 ClusterTimecode =3D 0;
-
- // read blocks and discard the ones we don't care about
- ElementLevel2 =3D ElementPtr(m_InputStream.FindNextElement(ElementLev=
el1->Generic().Context, UpperElementLevel, ElementLevel1->ElementSize(), =
bAllowDummy));
- while (ElementLevel2 !=3D NullElement) {
- if (UpperElementLevel > 0) {
- break;
- }
- if (UpperElementLevel < 0) {
- UpperElementLevel =3D 0;
- }
- if (EbmlId(*ElementLevel2) =3D=3D KaxClusterTimecode::ClassInfos.Glo=
balId) { =09
- KaxClusterTimecode & ClusterTime =3D *static_cast<KaxClusterTimecod=
e*>(ElementLevel2.get());
- ClusterTime.ReadData(m_InputStream.I_O());
- ClusterTimecode =3D uint32(ClusterTime);
- SegmentCluster->InitTimecode(ClusterTimecode, m_TimecodeScale);
- } else if (EbmlId(*ElementLevel2) =3D=3D KaxBlockGroup::ClassInfos.=
GlobalId) {
- //KaxBlockGroup & aBlockGroup =3D *static_cast<KaxBlockGroup*>(Elem=
entLevel2);
-
- // Create a new frame
- MatroskaAudioFrame *newFrame =3D new MatroskaAudioFrame; =09
-
- ElementLevel3 =3D ElementPtr(m_InputStream.FindNextElement(ElementL=
evel2->Generic().Context, UpperElementLevel, ElementLevel2->ElementSize()=
, bAllowDummy));
- while (ElementLevel3 !=3D NullElement) {
- if (UpperElementLevel > 0) {
- break;
- }
- if (UpperElementLevel < 0) {
- UpperElementLevel =3D 0;
- }
- if (EbmlId(*ElementLevel3) =3D=3D KaxBlock::ClassInfos.GlobalId) {=
=09
- KaxBlock & DataBlock =3D *static_cast<KaxBlock*>(ElementLevel3.ge=
t()); =09
- DataBlock.ReadData(m_InputStream.I_O()); =09
- DataBlock.SetParent(*SegmentCluster);
-
- //NOTE4("Track # %u / %u frame%s / Timecode %I64d", DataBlock.Tra=
ckNum(), DataBlock.NumberFrames(), (DataBlock.NumberFrames() > 1)?"s":"",=
DataBlock.GlobalTimecode()/m_TimecodeScale);
- if (DataBlock.TrackNum() =3D=3D m_Tracks.at(m_CurrentTrackNo).tra=
ckNumber) { =09
- newFrame->timecode =3D DataBlock.GlobalTimecode(); =09
-
- if (DataBlock.NumberFrames() > 1) {=09
- // The evil lacing has been used
- newFrame->duration =3D m_Tracks.at(m_CurrentTrackNo).defaultDur=
ation * DataBlock.NumberFrames();
-
- newFrame->dataBuffer.resize(DataBlock.NumberFrames());
- for (uint32 f =3D 0; f < DataBlock.NumberFrames(); f++) {
- DataBuffer &buffer =3D DataBlock.GetBuffer(f);
- newFrame->dataBuffer[f].resize(buffer.Size()); =09
- memcpy(&newFrame->dataBuffer[f][0], buffer.Buffer(), buffer.Si=
ze());
- }
- } else {
- // Non-lacing block =09
- newFrame->duration =3D m_Tracks.at(m_CurrentTrackNo).defaultDur=
ation;
- =09
- newFrame->dataBuffer.resize(1);
- DataBuffer &buffer =3D DataBlock.GetBuffer(0);
- newFrame->dataBuffer.at(0).resize(buffer.Size()); =09
- memcpy(&newFrame->dataBuffer[0][0], buffer.Buffer(), buffer.Siz=
e());
- }
- } else {
- //newFrame->timecode =3D MAX_UINT64;
- }
- /*
- } else if (EbmlId(*ElementLevel3) =3D=3D KaxReferenceBlock::ClassI=
nfos.GlobalId) {
- KaxReferenceBlock & RefTime =3D *static_cast<KaxReferenceBlock*>(=
ElementLevel3);
- RefTime.ReadData(m_InputStream.I_O());
- newFrame->frameReferences.push_back(int32(RefTime));
- //wxLogDebug(" Reference frame at scaled (%d) timecode %ld\n", i=
nt32(RefTime), int32(int64(RefTime) * TimecodeScale));
- */
- } else if (EbmlId(*ElementLevel3) =3D=3D KaxBlockDuration::ClassIn=
fos.GlobalId) {
- KaxBlockDuration & BlockDuration =3D *static_cast<KaxBlockDuratio=
n*>(ElementLevel3.get());
- BlockDuration.ReadData(m_InputStream.I_O());
- newFrame->duration =3D uint64(BlockDuration);
- }
- if (UpperElementLevel > 0) {
- UpperElementLevel--;
- //delete ElementLevel3;
- //_DELETE(ElementLevel3);
- ElementLevel3 =3D ElementLevel4;
- if (UpperElementLevel > 0)
- break;
- } else {
- ElementLevel3->SkipData(m_InputStream, ElementLevel3->Generic().C=
ontext);
- //delete ElementLevel3;
- //ElementLevel3 =3D NULL;
- //_DELETE(ElementLevel3);
-
- ElementLevel3 =3D ElementPtr(m_InputStream.FindNextElement(Elemen=
tLevel2->Generic().Context, UpperElementLevel, ElementLevel2->ElementSize=
(), bAllowDummy));
- } =09
- //newFrame =3D new MatroskaReadFrame();
- }
- if (newFrame->dataBuffer.size()>0)
- m_Queue.push(newFrame);
- }
-
- if (UpperElementLevel > 0) {
- UpperElementLevel--;
- //delete ElementLevel2;
- //_DELETE(ElementLevel2);
- ElementLevel2 =3D ElementLevel3;
- if (UpperElementLevel > 0)
- break;
- } else {
- ElementLevel2->SkipData(m_InputStream, ElementLevel2->Generic().Con=
text);
- //if (ElementLevel2 !=3D pChecksum)
- // delete ElementLevel2; =09
- //ElementLevel2 =3D NULL;
- //_DELETE(ElementLevel2);
-
- ElementLevel2 =3D ElementPtr(m_InputStream.FindNextElement(ElementL=
evel1->Generic().Context, UpperElementLevel, ElementLevel1->ElementSize()=
, bAllowDummy));
- }
- }
- }
- ElementLevel1->SkipData(m_InputStream, ElementLevel1->Generic().Contex=
t);
- //_DELETE(ElementLevel3);
- //_DELETE(ElementLevel2);
- //_DELETE(ElementLevel1);
- //delete ElementLevel1;
- }
- //NOTE1("MatroskaAudioParser::FillQueue() - Queue now has %u frames", m=
_Queue.size());
- return 0;
-};
-
-uint64 MatroskaAudioParser::GetClusterTimecode(uint64 filePos) {=09
- try {
- uint64 ret =3D MAX_UINT64;
-
- int UpperElementLevel =3D 0;
- // Elements for different levels
- ElementPtr ElementLevel1;
- ElementPtr ElementLevel2; =09
- ElementPtr ElementLevel3;
- ElementPtr NullElement;
-
- m_IOCallback.setFilePointer(filePos);
- // Find the element data
- ElementLevel1 =3D ElementPtr(m_InputStream.FindNextID(KaxCluster::Clas=
sInfos, 0xFFFFFFFFFFFFFFFFL));
- if (ElementLevel1 =3D=3D NullElement)
- return MAX_UINT64;
-
- if (EbmlId(*ElementLevel1) =3D=3D KaxCluster::ClassInfos.GlobalId) {
- //KaxCluster *SegmentCluster =3D static_cast<KaxCluster *>(ElementLev=
el1);
- //uint32 ClusterTimecode =3D 0;
-
- // read blocks and discard the ones we don't care about
- ElementLevel2 =3D ElementPtr(m_InputStream.FindNextElement(ElementLev=
el1->Generic().Context, UpperElementLevel, ElementLevel1->ElementSize(), =
false));
- while (ElementLevel2 !=3D NullElement) {
- if (UpperElementLevel > 0) {
- break;
- }
- if (UpperElementLevel < 0) {
- UpperElementLevel =3D 0;
- }
- if (EbmlId(*ElementLevel2) =3D=3D KaxClusterTimecode::ClassInfos.Glo=
balId) { =09
- KaxClusterTimecode & ClusterTime =3D *static_cast<KaxClusterTimecod=
e*>(ElementLevel2.get());
- ClusterTime.ReadData(m_InputStream.I_O());
- ret =3D uint64(ClusterTime) * m_TimecodeScale;
- =09
- }
-
- if (UpperElementLevel > 0) {
- UpperElementLevel--;
- //delete ElementLevel2;
- //_DELETE(ElementLevel2);
- ElementLevel2 =3D ElementLevel3;
- if (UpperElementLevel > 0)
- break;
- } else {
- ElementLevel2->SkipData(m_InputStream, ElementLevel2->Generic().Con=
text);
- //if (ElementLevel2 !=3D pChecksum)
- //delete ElementLevel2; =09
- //ElementLevel2 =3D NULL;
- //_DELETE(ElementLevel2);
- ElementLevel2 =3D NullElement;
- if (ret =3D=3D -1)
- ElementLevel2 =3D ElementPtr(m_InputStream.FindNextElement(Element=
Level1->Generic().Context, UpperElementLevel, ElementLevel1->ElementSize(=
), false));
- }
- }
- }
- //_DELETE(ElementLevel3);
- //_DELETE(ElementLevel2);
- //_DELETE(ElementLevel1);
- //delete ElementLevel1;
-
- return ret;
- } catch (...) {
- return MAX_UINT64;
- }=09
-};
-
-cluster_entry_ptr MatroskaAudioParser::FindCluster(uint64 timecode)
-{
- try {
- #ifdef _DEBUG_NO_SEEKING
- static size_t callCount =3D 0;
- if (callCount < m_ClusterIndex.size())
- return &m_ClusterIndex[callCount++];
- else return NULL;
- #endif
-
- if (timecode =3D=3D 0)
- // Special case
- return m_ClusterIndex.at(0);
- =09
- cluster_entry_ptr correctEntry;
- double clusterDuration =3D (double)(int64)m_ClusterIndex.size() / m_Du=
ration;
- size_t clusterIndex =3D clusterDuration * (double)(int64)timecode;
- //int lookCount =3D 0;
- if (clusterIndex > m_ClusterIndex.size())
- clusterIndex =3D m_ClusterIndex.size()-1;
-
- cluster_entry_ptr clusterEntry;
- cluster_entry_ptr prevClusterEntry;
- cluster_entry_ptr nextClusterEntry;
- while (correctEntry =3D=3D NULL) {
- clusterEntry =3D m_ClusterIndex.at(clusterIndex); =09
- if (clusterIndex > 0)
- prevClusterEntry =3D m_ClusterIndex.at(clusterIndex-1);
- if (clusterIndex+1 < m_ClusterIndex.size())
- nextClusterEntry =3D m_ClusterIndex.at(clusterIndex+1); =09
- =09
- // We need timecodes to do good seeking
- if (clusterEntry->timecode =3D=3D MAX_UINT64) { =09
- clusterEntry->timecode =3D GetClusterTimecode(clusterEntry->filePos)=
; =09
- }
- if (prevClusterEntry !=3D NULL && prevClusterEntry->timecode =3D=3D M=
AX_UINT64) {
- prevClusterEntry->timecode =3D GetClusterTimecode(prevClusterEntry->=
filePos); =09
- }
- if (nextClusterEntry !=3D NULL && nextClusterEntry->timecode =3D=3D M=
AX_UINT64) { =09
- nextClusterEntry->timecode =3D GetClusterTimecode(nextClusterEntry->=
filePos); =09
- }
-
- if (clusterEntry->timecode =3D=3D timecode) {
- // WOW, we are seeking directly to this cluster
- correctEntry =3D clusterEntry;
- break;
- }
-
- if (prevClusterEntry !=3D NULL) {
- if (clusterEntry->timecode > timecode && timecode > prevClusterEntry=
->timecode) {
- // We found it !!!
- correctEntry =3D prevClusterEntry;
- break;
- }
- if (prevClusterEntry->timecode =3D=3D timecode) {
- // WOW, we are seeking directly to this cluster
- correctEntry =3D prevClusterEntry;
- break;
- }
- // Check if we overshot the needed cluster
- if (timecode < prevClusterEntry->timecode) {
- clusterIndex--;
- //lookCount++; // This is how many times we have 'looked'
- continue;
- }
- }
- =09
- if (nextClusterEntry !=3D NULL) {
- if (clusterEntry->timecode < timecode && timecode < nextClusterEntry=
->timecode) {
- // We found it !!!
- correctEntry =3D clusterEntry;
- break;
- } =09
- if (nextClusterEntry->timecode =3D=3D timecode) {
- // WOW, we are seeking directly to this cluster
- correctEntry =3D nextClusterEntry;
- break;
- }
- // Check if we undershot the needed cluster
- if (timecode > nextClusterEntry->timecode) {
- clusterIndex++;
- //lookCount--;
- continue;
- }
- }
- // We should never get here, unless this is the last cluster
- assert(clusterEntry !=3D NULL);=09
- if (timecode <=3D m_Duration)
- correctEntry =3D clusterEntry;
- else
- break;
- }
-
- if (correctEntry !=3D NULL)
- NOTE3("MatroskaAudioParser::FindCluster(timecode =3D %u) seeking to c=
luster %i at %u", (uint32)(timecode / m_TimecodeScale), (uint32)correctEn=
try->clusterNo, (uint32)correctEntry->filePos);
- else
- NOTE1("MatroskaAudioParser::FindCluster(timecode =3D %u) seeking fail=
ed", (uint32)(timecode / m_TimecodeScale));
-
- return correctEntry;
- } catch (...) {
- cluster_entry_ptr null_ptr;
- return null_ptr;
- }
-}
-
-void MatroskaAudioParser::CountClusters()=20
-{
- for (uint32 c =3D 0; c < m_ClusterIndex.size(); c++) {
- cluster_entry_ptr clusterEntry =3D m_ClusterIndex.at(c); =09
- clusterEntry->clusterNo =3D c;
- }
-}
-
-void MatroskaAudioParser::FixChapterEndTimes()
-{
- if (m_Chapters.size() > 0) {
- MatroskaChapterInfo *nextChapter =3D &m_Chapters.at(m_Chapters.size()-=
1);
- if (nextChapter->timeEnd =3D=3D 0) {
- nextChapter->timeEnd =3D static_cast<uint64>(m_Duration);
- }
- for (uint32 c =3D 0; c < m_Chapters.size()-1; c++) {
- MatroskaChapterInfo ¤tChapter =3D m_Chapters.at(c);=09
- nextChapter =3D &m_Chapters.at(c+1);
- if (currentChapter.timeEnd =3D=3D 0) {
- currentChapter.timeEnd =3D nextChapter->timeStart;
- }
- }
- nextChapter =3D &m_Chapters.at(m_Chapters.size()-1);
- if ((nextChapter->timeEnd =3D=3D 0) || (nextChapter->timeEnd =3D=3D ne=
xtChapter->timeStart)) {
- nextChapter->timeEnd =3D static_cast<uint64>(m_Duration);
- }
- }=09
-}
-
-bool MatroskaAudioParser::FindEditionUID(uint64 uid)
-{
- for (uint32 c =3D 0; c < m_Editions.size(); c++) {
- MatroskaEditionInfo ¤tEdition =3D m_Editions.at(c);=09
- if (currentEdition.editionUID =3D=3D uid)
- return true;
- }=09
- return false;
-}
-
-bool MatroskaAudioParser::FindChapterUID(uint64 uid)
-{
- for (uint32 c =3D 0; c < m_Chapters.size(); c++) {
- MatroskaChapterInfo ¤tChapter =3D m_Chapters.at(c);=09
- if (currentChapter.chapterUID =3D=3D uid)
- return true;
- }=09
- return false;
-}
-
-void PrintChapters(std::vector<MatroskaChapterInfo> &theChapters)=20
-{
- for (uint32 c =3D 0; c < theChapters.size(); c++) {
- MatroskaChapterInfo ¤tChapter =3D theChapters.at(c);=09
- NOTE2("Chapter %u, UID: %u", c, (uint32)currentChapter.chapterUID);
- NOTE1("\tStart Time: %u", (uint32)currentChapter.timeStart);
- NOTE1("\tEnd Time: %u", (uint32)currentChapter.timeEnd);
- for (uint32 d =3D 0; d < currentChapter.display.size(); d++) {
- NOTE3("\tDisplay %u, String: %s Lang: %s", d, currentChapter.display.=
at(d).string.GetUTF8().c_str(), currentChapter.display.at(d).lang.c_str()=
);
- }
- for (uint32 t =3D 0; t < currentChapter.tracks.size(); t++) {
- NOTE2("\tTrack %u, UID: %%u", t, (uint32)currentChapter.tracks.at(t))=
;
- }
-
- }
-};
-
-bool MatroskaSearch::Skip()
-{
- int j;
-
- for (j =3D 0; j < SEARCH_TABLE_SIZE; j++) skip[j] =3D SEARCH_PATTERN_SI=
ZE;
- for (j =3D 0; j < SEARCH_PATTERN_SIZE - 1; j++)
- skip[pattern[j] & 0x00ff] =3D SEARCH_PATTERN_SIZE-1-j;
- return true;
-}
-
-bool MatroskaSearch::Next()
-{
- int j, k, s;
- int *g;
-
- if ((g =3D (int *)malloc(sizeof(int)*SEARCH_PATTERN_SIZE)) =3D=3D NULL)=
return false;
- for (j =3D 0; j < SEARCH_PATTERN_SIZE; j++) next[j] =3D 2*SEARCH_PATTER=
N_SIZE - 1 - j;
- j =3D SEARCH_PATTERN_SIZE;
- for (k =3D SEARCH_PATTERN_SIZE - 1; k >=3D 0; k--) {
- g[k] =3D j;
- while (j !=3D SEARCH_PATTERN_SIZE && pattern[j] !=3D pattern[k]) {
- next[j] =3D (next[j] <=3D SEARCH_PATTERN_SIZE-1-k) ? next[j] : SEARCH=
_PATTERN_SIZE-1-k;
- j =3D g[j];
- }
- j--;
- }
- s =3D j;
- for (j =3D 0; j < SEARCH_PATTERN_SIZE; j++) {
- next[j] =3D (next[j] <=3D s+SEARCH_PATTERN_SIZE-j) ? next[j] : s+SEARC=
H_PATTERN_SIZE-j;
- if (j >=3D s) s =3D g[s];
- }
- free(g);
- return true;
-}
-
-int MatroskaSearch::Match(unsigned int start)
-{
- int i, j;
-
- i =3D SEARCH_PATTERN_SIZE - 1 + start;
- while (i < SEARCH_SOURCE_SIZE) {
- j =3D SEARCH_PATTERN_SIZE - 1;
- while (j >=3D 0 && source[i] =3D=3D pattern[j]) {
- i--;
- j--;
- }
- if (j < 0) return i + 1;
- if (skip[source[i] & 0x00ff] >=3D next[j])
- i +=3D skip[source[i] & 0x00ff];
- else i +=3D next[j];
- }
- return -1;
+/*
+ * Part of the foobar2000 Matroska plugin
+ *
+ * Copyright (C) Jory 'jcsston' Stone (jcsston at toughguy net) - 2003-=
2004
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING =
THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PUR=
POSE.
+ *
+ */
+
+/*!
+ \file matroska_parser.cpp
+ \version $Id$
+ \brief An audio slated Matroska Reader+Parser
+ \author Jory Stone <jcsston @ toughguy.net>
+*/
+
+#include "matroska_parser.h"
+
+#include <string>
+using std::string;
+
+using namespace LIBEBML_NAMESPACE;=09
+using namespace LIBMATROSKA_NAMESPACE;
+
+static const char * rg_fields[]=3D
+{
+ "REPLAYGAIN_GAIN",
+ "REPLAYGAIN_PEAK"
+};
+
+static const char * rg_track_fields[]=3D
+{
+ "REPLAYGAIN_TRACK_GAIN",
+ "REPLAYGAIN_TRACK_PEAK"
+};
+
+static const char * rg_album_fields[]=3D
+{
+ "REPLAYGAIN_ALBUM_GAIN",
+ "REPLAYGAIN_ALBUM_PEAK"
+};
+
+#define MATROSKA_TAG_IDX 0
+#define FOOBAR2K_TAG_IDX 1
+
+static const char * chapter_tag_mapping[][2] =3D
+{
+ { "PART_NUMBER", "TRACKNUMBER" },
+ { "DATE_RELEASED", "DATE" },
+ //{ "LEAD_PERFORMER", "PERFORMER" },
+ //{ "ACCOMPANIMENT", "BAND" },
+ //{ "LYRICIST", "WRITER" }
+};
+
+static const char * edition_tag_mapping[][2] =3D
+{
+ { "TITLE", "ALBUM" },
+ { "CATALOG_NUMBER", "CATALOG" },
+ { "TOTAL_PARTS", "TOTALTRACKS" },
+ //{ "PART_NUMBER", "DISCNUMBER" },
+ //{ "TOTAL_DISCS", "TOTALDISCS" }
+};
+
+static const char * hidden_edition_field[] =3D
+{
+ "___DUMMY___",
+};
+
+static const char * hidden_chapter_field[] =3D
+{
+ "CDAUDIO_TRACK_FLAGS",
+};
+
+bool starts_with(const string &s, const char *start) {
+ return strncmp(s.c_str(), start, strlen(start)) =3D=3D 0;
+};
+
+uint64 MatroskaAudioParser::SecondsToTimecode(double seconds)
+{
+ return (uint64)floor(seconds * 1000000000);
+};
+
+double MatroskaAudioParser::TimecodeToSeconds(uint64 code,unsigned sampl=
erate_hint)
+{
+ return ((double)(int64)code / 1000000000);
+};
+
+
+MatroskaAudioFrame::MatroskaAudioFrame()=20
+{
+ timecode =3D 0;
+ duration =3D 0;
+ add_id =3D 0;
+};
+
+MatroskaAttachment::MatroskaAttachment()
+{
+ FileName =3D L"";
+ MimeType =3D "";
+ Description =3D L"";
+ SourceFilename =3D L"";
+ SourceStartPos =3D 0;
+ SourceDataLength =3D 0;
+};
+
+void MatroskaAudioFrame::Reset()
+{
+ timecode =3D 0;
+ duration =3D 0;
+ add_id =3D 0;
+};
+
+MatroskaSimpleTag::MatroskaSimpleTag()
+{
+ name =3D L"";
+ value =3D L"";
+ language =3D "und";
+ defaultFlag =3D 1;
+ hidden =3D false;
+ removalPending =3D false;
+};
+
+MatroskaTagInfo::MatroskaTagInfo()
+{
+ targetTrackUID =3D 0;
+ targetEditionUID =3D 0;
+ targetChapterUID =3D 0;
+ targetAttachmentUID =3D 0;
+ targetTypeValue =3D 0;
+};
+
+void MatroskaTagInfo::SetTagValue(const char *name, const char *value, i=
nt index)
+{
+ for (size_t s =3D 0; s < tags.size(); s++)
+ {
+ MatroskaSimpleTag ¤tSimpleTag =3D tags.at(s);
+ if (strcmpi(currentSimpleTag.name.GetUTF8().c_str(), name) =3D=3D 0) =
=09
+ {
+ if(index =3D=3D 0)
+ {
+ currentSimpleTag.value.SetUTF8(value);
+ currentSimpleTag.removalPending =3D false;
+ return;
+ }
+ index--;
+ }
+ }
+
+ // If we are here then we didn't find this tag in the vector already
+ MatroskaSimpleTag newSimpleTag;
+ newSimpleTag.name.SetUTF8(name);
+ newSimpleTag.value.SetUTF8(value);=09
+ newSimpleTag.removalPending =3D false;
+ tags.push_back(newSimpleTag);
+};
+
+void MatroskaTagInfo::RemoveMarkedTags()
+{
+ for (int i =3D tags.size()-1; i >=3D 0; i--)
+ {
+ MatroskaSimpleTag &simpleTag =3D tags.at(i);
+ if(simpleTag.removalPending =3D=3D true)
+ {
+ tags.erase(tags.begin() + i);
+ }
+ }
+}
+
+void MatroskaTagInfo::MarkAllAsRemovalPending()
+{
+ for (int i =3D tags.size()-1; i >=3D 0; i--)
+ {
+ MatroskaSimpleTag &simpleTag =3D tags.at(i);
+ simpleTag.removalPending =3D true;
+ }
+}
+
+MatroskaChapterDisplayInfo::MatroskaChapterDisplayInfo() {
+ string =3D L"";
+};
+
+MatroskaChapterInfo::MatroskaChapterInfo() {
+ chapterUID =3D 0;
+ timeStart =3D 0;
+ timeEnd =3D 0;
+}
+
+MatroskaEditionInfo::MatroskaEditionInfo() {
+ editionUID =3D 0;
+}
+
+MatroskaTrackInfo::MatroskaTrackInfo() {
+ trackNumber =3D 0;
+ trackUID =3D 0; =09
+ duration =3D 0;
+
+ channels =3D 1;
+ samplesPerSec =3D 0;
+ samplesOutputPerSec =3D 0;
+ bitsPerSample =3D 0;
+ avgBytesPerSec =3D 0;
+ defaultDuration =3D 0;
+
+ name =3D L"";
+
+ codecPrivateReady =3D false;
+};
+
+MatroskaAudioParser::MatroskaAudioParser(service_ptr_t<file> input, abor=
t_callback & p_abort)=20
+ : m_IOCallback(input, p_abort),
+ m_InputStream(m_IOCallback)
+{
+ m_TimecodeScale =3D TIMECODE_SCALE;
+ m_FileDate =3D 0;
+ m_Duration =3D 0;
+ m_CurrentTimecode =3D 0;
+ //m_ElementLevel0 =3D NULL;
+ //UpperElementLevel =3D 0;
+ m_CurrentEdition =3D 0;
+ m_CurrentChapter =3D 0;
+ m_FileSize =3D input->get_size(p_abort);
+ m_TagPos =3D 0;
+ m_TagSize =3D 0;
+ m_TagScanRange =3D 1024 * 64;
+ m_CurrentTrackNo =3D 0;
+};
+
+MatroskaAudioParser::~MatroskaAudioParser() {
+ //if (m_ElementLevel0 !=3D NULL)
+ // _DELETE(m_ElementLevel0);
+ //delete m_ElementLevel0;
+=09
+ while (!m_Queue.empty()) {
+ MatroskaAudioFrame *currentPacket =3D m_Queue.front();
+ //delete currentPacket;
+ _DELETE(currentPacket);
+ m_Queue.pop();
+ }
+};
+
+int MatroskaAudioParser::Parse(bool bInfoOnly, bool bBreakAtClusters)=20
+{
+ try {
+ int UpperElementLevel =3D 0;
+ bool bAllowDummy =3D false;
+ // Elements for different levels
+ ElementPtr ElementLevel1;
+ ElementPtr ElementLevel2;
+ ElementPtr ElementLevel3;
+ ElementPtr ElementLevel4;
+ ElementPtr ElementLevel5;
+ ElementPtr NullElement;
+
+ // Be sure we are at the beginning of the file
+ m_IOCallback.setFilePointer(0);
+ // Find the EbmlHead element. Must be the first one.
+ m_ElementLevel0 =3D ElementPtr(m_InputStream.FindNextID(EbmlHead::Clas=
sInfos, 0xFFFFFFFFFFFFFFFFL));
+ if (m_ElementLevel0 =3D=3D NullElement) {
+ return 1;
+ }
+ //We must have found the EBML head :)
+ m_ElementLevel0->SkipData(m_InputStream, m_ElementLevel0->Generic().Co=
ntext);
+ //delete m_ElementLevel0;
+ //_DELETE(m_ElementLevel0);
+
+ // Next element must be a segment
+ m_ElementLevel0 =3D ElementPtr(m_InputStream.FindNextID(KaxSegment::Cl=
assInfos, 0xFFFFFFFFFFFFFFFFL));
+ if (m_ElementLevel0 =3D=3D NullElement) {
+ //No segment/level 0 element found.
+ return 1;
+ }
+ if (!(EbmlId(*m_ElementLevel0) =3D=3D KaxSegment::ClassInfos.GlobalId)=
) {
+ //delete m_ElementLevel0;
+ //m_ElementLevel0 =3D NULL;
+ //_DELETE(m_ElementLevel0);
+ return 1;
+ }
+
+ UpperElementLevel =3D 0;
+ // We've got our segment, so let's find the tracks
+ ElementLevel1 =3D ElementPtr(m_InputStream.FindNextElement(m_ElementLe=
vel0->Generic().Context, UpperElementLevel, 0xFFFFFFFFFFFFFFFFL, true, 1)=
);
+ while (ElementLevel1 !=3D NullElement) {
+ if (UpperElementLevel > 0) {
+ break;
+ }
+ if (UpperElementLevel < 0) {
+ UpperElementLevel =3D 0;
+ }
+
+ if (EbmlId(*ElementLevel1) =3D=3D KaxSeekHead::ClassInfos.GlobalId) {
+ if (m_IOCallback.seekable()) {
+ Parse_MetaSeek(ElementLevel1, bInfoOnly);
+ if (m_TagPos =3D=3D 0) {
+ // Search for them at the end of the file
+ if (m_TagScanRange > 0)
+ {
+ m_IOCallback.setFilePointer(m_FileSize - m_TagScanRange);
+ uint64 init_pos =3D m_IOCallback.getFilePointer();
+ /*
+ BM Search
+ */
+ binary buf[1024*64];
+ binary pat[3]; pat[0] =3D 0x54; pat[1] =3D 0xc3; pat[2] =3D 0x67;
+ uint64 s_pos =3D m_IOCallback.getFilePointer();
+ m_IOCallback.read(buf, m_TagScanRange);
+ MatroskaSearch search(buf, pat);
+ int pos =3D search.Match();
+ if (pos !=3D -1) {
+ do {
+ m_IOCallback.setFilePointer(s_pos+pos+3);
+ uint64 startPos =3D m_IOCallback.getFilePointer();
+ m_IOCallback.setFilePointer(-4, seek_current);
+ ElementPtr levelUnknown =3D ElementPtr(m_InputStream.FindNextID=
(KaxTags::ClassInfos, 0xFFFFFFFFFFFFFFFFL));
+ if ((levelUnknown !=3D NullElement)=20
+ && (m_FileSize >=3D startPos + levelUnknown->GetSize())=20
+ && (EbmlId(*levelUnknown) =3D=3D KaxTags::ClassInfos.GlobalId)=
)
+ {
+ Parse_Tags(static_cast<KaxTags *>(levelUnknown.get()));
+ break;
+ }
+ m_IOCallback.setFilePointer(s_pos);
+ pos =3D search.Match(pos+1);
+ } while (pos !=3D -1);
+ /*
+ ~BM Search
+ */
+ } else {
+ m_IOCallback.setFilePointer(init_pos);
+ binary Buffer[4];
+ while (m_IOCallback.read(Buffer, 3) >=3D 3)
+ {//0x18
+ if ((Buffer[0] =3D=3D 0x54) && (Buffer[1] =3D=3D 0xc3) && (Buff=
er[2] =3D=3D 0x67))
+ {
+ uint64 startPos =3D m_IOCallback.getFilePointer();
+
+ //seek back 3 bytes, so libmatroska can find the Tags element =
Ebml ID
+ m_IOCallback.setFilePointer(-4, seek_current);
+
+ ElementPtr levelUnknown =3D ElementPtr(m_InputStream.FindNextI=
D(KaxTags::ClassInfos, 0xFFFFFFFFFFFFFFFFL));
+ if ((levelUnknown !=3D NullElement)=20
+ && (m_FileSize >=3D startPos + levelUnknown->GetSize())=20
+ && (EbmlId(*levelUnknown) =3D=3D KaxTags::ClassInfos.GlobalId=
))
+ {
+ Parse_Tags(static_cast<KaxTags *>(levelUnknown.get()));
+ //_DELETE(levelUnknown);
+ break;
+ }
+ //_DELETE(levelUnknown);
+
+ //Restore the file pos
+ m_IOCallback.setFilePointer(startPos);
+ }
+ //seek back 2 bytes
+ m_IOCallback.setFilePointer(-2, seek_current);
+ }
+ }
+ } else {
+ //m_TagPos =3D m_FileSize;
+ }
+ }
+ }
+ }else if (EbmlId(*ElementLevel1) =3D=3D KaxInfo::ClassInfos.GlobalId)=
{
+ // General info about this Matroska file
+ ElementLevel2 =3D ElementPtr(m_InputStream.FindNextElement(ElementLe=
vel1->Generic().Context, UpperElementLevel, 0xFFFFFFFFFFFFFFFFL, bAllowDu=
mmy));
+ while (ElementLevel2 !=3D NullElement) {
+ if (UpperElementLevel > 0) {
+ break;
+ }
+ if (UpperElementLevel < 0) {
+ UpperElementLevel =3D 0;
+ }
+
+ if (EbmlId(*ElementLevel2) =3D=3D KaxTimecodeScale::ClassInfos.Glob=
alId) {
+ KaxTimecodeScale &TimeScale =3D *static_cast<KaxTimecodeScale *>(E=
lementLevel2.get());
+ TimeScale.ReadData(m_InputStream.I_O());
+
+ //matroskaGlobalTrack->SetTimecodeScale(uint64(TimeScale));
+ m_TimecodeScale =3D uint64(TimeScale);
+ } else if (EbmlId(*ElementLevel2) =3D=3D KaxDuration::ClassInfos.Gl=
obalId) {
+ KaxDuration &duration =3D *static_cast<KaxDuration *>(ElementLevel=
2.get());
+ duration.ReadData(m_InputStream.I_O());
+
+ // it's in milliseconds? -- in nanoseconds.
+ m_Duration =3D double(duration) * m_TimecodeScale;
+
+ } else if (EbmlId(*ElementLevel2) =3D=3D KaxDateUTC::ClassInfos.Glo=
balId) {
+ KaxDateUTC & DateUTC =3D *static_cast<KaxDateUTC *>(ElementLevel2.=
get());
+ DateUTC.ReadData(m_InputStream.I_O());
+ =09
+ m_FileDate =3D DateUTC.GetEpochDate();
+
+ } else if (EbmlId(*ElementLevel2) =3D=3D KaxSegmentFilename::ClassI=
nfos.GlobalId) {
+ KaxSegmentFilename &tag_SegmentFilename =3D *static_cast<KaxSegmen=
tFilename *>(ElementLevel2.get());
+ tag_SegmentFilename.ReadData(m_InputStream.I_O());
+
+ m_SegmentFilename =3D *static_cast<EbmlUnicodeString *>(&tag_Segme=
ntFilename);
+
+ } else if (EbmlId(*ElementLevel2) =3D=3D KaxMuxingApp::ClassInfos.G=
lobalId) {
+ KaxMuxingApp &tag_MuxingApp =3D *static_cast<KaxMuxingApp *>(Eleme=
ntLevel2.get());
+ tag_MuxingApp.ReadData(m_InputStream.I_O());
+
+ m_MuxingApp =3D *static_cast<EbmlUnicodeString *>(&tag_MuxingApp);
+
+ } else if (EbmlId(*ElementLevel2) =3D=3D KaxWritingApp::ClassInfos.=
GlobalId) {
+ KaxWritingApp &tag_WritingApp =3D *static_cast<KaxWritingApp *>(El=
ementLevel2.get());
+ tag_WritingApp.ReadData(m_InputStream.I_O());
+ =09
+ m_WritingApp =3D *static_cast<EbmlUnicodeString *>(&tag_WritingApp=
);
+
+ } else if (EbmlId(*ElementLevel2) =3D=3D KaxTitle::ClassInfos.Globa=
lId) {
+ KaxTitle &Title =3D *static_cast<KaxTitle*>(ElementLevel2.get());
+ Title.ReadData(m_InputStream.I_O());
+ m_FileTitle =3D UTFstring(Title).c_str();
+ }
+
+ if (UpperElementLevel > 0) { // we're coming from ElementLevel3
+ UpperElementLevel--;
+ //delete ElementLevel2;
+ ElementLevel2 =3D ElementLevel3;
+ if (UpperElementLevel > 0)
+ break;
+ } else {
+ ElementLevel2->SkipData(m_InputStream, ElementLevel2->Generic().Co=
ntext);
+ //delete ElementLevel2;
+ //_DELETE(ElementLevel2);
+ ElementLevel2 =3D ElementPtr(m_InputStream.FindNextElement(Element=
Level1->Generic().Context, UpperElementLevel, 0xFFFFFFFFFFFFFFFFL, bAllow=
Dummy));
+ }
+ }
+ }else if (EbmlId(*ElementLevel1) =3D=3D KaxChapters::ClassInfos.Globa=
lId) {
+ Parse_Chapters(static_cast<KaxChapters *>(ElementLevel1.get()));
+ }else if (EbmlId(*ElementLevel1) =3D=3D KaxTags::ClassInfos.GlobalId)=
{
+ Parse_Tags(static_cast<KaxTags *>(ElementLevel1.get()));
+ } else if (EbmlId(*ElementLevel1) =3D=3D KaxTracks::ClassInfos.Global=
Id) {
+ // Yep, we've found our KaxTracks element. Now find all tracks
+ // contained in this segment.=20
+ KaxTracks *Tracks =3D static_cast<KaxTracks *>(ElementLevel1.get());
+ EbmlElement* tmpElement =3D ElementLevel2.get();
+ Tracks->Read(m_InputStream, KaxTracks::ClassInfos.Context, UpperElem=
entLevel, tmpElement, bAllowDummy);
+
+ unsigned int Index0;
+ for (Index0 =3D 0; Index0 < Tracks->ListSize(); Index0++) {
+ if ((*Tracks)[Index0]->Generic().GlobalId =3D=3D KaxTrackEntry::Cla=
ssInfos.GlobalId) {
+ KaxTrackEntry &TrackEntry =3D *static_cast<KaxTrackEntry *>((*Trac=
ks)[Index0]);
+ // Create a new MatroskaTrack
+ MatroskaTrackInfo newTrack;
+ =09
+ unsigned int Index1;
+ for (Index1 =3D 0; Index1 < TrackEntry.ListSize(); Index1++) {
+ if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrackNumber:=
:ClassInfos.GlobalId) {
+ KaxTrackNumber &TrackNumber =3D *static_cast<KaxTrackNumber*>(Tr=
ackEntry[Index1]);
+ newTrack.trackNumber =3D TrackNumber;
+
+ } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrack=
UID::ClassInfos.GlobalId) {
+ KaxTrackUID &TrackUID =3D *static_cast<KaxTrackUID*>(TrackEntry[=
Index1]);
+ newTrack.trackUID =3D TrackUID;
+
+ } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrack=
Type::ClassInfos.GlobalId) {
+ KaxTrackType &TrackType =3D *static_cast<KaxTrackType*>(TrackEnt=
ry[Index1]);
+ if (uint8(TrackType) !=3D track_audio) {
+ newTrack.trackNumber =3D 0xFFFF;
+ break;
+ }
+
+ } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrack=
TimecodeScale::ClassInfos.GlobalId) {
+ KaxTrackTimecodeScale &TrackTimecodeScale =3D *static_cast<KaxTr=
ackTimecodeScale*>(TrackEntry[Index1]);
+ // TODO: Support Tracks with different timecode scales?
+ //newTrack->TrackTimecodeScale =3D TrackTimecodeScale;
+
+ } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrack=
DefaultDuration::ClassInfos.GlobalId) {
+ KaxTrackDefaultDuration &TrackDefaultDuration =3D *static_cast<K=
axTrackDefaultDuration*>(TrackEntry[Index1]);
+ newTrack.defaultDuration =3D uint64(TrackDefaultDuration);
+
+ } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxCodec=
ID::ClassInfos.GlobalId) {
+ KaxCodecID &CodecID =3D *static_cast<KaxCodecID*>(TrackEntry[Ind=
ex1]);
+ newTrack.codecID =3D std::string(CodecID);
+
+ } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxCodec=
Private::ClassInfos.GlobalId) {
+ KaxCodecPrivate &CodecPrivate =3D *static_cast<KaxCodecPrivate*>=
(TrackEntry[Index1]);
+ newTrack.codecPrivate.resize(CodecPrivate.GetSize()); =09
+ memcpy(&newTrack.codecPrivate[0], CodecPrivate.GetBuffer(), Code=
cPrivate.GetSize());
+
+ } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrack=
FlagDefault::ClassInfos.GlobalId) {
+ KaxTrackFlagDefault &TrackFlagDefault =3D *static_cast<KaxTrackF=
lagDefault*>(TrackEntry[Index1]);
+ //newTrack->FlagDefault =3D TrackFlagDefault;
+ /* Matroska2
+ } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrack=
FlagEnabled::ClassInfos.GlobalId) {
+ KaxTrackFlagEnabled &TrackFlagEnabled =3D *static_cast<KaxTrackF=
lagEnabled*>(TrackEntry[Index1]);
+ //newTrack->FlagEnabled =3D TrackFlagEnabled;
+ */
+ } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrack=
FlagLacing::ClassInfos.GlobalId) {
+ KaxTrackFlagLacing &TrackFlagLacing =3D *static_cast<KaxTrackFla=
gLacing*>(TrackEntry[Index1]);
+ //newTrack->FlagLacing =3D TrackFlagLacing;
+
+ } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrack=
Language::ClassInfos.GlobalId) {
+ KaxTrackLanguage &TrackLanguage =3D *static_cast<KaxTrackLanguag=
e*>(TrackEntry[Index1]);
+ newTrack.language =3D std::string(TrackLanguage);
+
+ } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrack=
MaxCache::ClassInfos.GlobalId) {
+ KaxTrackMaxCache &TrackMaxCache =3D *static_cast<KaxTrackMaxCach=
e*>(TrackEntry[Index1]);
+ //newTrack->MaxCache =3D TrackMaxCache;
+
+ } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrack=
MinCache::ClassInfos.GlobalId) {
+ KaxTrackMinCache &TrackMinCache =3D *static_cast<KaxTrackMinCach=
e*>(TrackEntry[Index1]);
+ //newTrack->MinCache =3D TrackMinCache;
+
+ } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrack=
Name::ClassInfos.GlobalId) {
+ KaxTrackName &TrackName =3D *static_cast<KaxTrackName*>(TrackEnt=
ry[Index1]);
+ newTrack.name =3D TrackName;
+
+ } else if (TrackEntry[Index1]->Generic().GlobalId =3D=3D KaxTrack=
Audio::ClassInfos.GlobalId) {
+ KaxTrackAudio &TrackAudio =3D *static_cast<KaxTrackAudio*>(Track=
Entry[Index1]);
+
+ unsigned int Index2;
+ for (Index2 =3D 0; Index2 < TrackAudio.ListSize(); Index2++) {
+ if (TrackAudio[Index2]->Generic().GlobalId =3D=3D KaxAudioBitDe=
pth::ClassInfos.GlobalId) {
+ KaxAudioBitDepth &AudioBitDepth =3D *static_cast<KaxAudioBitDe=
pth*>(TrackAudio[Index2]);
+ newTrack.bitsPerSample =3D AudioBitDepth;
+ /* Matroska2
+ } else if (TrackAudio[Index2]->Generic().GlobalId =3D=3D KaxAud=
ioPosition::ClassInfos.GlobalId) {
+ KaxAudioPosition &AudioPosition =3D *static_cast<KaxAudioPosit=
ion*>(TrackAudio[Index2]);
+
+ // TODO: Support multi-channel?
+ //newTrack->audio->ChannelPositionSize =3D AudioPosition.GetSi=
ze();
+ //newTrack->audio->ChannelPosition =3D new binary[AudioPositio=
n.GetSize()+1];
+ //memcpy(newTrack->audio->ChannelPosition, AudioPosition.GetBu=
ffer(), AudioPosition.GetSize());
+ */
+ } else if (TrackAudio[Index2]->Generic().GlobalId =3D=3D KaxAud=
ioChannels::ClassInfos.GlobalId) {
+ KaxAudioChannels &AudioChannels =3D *static_cast<KaxAudioChann=
els*>(TrackAudio[Index2]);
+ newTrack.channels =3D AudioChannels;
+
+ } else if (TrackAudio[Index2]->Generic().GlobalId =3D=3D KaxAud=
ioOutputSamplingFreq::ClassInfos.GlobalId) {
+ KaxAudioOutputSamplingFreq &AudioOutputSamplingFreq =3D *stati=
c_cast<KaxAudioOutputSamplingFreq*>(TrackAudio[Index2]);
+ newTrack.samplesOutputPerSec =3D AudioOutputSamplingFreq;
+
+ } else if (TrackAudio[Index2]->Generic().GlobalId =3D=3D KaxAud=
ioSamplingFreq::ClassInfos.GlobalId) {
+ KaxAudioSamplingFreq &AudioSamplingFreq =3D *static_cast<KaxAu=
dioSamplingFreq*>(TrackAudio[Index2]);
+ newTrack.samplesPerSec =3D AudioSamplingFreq;
+ }
+ }
+ }
+ }
+ if (newTrack.trackNumber !=3D 0xFFFF)
+ m_Tracks.push_back(newTrack);
+ }
+ }
+ } else if (EbmlId(*ElementLevel1) =3D=3D KaxCluster::ClassInfos.Globa=
lId) {
+ if (bBreakAtClusters) {
+ m_IOCallback.setFilePointer(ElementLevel1->GetElementPosition());
+ //delete ElementLevel1;
+ //ElementLevel1 =3D NULL;
+ //_DELETE(ElementLevel1);
+ break;
+ }
+ } else if (EbmlId(*ElementLevel1) =3D=3D KaxAttachments::ClassInfos.G=
lobalId) {
+ // Yep, we've found our KaxAttachment element. Now find all attached=
files
+ // contained in this segment.
+#if 1
+ ElementLevel2 =3D ElementPtr(m_InputStream.FindNextElement(ElementLe=
vel1->Generic().Context, UpperElementLevel, 0xFFFFFFFFL, true, 1));
+ while (ElementLevel2 !=3D NullElement) {
+ if (UpperElementLevel > 0) {
+ break;
+ }
+ if (UpperElementLevel < 0) {
+ UpperElementLevel =3D 0;
+ }
+ if (EbmlId(*ElementLevel2) =3D=3D KaxAttached::ClassInfos.GlobalId)=
{
+ // We actually found a attached file entry :D
+ MatroskaAttachment newAttachment;
+
+ ElementLevel3 =3D ElementPtr(m_InputStream.FindNextElement(Element=
Level2->Generic().Context, UpperElementLevel, 0xFFFFFFFFL, true, 1));
+ while (ElementLevel3 !=3D NullElement) {
+ if (UpperElementLevel > 0) {
+ break;
+ }
+ if (UpperElementLevel < 0) {
+ UpperElementLevel =3D 0;
+ }
+
+ // Now evaluate the data belonging to this track
+ if (EbmlId(*ElementLevel3) =3D=3D KaxFileName::ClassInfos.GlobalI=
d) {
+ KaxFileName &attached_filename =3D *static_cast<KaxFileName *>(E=
lementLevel3.get());
+ attached_filename.ReadData(m_InputStream.I_O());
+ newAttachment.FileName =3D UTFstring(attached_filename);
+
+ } else if (EbmlId(*ElementLevel3) =3D=3D KaxMimeType::ClassInfos.=
GlobalId) {
+ KaxMimeType &attached_mime_type =3D *static_cast<KaxMimeType *>(=
ElementLevel3.get());
+ attached_mime_type.ReadData(m_InputStream.I_O());
+ newAttachment.MimeType =3D std::string(attached_mime_type);
+
+ } else if (EbmlId(*ElementLevel3) =3D=3D KaxFileDescription::Clas=
sInfos.GlobalId) {
+ KaxFileDescription &attached_description =3D *static_cast<KaxFil=
eDescription *>(ElementLevel3.get());
+ attached_description.ReadData(m_InputStream.I_O());
+ newAttachment.Description =3D UTFstring(attached_description);
+
+ } else if (EbmlId(*ElementLevel3) =3D=3D KaxFileData::ClassInfos.=
GlobalId) {
+ KaxFileData &attached_data =3D *static_cast<KaxFileData *>(Eleme=
ntLevel3.get());
+
+ //We don't what to read the data into memory because it could be=
very large
+ //attached_data.ReadData(m_InputStream.I_O());
+
+ //Instead we store the Matroska filename, the start of the data =
and the length, so we can read it
+ //later at the users request. IMHO This will save a lot of memor=
y
+ newAttachment.SourceStartPos =3D attached_data.GetElementPositio=
n() + attached_data.HeadSize();
+ newAttachment.SourceDataLength =3D attached_data.GetSize();
+ }
+
+ if (UpperElementLevel > 0) { // we're coming from ElementLevel4
+ UpperElementLevel--;
+ ElementLevel3 =3D ElementLevel4;
+ if (UpperElementLevel > 0)
+ break;
+ } else {
+ ElementLevel3->SkipData(m_InputStream, ElementLevel3->Generic().=
Context);
+ ElementLevel3 =3D ElementPtr(m_InputStream.FindNextElement(Eleme=
ntLevel2->Generic().Context, UpperElementLevel, 0xFFFFFFFFL, true, 1));
+ } =09
+ } // while (ElementLevel3 !=3D NULL)
+ //m_AttachmentList.push_back(newAttachment);
+ m_AttachmentList.add_item(newAttachment);
+ }
+
+ if (UpperElementLevel > 0) { // we're coming from ElementLevel3
+ UpperElementLevel--;
+ ElementLevel2 =3D ElementLevel3;
+ if (UpperElementLevel > 0)
+ break;
+ } else {
+ ElementLevel2->SkipData(m_InputStream, ElementLevel2->Generic().Co=
ntext);
+ ElementLevel2 =3D ElementPtr(m_InputStream.FindNextElement(Element=
Level1->Generic().Context, UpperElementLevel, 0xFFFFFFFFL, true, 1));
+ }
+ } // while (ElementLevel2 !=3D NULL)
+#endif
+ }
+ =09
+ if (UpperElementLevel > 0) { // we're coming from ElementLevel2
+ UpperElementLevel--;
+ //delete ElementLevel1;
+ //_DELETE(ElementLevel1);
+ ElementLevel1 =3D ElementLevel2;
+ if (UpperElementLevel > 0)
+ break;
+ } else {
+ ElementLevel1->SkipData(m_InputStream, ElementLevel1->Generic().Cont=
ext);
+ //delete ElementLevel1;
+ //ElementLevel1 =3D NULL;
+ //_DELETE(ElementLevel1);
+
+ ElementLevel1 =3D ElementPtr(m_InputStream.FindNextElement(m_Element=
Level0->Generic().Context, UpperElementLevel, 0xFFFFFFFFFFFFFFFFL, true, =
1));
+ }
+ } // while (ElementLevel1 !=3D NULL)
+ //_DELETE(ElementLevel3);
+ //_DELETE(ElementLevel2);
+ //_DELETE(ElementLevel1);
+ } catch (std::exception &) {
+ return 1;
+
+ } catch (...) {
+ return 1;
+ }
+
+ CountClusters();
+ return 0;
+};
+
+//int MatroskaAudioParser::WriteTags(const file_info & info)
+int MatroskaAudioParser::WriteTags()
+{
+ KaxTags & MyKaxTags =3D GetChild<KaxTags>(*static_cast<EbmlMaster *>(m_=
ElementLevel0.get()));
+
+ // On to writing :)
+ if (m_TagPos =3D=3D 0) {
+ // Ok, we need to append the tags onto the end of the file, no existin=
g tag element
+ m_TagPos =3D m_FileSize;
+ } else {
+ =09
+ }=09
+
+ //Start going through the list and adding tags
+ KaxTag *MyKaxTag_last =3D NULL;
+ for(size_t current_tag_track =3D 0; current_tag_track < m_Tags.size(); =
current_tag_track++) {
+ KaxTag *MyKaxTag =3D NULL;
+ if (MyKaxTag_last !=3D NULL)
+ {
+ MyKaxTag =3D &GetNextChild<KaxTag>(MyKaxTags, *MyKaxTag_last);
+ MyKaxTag_last =3D MyKaxTag;
+ }else {
+ MyKaxTag =3D &GetChild<KaxTag>(MyKaxTags);
+ MyKaxTag_last =3D MyKaxTag;
+ }
+ MatroskaTagInfo ¤tTag =3D m_Tags.at(current_tag_track);
+ //The Targets group
+ KaxTagTargets & MyKaxTagTargets =3D GetChild<KaxTagTargets>(*MyKaxTag)=
;
+ if (currentTag.targetTrackUID !=3D 0) {
+ KaxTagTrackUID & MyKaxTagTrackUID =3D GetChild<KaxTagTrackUID>(MyKaxT=
agTargets);
+ *static_cast<EbmlUInteger *>(&MyKaxTagTrackUID) =3D currentTag.target=
TrackUID;
+ }
+ if (currentTag.targetEditionUID !=3D 0) {
+ KaxTagEditionUID & MyKaxTagEditionUID =3D GetChild<KaxTagEditionUID>(=
MyKaxTagTargets);
+ *static_cast<EbmlUInteger *>(&MyKaxTagEditionUID) =3D currentTag.targ=
etEditionUID;
+ }
+ if (currentTag.targetChapterUID !=3D 0) {
+ KaxTagChapterUID & MyKaxTagChapterUID =3D GetChild<KaxTagChapterUID>(=
MyKaxTagTargets);
+ *static_cast<EbmlUInteger *>(&MyKaxTagChapterUID) =3D currentTag.targ=
etChapterUID;
+ }
+ if (currentTag.targetAttachmentUID !=3D 0) {
+ KaxTagAttachmentUID & MyKaxTagAttachmentUID =3D GetChild<KaxTagAttach=
mentUID>(MyKaxTagTargets);
+ *static_cast<EbmlUInteger *>(&MyKaxTagAttachmentUID) =3D currentTag.t=
argetAttachmentUID;
+ }
+ if(currentTag.targetTypeValue !=3D 0) {
+ KaxTagTargetTypeValue& MyKaxTagTargetTypeValue =3D GetChild<KaxTagTar=
getTypeValue>(MyKaxTagTargets);
+ *static_cast<EbmlUInteger *>(&MyKaxTagTargetTypeValue) =3D currentTag=
.targetTypeValue;
+ if(!currentTag.targetType.empty())
+ {
+ KaxTagTargetType& MyKaxTagTargetType =3D GetChild<KaxTagTargetType>(=
MyKaxTagTargets);
+ *static_cast<EbmlString *>(&MyKaxTagTargetType) =3D currentTag.targe=
tType; =09
+ }
+ }
+ =09
+ // Add the millions of simple tags we can have ;)
+ KaxTagSimple *MySimpleTag_last =3D NULL;
+ for(size_t st =3D 0; st < currentTag.tags.size(); st++) {
+ KaxTagSimple *MySimpleTag =3D NULL;
+ if (MySimpleTag_last !=3D NULL)
+ {
+ MySimpleTag =3D &GetNextChild<KaxTagSimple>(*MyKaxTag, *MySimpleTag_=
last);
+ MySimpleTag_last =3D MySimpleTag;
+ }else {
+ MySimpleTag =3D &GetChild<KaxTagSimple>(*MyKaxTag);
+ MySimpleTag_last =3D MySimpleTag;
+ }
+ MatroskaSimpleTag ¤tSimpleTag =3D currentTag.tags.at(st);
+
+ KaxTagName & MyKaxTagName =3D GetChild<KaxTagName>(*MySimpleTag);
+ *static_cast<EbmlUnicodeString *>(&MyKaxTagName) =3D currentSimpleTag=
.name;
+
+ KaxTagString & MyKaxTagString =3D GetChild<KaxTagString>(*MySimpleTag=
);
+ *static_cast<EbmlUnicodeString *>(&MyKaxTagString) =3D currentSimpleT=
ag.value;
+ =09
+ KaxTagLangue& MyKaxTagLangue =3D GetChild<KaxTagLangue>(*MySimpleTag)=
;
+ *static_cast<EbmlString *>(&MyKaxTagLangue) =3D currentSimpleTag.lang=
uage;
+
+ KaxTagDefault& MyKaxTagDefault =3D GetChild<KaxTagDefault>(*MySimpleT=
ag);
+ *static_cast<EbmlUInteger *>(&MyKaxTagDefault) =3D currentSimpleTag.d=
efaultFlag; =09
+ }
+
+ m_IOCallback.setFilePointer(m_TagPos);
+ // Now we write the tags to the file
+ EbmlVoid & Dummy =3D GetChild<EbmlVoid>(*static_cast<EbmlMaster *>(m_E=
lementLevel0.get()));
+ uint64 size_of_tags =3D m_TagSize;
+ MyKaxTags.UpdateSize(true);
+ if (size_of_tags < MyKaxTags.GetSize())
+ size_of_tags =3D MyKaxTags.GetSize();
+
+ Dummy.SetSize(size_of_tags+8); // Size of the previous tag element
+ uint64 pos =3D m_IOCallback.getFilePointer();
+ if (pos =3D=3D 0)
+ //We don't want to overwrite the EBML header :P
+ return 2;
+ Dummy.Render(m_IOCallback);
+ m_IOCallback.setFilePointer(Dummy.GetElementPosition());
+ pos =3D m_IOCallback.getFilePointer();
+ if (pos =3D=3D 0)
+ //We don't want to overwrite the EBML header :P
+ return 2;
+
+ MyKaxTags.Render(m_IOCallback);
+ =09
+ //l0->UpdateSize(false, true);
+ std::auto_ptr<KaxSegment> new_segment(new KaxSegment);
+ KaxSegment * segment =3D (KaxSegment *)m_ElementLevel0.get();
+
+ m_IOCallback.setFilePointer(segment->GetElementPosition());
+ new_segment->WriteHead(m_IOCallback, segment->HeadSize() - 4);
+ m_IOCallback.setFilePointer(0, seek_end);
+ int ret =3D new_segment->ForceSize(m_IOCallback.getFilePointer() - seg=
ment->HeadSize() - segment->GetElementPosition());
+ if (!ret) {=20
+ segment->OverwriteHead(m_IOCallback);
+ /*("Wrote the element at the end of the file but could "
+ "not update the segment size. Therefore the elemen=
t "
+ "will not be visible. Aborting the process. The fi=
le "
+ "has been changed!")*/
+ m_IOCallback.setFilePointer(segment->HeadSize() - segment->GetElement=
Position());
+ m_IOCallback.truncate();
+
+ return 1;
+ } else {
+ new_segment->OverwriteHead(m_IOCallback);
+
+ }
+
+ }
+ return 0;
+};
+
+static const char* foobar2k_to_matroska_edition_tag(const char * name)
+{
+ if (!stricmp_utf8(name, "ALBUM"))
+ return "TITLE";
+ else if (!stricmp_utf8(name, "SUBALBUM"))
+ return "SUBTITLE";
+ else if (starts_with(name, "ALBUM ")) {
+ static char newname[255];
+ ZeroMemory(newname,255);
+ strncpy(newname,name+6,254);
+ name =3D newname;
+ }
+ for (int i =3D 0; i < tabsize(edition_tag_mapping); i++)
+ if (!stricmp_utf8(name, edition_tag_mapping[i][FOOBAR2K_TAG_IDX]))
+ return edition_tag_mapping[i][MATROSKA_TAG_IDX];
+ return name;
+}
+
+static const char* foobar2k_to_matroska_chapter_tag(const char * name)
+{
+ for (int i =3D 0; i < tabsize(chapter_tag_mapping); i++)
+ if (!stricmp_utf8(name, chapter_tag_mapping[i][FOOBAR2K_TAG_IDX]))
+ return chapter_tag_mapping[i][MATROSKA_TAG_IDX];
+ return name;
+}
+
+int meta_get_num(const file_info &info, const char* name, int idx)
+{
+ assert(pfc::is_valid_utf8(name));
+ int n, m =3D min(info.meta_get_count(), idx);
+ int rv =3D 0;
+ for(n=3D0; n<m; n++)
+ {
+ if (!stricmp_utf8(name, info.meta_enum_name(n)))
+ rv++;
+ }
+ return rv;
+}
+
+bool isEditionTag(const char * name) {
+ if (starts_with(name, "ALBUM") ||
+ starts_with(name, "SUBALBUM") ||
+ starts_with(name, "DISCID") ||
+ starts_with(name, "CATALOG"))
+ {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void MatroskaAudioParser::SetTags(const file_info &info)
+{
+ int i, idx;
+ const char *name, *value;=09
+
+ if (m_Chapters.size() =3D=3D 0)
+ { =09
+ // No chapters, works on track
+ MatroskaTagInfo *trackTag;
+ trackTag =3D FindTagWithTrackUID(m_Tracks.at(m_CurrentTrackNo).trackUI=
D);
+ if (trackTag =3D=3D NULL) {
+ // The tag doesn't exist yet
+ MatroskaTagInfo tempTag;
+ tempTag.targetTrackUID =3D m_Tracks.at(m_CurrentTrackNo).trackUID;
+ m_Tags.push_back(tempTag);
+ trackTag =3D &m_Tags.at(m_Tags.size()-1);
+ }
+ //if(trackTag->targetTypeValue =3D=3D 0)
+ // trackTag->targetTypeValue =3D 50;
+ trackTag->targetTypeValue =3D 30;
+ trackTag->MarkAllAsRemovalPending();
+ int metaDataCount =3D info.meta_get_count();
+ for (i =3D 0; i < metaDataCount; i++)
+ {
+ for (int j =3D 0; j !=3D info.meta_enum_value_count(i); ++j) {
+ name =3D info.meta_enum_name(i);
+ value =3D info.meta_enum_value(i, j);
+ //idx =3D meta_get_num(info, name, i);
+ idx =3D j;
+ name =3D foobar2k_to_matroska_chapter_tag(name);
+ if ((name !=3D NULL) && (value !=3D NULL)) {
+ trackTag->SetTagValue(name, value, idx);
+ }
+ }
+ }
+ // Add the replay_gain tags
+ replaygain_info rg =3D info.get_replaygain();
+ if (rg.is_track_gain_present()) {
+ char tmp[rg.text_buffer_size];
+ pfc::float_to_string(tmp, rg.text_buffer_size, rg.m_track_gain, 7);
+ value =3D (const char*)tmp;
+ } else {
+ value =3D NULL;
+ }
+ if (value)
+ trackTag->SetTagValue("REPLAYGAIN_GAIN", value);
+ if (rg.is_track_peak_present()) {
+ char tmp[rg.text_buffer_size];
+ pfc::float_to_string(tmp, rg.text_buffer_size, rg.m_track_peak, 7);
+ value =3D (const char*)tmp;
+ } else {
+ value =3D NULL;
+ }
+ if (value)
+ trackTag->SetTagValue("REPLAYGAIN_PEAK", value);
+ trackTag->RemoveMarkedTags();
+ }
+=09
+ // Set global track tags as album tags
+ if ((m_Chapters.size() > 0) && (m_CurrentChapter !=3D NULL))
+ {
+ MatroskaTagInfo *trackTag;
+ trackTag =3D FindTagWithTrackUID(m_Tracks.at(m_CurrentTrackNo).trackUI=
D);
+ if (trackTag =3D=3D NULL)
+ {
+ MatroskaTagInfo tempTag;
+ tempTag.targetTrackUID =3D m_Tracks.at(m_CurrentTrackNo).trackUID; =09
+ m_Tags.push_back(tempTag);
+ trackTag =3D &m_Tags.at(m_Tags.size()-1);
+ }
+ if(trackTag->targetTypeValue =3D=3D 0)
+ trackTag->targetTypeValue =3D 50;
+ trackTag->MarkAllAsRemovalPending();
+ int metaDataCount =3D info.meta_get_count();
+ for (i =3D 0; i < metaDataCount; i++)
+ {
+ for (int j =3D 0; j !=3D info.meta_enum_value_count(i); ++j) {
+ name =3D info.meta_enum_name(i);
+ value =3D info.meta_enum_value(i, j);
+ //idx =3D meta_get_num(info, name, i);
+ idx =3D j;
+ if (isEditionTag(name))
+ {
+ name =3D foobar2k_to_matroska_edition_tag(name);
+ } else {
+ name =3D NULL;
+ }
+ if ((name !=3D NULL) && (value !=3D NULL)) {
+ trackTag->SetTagValue(name, value, idx);
+ }
+ }
+ }
+ replaygain_info rg =3D info.get_replaygain();
+ if (rg.is_album_gain_present()) {
+ char tmp[rg.text_buffer_size];
+ pfc::float_to_string(tmp, rg.text_buffer_size, rg.m_album_gain, 7);
+ value =3D (const char*)tmp;
+ } else {
+ value =3D NULL;
+ }
+ if (value)
+ trackTag->SetTagValue("REPLAYGAIN_GAIN", value);
+ if (rg.is_album_peak_present()) {
+ char tmp[rg.text_buffer_size];
+ pfc::float_to_string(tmp, rg.text_buffer_size, rg.m_album_peak, 7);
+ value =3D (const char*)tmp;
+ } else {
+ value =3D NULL;
+ }
+ if (value)
+ trackTag->SetTagValue("REPLAYGAIN_PEAK", value);
+ trackTag->RemoveMarkedTags();
+ }
+
+
+ //If there's not only a track, set all the chapter tags
+ if ((m_Chapters.size() > 0) && (m_CurrentChapter !=3D NULL))
+ {
+ // Ok we add the tags to tag with chapter+track UID's
+ MatroskaTagInfo *chapterTag; =09
+ chapterTag =3D FindTagWithChapterUID(m_CurrentChapter->chapterUID,
+ m_Tracks.at(m_CurrentTrackNo).trackUID);
+ if (chapterTag =3D=3D NULL)
+ {
+ MatroskaTagInfo tempTag;
+ tempTag.targetTrackUID =3D m_Tracks.at(m_CurrentTrackNo).trackUID;
+ tempTag.targetChapterUID =3D m_CurrentChapter->chapterUID;
+ m_Tags.push_back(tempTag);
+ chapterTag =3D &m_Tags.at(m_Tags.size()-1);
+ }
+ if(chapterTag->targetTypeValue =3D=3D 0)
+ chapterTag->targetTypeValue =3D 30;
+ chapterTag->MarkAllAsRemovalPending();
+ int metaDataCount =3D info.meta_get_count();
+ for (i =3D 0; i < metaDataCount; i++)
+ {
+ for (int j =3D 0; j !=3D info.meta_enum_value_count(i); ++j) {
+ name =3D info.meta_enum_name(i);
+ value =3D info.meta_enum_value(i, j);
+ //idx =3D meta_get_num(info, name, i);
+ idx =3D j;
+ if (isEditionTag(name))
+ {
+ name =3D NULL;
+ } else {
+ name =3D foobar2k_to_matroska_chapter_tag(name);
+ }
+ if ((name !=3D NULL) && (value !=3D NULL)) {
+ chapterTag->SetTagValue(name, value, idx);
+ }
+ }
+ }
+ replaygain_info rg =3D info.get_replaygain();
+ if (rg.is_track_gain_present()) {
+ char tmp[rg.text_buffer_size];
+ pfc::float_to_string(tmp, rg.text_buffer_size, rg.m_track_gain, 7);
+ value =3D (const char*)tmp;
+ } else {
+ value =3D NULL;
+ }
+ if (value)
+ chapterTag->SetTagValue("REPLAYGAIN_GAIN", value);
+ if (rg.is_track_peak_present()) {
+ char tmp[rg.text_buffer_size];
+ pfc::float_to_string(tmp, rg.text_buffer_size, rg.m_track_peak, 7);
+ value =3D (const char*)tmp;
+ } else {
+ value =3D NULL;
+ }
+ if (value)
+ chapterTag->SetTagValue("REPLAYGAIN_PEAK", value);
+ chapterTag->RemoveMarkedTags();
+ }
+};
+
+MatroskaTagInfo *MatroskaAudioParser::FindTagWithTrackUID(uint64 trackUI=
D)=20
+{
+ MatroskaTagInfo *foundTag =3D NULL;
+
+ for (size_t t =3D 0; t < m_Tags.size(); t++)
+ {
+ MatroskaTagInfo& currentTag =3D m_Tags.at(t);
+ if (currentTag.targetTrackUID =3D=3D trackUID &&
+ currentTag.targetEditionUID =3D=3D 0 &&
+ currentTag.targetChapterUID =3D=3D 0 &&
+ currentTag.targetAttachmentUID =3D=3D 0)
+ {
+ foundTag =3D ¤tTag;
+ break;
+ }
+ }
+
+ return foundTag;
+};
+
+MatroskaTagInfo *MatroskaAudioParser::FindTagWithEditionUID(uint64 editi=
onUID, uint64 trackUID)
+{
+ MatroskaTagInfo *foundTag =3D NULL;
+
+ for (size_t t =3D 0; t < m_Tags.size(); t++)
+ {
+ MatroskaTagInfo ¤tTag =3D m_Tags.at(t);
+ if (currentTag.targetEditionUID =3D=3D editionUID &&
+ (trackUID =3D=3D 0 || (currentTag.targetTrackUID =3D=3D trackUID)))
+ {
+ foundTag =3D ¤tTag;
+ break;
+ }
+ }
+
+ return foundTag;
+};
+
+MatroskaTagInfo *MatroskaAudioParser::FindTagWithChapterUID(uint64 chapt=
erUID, uint64 trackUID)
+{
+ MatroskaTagInfo *foundTag =3D NULL;
+
+ for (size_t t =3D 0; t < m_Tags.size(); t++)
+ {
+ MatroskaTagInfo ¤tTag =3D m_Tags.at(t);
+ if (currentTag.targetChapterUID =3D=3D chapterUID &&
+ (trackUID =3D=3D 0 || (currentTag.targetTrackUID =3D=3D trackUID)))
+ {
+ foundTag =3D ¤tTag;
+ break;
+ }
+ }
+
+ return foundTag;
+};
+
+double MatroskaAudioParser::GetDuration() {=20
+ if (m_CurrentChapter !=3D NULL) {
+ return TimecodeToSeconds(m_CurrentChapter->timeEnd - m_CurrentChapter-=
>timeStart);
+ };
+ return m_Duration / 1000000000.0;
+ if (m_Tracks.size() !=3D 0) {
+ return m_Tracks.at(m_CurrentTrackNo).defaultDuration * (int64)m_Timeco=
deScale;
+ }
+};
+
+int32 MatroskaAudioParser::GetFirstAudioTrack()
+{
+ for (uint16 t =3D 0; t < m_Tracks.size(); t++)
+ {
+ MatroskaTrackInfo ¤tTrack =3D m_Tracks.at(t);
+ if (!strncmp(currentTrack.codecID.c_str(),"A_",2)) return t;
+ }
+ return -1;
+}
+
+uint32 MatroskaAudioParser::GetAudioTrackCount()
+{
+ uint32 count =3D 0;
+ for (uint16 t =3D 0; t < m_Tracks.size(); t++)
+ {
+ MatroskaTrackInfo ¤tTrack =3D m_Tracks.at(t);
+ if (!strncmp(currentTrack.codecID.c_str(),"A_",2))
+ count++;
+ }
+ return count;
+}
+
+uint32 MatroskaAudioParser::GetAudioTrackIndex(uint32 index)
+{
+ uint32 idx =3D 0;
+ for (uint16 t =3D 0; t < m_Tracks.size(); t++)
+ {
+ MatroskaTrackInfo ¤tTrack =3D m_Tracks.at(t);
+ if (!strncmp(currentTrack.codecID.c_str(),"A_",2))
+ {
+ if(t =3D=3D index)
+ break;
+ idx++;
+ }
+ }
+ return idx;
+}
+
+static bool is_rg_field(const char * name)
+{
+ int m;
+ for (m =3D 0; m < tabsize(rg_fields); m++)
+ {
+ if (!stricmp_utf8(name,rg_fields[m])) return true;
+ }
+ return false;
+}
+
+static bool is_hidden_edition_field(const char * name)
+{
+ for (int i =3D 0; i < tabsize(hidden_edition_field); i++)
+ if (!stricmp_utf8(name, hidden_edition_field[i]))
+ return true;
+ return false;
+}
+
+static bool is_hidden_chapter_field(const char * name)
+{
+ for (int i =3D 0; i < tabsize(hidden_chapter_field); i++)
+ if (!stricmp_utf8(name, hidden_chapter_field[i]))
+ return true;
+ return false;
+}
+
+static const char* matroska_to_foobar2k_edition_tag(const char * name)
+{
+ for (int i =3D 0; i < tabsize(edition_tag_mapping); i++)
+ if (!stricmp_utf8(name, edition_tag_mapping[i][MATROSKA_TAG_IDX]))
+ return edition_tag_mapping[i][FOOBAR2K_TAG_IDX];
+ return name;
+}
+
+static const char* matroska_to_foobar2k_chapter_tag(const char * name)
+{
+ for (int i =3D 0; i < tabsize(chapter_tag_mapping); i++)
+ if (!stricmp_utf8(name, chapter_tag_mapping[i][MATROSKA_TAG_IDX]))
+ return chapter_tag_mapping[i][FOOBAR2K_TAG_IDX];
+ return name;
+}
+
+static void convert_matroska_to_foobar2k_tag(pfc::string_base & p_out, c=
onst char * p_name)
+{
+ pfc::string8 name(p_name);
+ //name.replace_char('_', ' ');
+ p_out =3D name;
+}
+
+static bool IsTagNamed(const MatroskaSimpleTag ¤tSimpleTag, const =
char * name)
+{
+ return !stricmp_utf8(currentSimpleTag.name.GetUTF8().c_str(), name);
+}
+
+static bool IsTagValued(const MatroskaSimpleTag ¤tSimpleTag, const=
char * value)
+{
+ return !strcmp(currentSimpleTag.value.GetUTF8().c_str(), value);
+}
+
+static bool AreTagsNameEqual(const MatroskaSimpleTag &tag1, const Matros=
kaSimpleTag &tag2)
+{
+ return !stricmp_utf8(tag1.name.GetUTF8().c_str(), tag2.name.GetUTF8().c=
_str());
+}
+
+static bool AreTagsValueEqual(const MatroskaSimpleTag &tag1, const Matro=
skaSimpleTag &tag2)
+{
+ return !strcmp(tag1.value.GetUTF8().c_str(), tag2.value.GetUTF8().c_str=
());
+}
+
+static bool AreTagsEqual(const MatroskaSimpleTag &tag1, const MatroskaSi=
mpleTag &tag2)
+{
+ return AreTagsNameEqual(tag1,tag2) && AreTagsValueEqual(tag1,tag2);
+}
+
+const MatroskaSimpleTag* GetTagWithName(MatroskaTagInfo *SimpleTags, con=
st char * name)
+{
+ if(SimpleTags =3D=3D NULL)
+ return NULL;
+
+ for (size_t s =3D 0; s < SimpleTags->tags.size(); s++)
+ {
+ const MatroskaSimpleTag ¤tSimpleTag =3D SimpleTags->tags.at(s); =
=09
+ if(IsTagNamed(currentSimpleTag, name))
+ return ¤tSimpleTag;
+ }
+ return NULL;
+}
+
+bool TagExistsAtEditionLevel(MatroskaTagInfo *TrackTags, const char * na=
me)
+{
+ if(TrackTags =3D=3D NULL)
+ return false;
+
+ for (size_t s =3D 0; s < TrackTags->tags.size(); s++)
+ {
+ const MatroskaSimpleTag ¤tSimpleTag =3D TrackTags->tags.at(s); =09
+ if(IsTagNamed(currentSimpleTag,name))
+ return true;
+ }
+ return false;
+}
+
+bool TagExistsAtChapterLevel(MatroskaTagInfo *ChapterTags, const char * =
name)
+{
+ if(ChapterTags =3D=3D NULL)
+ return false;
+
+ for (size_t s =3D 0; s < ChapterTags->tags.size(); s++)
+ {
+ const MatroskaSimpleTag ¤tSimpleTag =3D ChapterTags->tags.at(s);=
=09
+ if(IsTagNamed(currentSimpleTag,name))
+ return true;
+ }
+ return false;
+}
+
+bool MatroskaAudioParser::AreTagsIdenticalAtAllLevels(const char * name)
+{
+ const MatroskaSimpleTag* ReferenceTag =3D NULL;
+ bool AtLeastOneChapter =3D false;
+
+ for (size_t i =3D 0; i < m_Tags.size(); i++)
+ {
+ MatroskaTagInfo ¤tTags =3D m_Tags.at(i);
+ if(ReferenceTag =3D=3D NULL)
+ {
+ AtLeastOneChapter =3D true;
+ ReferenceTag =3D GetTagWithName(¤tTags, name);
+ } else {
+ const MatroskaSimpleTag* TagToCheck =3D GetTagWithName(¤tTags, =
name);
+ if(TagToCheck && !AreTagsValueEqual(*ReferenceTag,*TagToCheck))
+ return false; =09
+ }
+ }
+ return AtLeastOneChapter;
+}
+
+bool MatroskaAudioParser::AreTagsIdenticalAtEditionLevel(const char * na=
me)
+{
+ const MatroskaSimpleTag* ReferenceTag =3D NULL;
+ bool AtLeastOneChapter =3D false;
+
+ for (size_t i =3D 0; i < m_Tags.size(); i++)
+ {
+ MatroskaTagInfo ¤tTags =3D m_Tags.at(i);
+ if (currentTags.targetChapterUID =3D=3D 0)
+ {
+ // Chapter tags
+ if(ReferenceTag =3D=3D NULL)
+ {
+ AtLeastOneChapter =3D true;
+ ReferenceTag =3D GetTagWithName(¤tTags, name);
+ } else {
+ const MatroskaSimpleTag* TagToCheck =3D GetTagWithName(¤tTags,=
name);
+ if(TagToCheck && !AreTagsValueEqual(*ReferenceTag,*TagToCheck))
+ return false; =09
+ }
+ }
+ }
+ return AtLeastOneChapter;
+}
+
+bool MatroskaAudioParser::AreTagsIdenticalAtChapterLevel(const char * na=
me)
+{
+ const MatroskaSimpleTag* ReferenceTag =3D NULL;
+ bool AtLeastOneChapter =3D false;
+
+ for (size_t i =3D 0; i < m_Tags.size(); i++)
+ {
+ MatroskaTagInfo ¤tTags =3D m_Tags.at(i);
+ if (currentTags.targetChapterUID !=3D 0)
+ {
+ // Chapter tags
+ if(ReferenceTag =3D=3D NULL)
+ {
+ AtLeastOneChapter =3D true;
+ ReferenceTag =3D GetTagWithName(¤tTags, name);
+ } else {
+ const MatroskaSimpleTag* TagToCheck =3D GetTagWithName(¤tTags,=
name);
+ if(TagToCheck && !AreTagsValueEqual(*ReferenceTag,*TagToCheck))
+ return false; =09
+ }
+ }
+ }
+ return AtLeastOneChapter;
+}
+
+void MatroskaAudioParser::SetAlbumTags(file_info & info,
+ MatroskaTagInfo* AlbumTags,
+ MatroskaTagInfo* TrackTags)
+{
+ if (AlbumTags =3D=3D NULL)
+ return;
+
+ for (size_t s =3D 0; s < AlbumTags->tags.size(); s++)
+ {
+ MatroskaSimpleTag &simpleTag =3D AlbumTags->tags.at(s);
+ =09
+ if (is_rg_field(simpleTag.name.GetUTF8().c_str()))
+ {
+ if(IsTagNamed(simpleTag, "REPLAYGAIN_GAIN"))
+ {
+ info.info_set_replaygain("replaygain_album_gain", simpleTag.value.Ge=
tUTF8().c_str());
+ if (TrackTags =3D=3D NULL) info.info_set_replaygain("replaygain_trac=
k_gain", simpleTag.value.GetUTF8().c_str());
+ } else if(IsTagNamed(simpleTag, "REPLAYGAIN_PEAK")) {
+ info.info_set_replaygain("replaygain_album_peak", simpleTag.value.Ge=
tUTF8().c_str());
+ if (TrackTags =3D=3D NULL) info.info_set_replaygain("replaygain_trac=
k_peak", simpleTag.value.GetUTF8().c_str());
+ }
+ }
+ else if (is_hidden_edition_field(simpleTag.name.GetUTF8().c_str()))
+ {
+ // Ignored tag, will be rewrited later
+ simpleTag.hidden =3D true;
+ }
+ else if(IsTagNamed(simpleTag,"TITLE"))
+ {
+ // Special case for Edition/TITLE
+ if(TagExistsAtChapterLevel(TrackTags, "ALBUM"))
+ {
+ info.meta_add("ALBUM TITLE", simpleTag.value.GetUTF8().c_str());
+ } else {
+ info.meta_add("ALBUM", simpleTag.value.GetUTF8().c_str());
+ }
+ }
+ /*
+ else if(IsTagNamed(simpleTag,"SUBTITLE"))
+ {
+ // Special case for Edition/SUBTITLE
+ if(TagExistsAtChapterLevel(TrackTags, "SUBALBUM"))
+ {
+ info.meta_add("ALBUM SUBTITLE", simpleTag.value.GetUTF8().c_str());
+ } else {
+ info.meta_add("SUBALBUM", simpleTag.value.GetUTF8().c_str());
+ }
+ }
+ */
+ else if (IsTagNamed(simpleTag, "DISCID") ||
+ IsTagNamed(simpleTag, "CATALOG_NUMBER") ||
+ IsTagNamed(simpleTag, "TOTAL_PARTS") ||
+ IsTagNamed(simpleTag, "PART_NUMBER") ||
+ IsTagNamed(simpleTag, "TOTAL_DISCS"))
+ {
+ info.meta_add(matroska_to_foobar2k_edition_tag(simpleTag.name.GetUTF8=
().c_str()), simpleTag.value.GetUTF8().c_str());
+ }
+ /*else if (IsTagNamed(simpleTag,"COMMENTS"))
+ {
+ info.meta_add("ALBUM COMMENT", simpleTag.value.GetUTF8().c_str());
+ }*/
+ else if((!AreTagsIdenticalAtAllLevels(simpleTag.name.GetUTF8().c_str()=
))
+ || (!TagExistsAtChapterLevel(TrackTags, simpleTag.name.GetUTF8().c_st=
r())))
+ {
+ // Prefix tag with "ALBUM "
+ char newTagName[255] =3D "ALBUM ";
+ strncat(newTagName, matroska_to_foobar2k_edition_tag(simpleTag.name.G=
etUTF8().c_str()),255);
+ pfc::string8 new_tagname;
+ convert_matroska_to_foobar2k_tag(new_tagname, newTagName);
+ info.meta_add(new_tagname, simpleTag.value.GetUTF8().c_str());
+ }
+ else=20
+ {
+ // Ignored tag, will be rewrited later
+ simpleTag.hidden =3D true;
+ }
+ }
+}
+
+void MatroskaAudioParser::SetTrackTags(file_info &info, MatroskaTagInfo*=
TrackTags)
+{
+ if(TrackTags =3D=3D NULL)
+ return;
+
+ for (size_t s =3D 0; s < TrackTags->tags.size(); s++)
+ {
+ MatroskaSimpleTag &simpleTag =3D TrackTags->tags.at(s);
+ =09
+ if (is_rg_field(simpleTag.name.GetUTF8().c_str()))
+ {
+ if(IsTagNamed(simpleTag, "REPLAYGAIN_GAIN"))
+ {
+ info.info_set_replaygain("replaygain_track_gain", simpleTag.value.Ge=
tUTF8().c_str());
+ } else if(IsTagNamed(simpleTag, "REPLAYGAIN_PEAK")) {
+ info.info_set_replaygain("replaygain_track_peak", simpleTag.value.Ge=
tUTF8().c_str());
+ }
+ }
+ else if (is_hidden_chapter_field(simpleTag.name.GetUTF8().c_str()))
+ {
+ // Ignore tag
+ simpleTag.hidden =3D true;
+ }
+ /*else if(IsTagNamed(simpleTag,"COMMENTS"))
+ {
+ info.meta_add("COMMENT", simpleTag.value.GetUTF8().c_str());
+ }*/
+ else if(IsTagNamed(simpleTag,"ALBUM"))
+ {
+ if(!TagExistsAtEditionLevel(TrackTags, "TITLE") && AreTagsIdenticalAt=
ChapterLevel("ALBUM")) {
+ info.meta_add("ALBUM", simpleTag.value.GetUTF8().c_str());
+ } else {
+ info.meta_add("ORIGINAL ALBUM", simpleTag.value.GetUTF8().c_str());
+ }
+ }
+ else
+ {
+ pfc::string8 new_tagname;
+ convert_matroska_to_foobar2k_tag(new_tagname, matroska_to_fo=
obar2k_chapter_tag(simpleTag.name.GetUTF8().c_str()));
+ info.meta_add(new_tagname, simpleTag.value.GetUTF8().c_str());=09
+ }
+ }
+}
+
+bool MatroskaAudioParser::SetFB2KInfo(file_info &info, t_uint32 p_subson=
g)
+{
+ if (m_MuxingApp.length() > 0)
+ info.info_set("MUXING_APP", m_MuxingApp.GetUTF8().c_str());
+ if (m_WritingApp.length() > 0)
+ info.info_set("WRITING_APP", m_WritingApp.GetUTF8().c_str());
+ if (m_FileTitle.length() > 0)
+ info.info_set("TITLE", m_FileTitle.GetUTF8().c_str());
+
+ // pregap
+ try {
+ if (m_Chapters.at(p_subsong).subChapters.size() > 1) {
+ double pregap =3D TimecodeToSeconds(m_Chapters.at(p_subsong).subChapt=
ers.at(1).timeStart - m_Chapters.at(p_subsong).subChapters.at(0).timeStar=
t);
+ info.info_set("pregap", cuesheet_format_index_time(pregap));
+ }
+ } catch (std::out_of_range & e) {
+ }
+
+ MatroskaTagInfo *TrackTags =3D FindTagWithTrackUID(m_Tracks.at(m_Curren=
tTrackNo).trackUID);
+ MatroskaTagInfo *ChapterTags =3D NULL;
+ if(m_CurrentChapter !=3D NULL)
+ {
+ ChapterTags =3D FindTagWithChapterUID(m_CurrentChapter->chapterUID,
+ m_Tracks.at(m_CurrentTrackNo).trackUID);
+ }
+
+ MatroskaTagInfo *EditionTags =3D NULL;
+ if(m_CurrentEdition !=3D NULL)
+ {
+ EditionTags =3D FindTagWithEditionUID(m_CurrentEdition->editionUID,
+ m_Tracks.at(m_CurrentTrackNo).trackUID);
+ }
+ if(EditionTags !=3D NULL && EditionTags->targetTypeValue =3D=3D 50)
+ {
+ SetAlbumTags(info, EditionTags, ChapterTags);
+ }
+
+ if(TrackTags !=3D NULL)
+ {
+ if(TrackTags->targetTypeValue =3D=3D 50)
+ {
+ SetAlbumTags(info, TrackTags, ChapterTags);
+ SetTrackTags(info, ChapterTags);
+ } else if (TrackTags->targetTypeValue =3D=3D 30) {
+ SetTrackTags(info, TrackTags);
+ }
+ }
+=09
+ // Last chance,
+ if(m_CurrentChapter !=3D NULL)
+ {
+ // If TITLE tag is empty we get it from the chapter name
+ if ( (m_CurrentChapter->display.size() > 0) &&
+ ((info.meta_get("TITLE", 0) =3D=3D NULL) ||
+ (strlen(info.meta_get("TITLE", 0)) =3D=3D 0) ) )
+ {
+ info.meta_set("TITLE", m_CurrentChapter->display.at(0).string.GetUTF8=
().c_str());
+ }
+ if ((info.meta_get("TRACKNUMBER", 0) =3D=3D NULL) || (strlen(info.meta=
_get("TRACKNUMBER", 0)) =3D=3D 0))
+ {
+ //char trackNumberString[32];
+ pfc::string8 trackNumberString;
+#ifdef MULTITRACK =09
+ //wsprintf((LPWSTR)trackNumberString, (LPCWSTR)"%d",
+ // (p_subsong % m_Chapters.size()) +1);
+ trackNumberString << ((p_subsong % m_Chapters.size()) +1);
+#else
+ wsprintf(trackNumberString, "%d",p_subsong+1);
+#endif
+ info.meta_set("TRACKNUMBER", trackNumberString);
+ }
+ if ((info.meta_get("ALBUM", 0) =3D=3D NULL) || (strlen(info.meta_get("=
ALBUM", 0)) =3D=3D 0))
+ {
+ if(m_FileTitle.length() > 0)
+ info.meta_set("ALBUM", m_FileTitle.GetUTF8().c_str());
+ }
+ }
+
+ return true;
+};
+
+void MatroskaAudioParser::MarkHiddenTags()
+{
+ // We call MatroskaAudioParser::SetFB2KInfo with a dummy file_info that
+ // do nothing, so we will only mark hidden tags.
+ // Hidden tag will be copied to keep track of them.
+ // This is needed cause tag are read and written in 2 different instanc=
es
+ file_info_impl info;
+ SetFB2KInfo(info, 0);
+};
+
+void MatroskaAudioParser::SetCurrentTrack(uint32 newTrackNo)
+{
+ m_CurrentTrackNo =3D newTrackNo;
+ // Clear the current queue (we are changing tracks)
+ while (!m_Queue.empty())
+ m_Queue.pop();
+};
+
+void MatroskaAudioParser::SetSubSong(int subsong)
+{
+ // As we don't (yet?) use several Editions, select the first (default) =
one as the current one.
+ m_CurrentEdition =3D NULL;
+ m_CurrentChapter =3D NULL;
+ if(m_Editions.size() > 0)
+ m_CurrentEdition =3D &m_Editions.at(0);
+ if (m_Chapters.size() > subsong)
+ m_CurrentChapter =3D &m_Chapters.at(subsong);
+=09
+};
+
+int32 MatroskaAudioParser::GetAvgBitrate()=20
+{=20
+ double ret =3D 0;
+ ret =3D static_cast<double>(int64(m_FileSize)) / 1024;
+ ret =3D ret / (m_Duration / 1000000000.0);
+ ret =3D ret * 8;
+ return static_cast<int32>(ret);
+};
+
+bool MatroskaAudioParser::skip_frames_until(double destination,unsigned =
& frames,double & last_timecode_delta,unsigned hint_samplerate)
+{
+ unsigned done =3D 0;
+ unsigned last_laced =3D 0;
+
+ double last_time;
+ {
+ uint64 last_timecode =3D get_current_frame_timecode();
+ if (last_timecode =3D=3D (uint64)(-1)) return false;
+ last_time =3D TimecodeToSeconds(last_timecode,hint_samplerate);
+ }
+
+ for(;;)
+ {
+ while (!m_Queue.empty()) {
+ MatroskaAudioFrame *currentPacket =3D m_Queue.front();
+ double packet_time =3D TimecodeToSeconds(currentPacket->timecode,hint=
_samplerate);
+ if (packet_time > destination)
+ {
+ if (done=3D=3D0) return false;
+ last_timecode_delta =3D destination - last_time;
+ frames =3D done - last_laced;
+ return true;
+ }
+ last_time =3D packet_time;
+ done +=3D (last_laced =3D currentPacket->dataBuffer.size());
+ //delete currentPacket;
+ _DELETE(currentPacket);
+ m_Queue.pop();
+ }
+ if (FillQueue()!=3D0)
+ return false;
+ }
+}
+
+
+void MatroskaAudioParser::flush_queue()
+{
+ while (!m_Queue.empty()) {
+ MatroskaAudioFrame *currentPacket =3D m_Queue.front();
+ //delete currentPacket;
+ _DELETE(currentPacket);
+ m_Queue.pop();
+ }
+}
+
+uint64 MatroskaAudioParser::get_current_frame_timecode()
+{
+ if (m_Queue.empty())
+ {
+ if (FillQueue()!=3D0) return -1;
+ if (m_Queue.empty()) return -1;
+ }
+ return m_Queue.front()->timecode;
+}
+
+bool MatroskaAudioParser::Seek(double seconds,unsigned & frames_to_skip,=
double & time_to_skip,unsigned samplerate_hint)
+{
+ int64 ret =3D 0;
+
+ if (m_CurrentChapter !=3D NULL) {
+ seconds +=3D (double)(int64)m_CurrentChapter->timeStart / 1000000000; =
// ns -> seconds
+ }
+
+ uint64 seekToTimecode =3D SecondsToTimecode(seconds);
+=09
+ flush_queue();
+ m_CurrentTimecode =3D seekToTimecode;
+
+ if (!skip_frames_until(seconds,frames_to_skip,time_to_skip,samplerate_h=
int)) return false;
+
+ flush_queue();
+ m_CurrentTimecode =3D seekToTimecode;
+ if (FillQueue()!=3D0) return false;
+ return true;
+
+};
+
+MatroskaAudioFrame * MatroskaAudioParser::ReadSingleFrame()
+{
+ for(;;)
+ {
+ if (!m_Queue.empty()) {
+ MatroskaAudioFrame *newFrame =3D m_Queue.front(); =09
+ m_Queue.pop();
+ return newFrame;
+ } else {
+ if (FillQueue()!=3D0)
+ return 0;
+ }
+ }
+};
+
+MatroskaAudioFrame * MatroskaAudioParser::ReadFirstFrame()
+{
+ m_CurrentTimecode =3D 0;
+ return ReadSingleFrame();
+};
+
+typedef boost::shared_ptr<EbmlId> EbmlIdPtr;
+
+void MatroskaAudioParser::Parse_MetaSeek(ElementPtr metaSeekElement, boo=
l bInfoOnly)=20
+{
+ TIMER;
+ uint64 lastSeekPos =3D 0;
+ uint64 endSeekPos =3D 0;
+ ElementPtr l2;
+ ElementPtr l3;
+ ElementPtr NullElement;
+ int UpperElementLevel =3D 0;
+
+ if (metaSeekElement =3D=3D NullElement)
+ return;
+
+ l2 =3D ElementPtr(m_InputStream.FindNextElement(metaSeekElement->Generi=
c().Context, UpperElementLevel, 0xFFFFFFFFFFFFFFFFL, true, 1));
+ while (l2 !=3D NullElement) {
+ if (UpperElementLevel > 0) {
+ break;
+ }
+ if (UpperElementLevel < 0) {
+ UpperElementLevel =3D 0;
+ }
+ if (bInfoOnly) {
+ if (m_ClusterIndex.size() >=3D 1) break;
+ }
+
+ if (EbmlId(*l2) =3D=3D KaxSeek::ClassInfos.GlobalId) {
+ //Wow we found the SeekEntries, time to speed up reading ;)
+ l3 =3D ElementPtr(m_InputStream.FindNextElement(l2->Generic().Context=
, UpperElementLevel, 0xFFFFFFFFFFFFFFFFL, true, 1));
+
+ EbmlIdPtr id;
+ while (l3 !=3D NullElement) {
+ if (UpperElementLevel > 0) {
+ break;
+ }
+ if (UpperElementLevel < 0) {
+ UpperElementLevel =3D 0;
+ }
+ if (bInfoOnly) {
+ if (m_ClusterIndex.size() >=3D 1) break;
+ }
+
+ if (EbmlId(*l3) =3D=3D KaxSeekID::ClassInfos.GlobalId) {
+ binary *b =3D NULL;
+ uint16 s =3D 0;
+ KaxSeekID &seek_id =3D static_cast<KaxSeekID &>(*l3);
+ seek_id.ReadData(m_InputStream.I_O(), SCOPE_ALL_DATA);
+ b =3D seek_id.GetBuffer();
+ s =3D (uint16)seek_id.GetSize();
+ id.reset();
+ id =3D EbmlIdPtr(new EbmlId(b, s));
+
+ } else if (EbmlId(*l3) =3D=3D KaxSeekPosition::ClassInfos.GlobalId) =
{
+ KaxSeekPosition &seek_pos =3D static_cast<KaxSeekPosition &>(*l3);
+ seek_pos.ReadData(m_InputStream.I_O()); =09
+ lastSeekPos =3D uint64(seek_pos);
+ if (endSeekPos < lastSeekPos)
+ endSeekPos =3D uint64(seek_pos);
+
+ if (*id =3D=3D KaxCluster::ClassInfos.GlobalId) {
+ //NOTE1("Found Cluster Seek Entry Postion: %u", (unsigned long)las=
tSeekPos);
+ //uint64 orig_pos =3D inputFile.getFilePointer();
+ //MatroskaMetaSeekClusterEntry newCluster;
+ cluster_entry_ptr newCluster(new MatroskaMetaSee=
kClusterEntry());
+ newCluster->timecode =3D MAX_UINT64;
+ newCluster->filePos =3D static_cast<KaxSegment *>(m_ElementLevel0.=
get())->GetGlobalPosition(lastSeekPos);
+ m_ClusterIndex.push_back(newCluster);
+
+ } else if (*id =3D=3D KaxSeekHead::ClassInfos.GlobalId) {
+ NOTE1("Found MetaSeek Seek Entry Postion: %u", (unsigned long)last=
SeekPos);
+ uint64 orig_pos =3D m_IOCallback.getFilePointer();
+ m_IOCallback.setFilePointer(static_cast<KaxSegment *>(m_ElementLev=
el0.get())->GetGlobalPosition(lastSeekPos));
+ =09
+ ElementPtr levelUnknown =3D ElementPtr(m_InputStream.FindNextID(Ka=
xSeekHead::ClassInfos, 0xFFFFFFFFFFFFFFFFL)); =09
+ Parse_MetaSeek(levelUnknown, bInfoOnly);
+
+ m_IOCallback.setFilePointer(orig_pos);
+ }
+
+ } else {
+
+ }
+ l3->SkipData(m_InputStream, l3->Generic().Context);
+ l3 =3D ElementPtr(m_InputStream.FindNextElement(l2->Generic().Contex=
t, UpperElementLevel, 0xFFFFFFFFFFFFFFFFL, true, 1));
+ }
+ } else {
+
+ }
+
+ if (UpperElementLevel > 0) { // we're coming from l3
+ UpperElementLevel--;
+ l2 =3D l3;
+ if (UpperElementLevel > 0)
+ break;
+
+ } else {
+ l2->SkipData(m_InputStream, l2->Generic().Context);
+ l2 =3D ElementPtr(m_InputStream.FindNextElement(metaSeekElement->Gene=
ric().Context, UpperElementLevel, 0xFFFFFFFFFFFFFFFFL, true, 1));
+ }
+ }
+ _TIMER("Parse_MetaSeek");
+}
+
+#define IS_ELEMENT_ID(__x__) (Element->Generic().GlobalId =3D=3D __x__::=
ClassInfos.GlobalId)
+
+void MatroskaAudioParser::Parse_Chapter_Atom(KaxChapterAtom *ChapterAtom=
)
+{
+ Parse_Chapter_Atom(ChapterAtom, m_Chapters);
+}
+
+void MatroskaAudioParser::Parse_Chapter_Atom(KaxChapterAtom *ChapterAtom=
, std::vector<MatroskaChapterInfo> &p_chapters)
+{
+ int i, j;
+ EbmlElement *Element =3D NULL;
+ MatroskaChapterInfo newChapter;
+
+ NOTE("New chapter");
+
+ for (i =3D 0; i < ChapterAtom->ListSize(); i++)
+ {=09
+ Element =3D (*ChapterAtom)[i];
+ =09
+ if (IS_ELEMENT_ID(KaxChapterUID))
+ {
+ newChapter.chapterUID =3D uint64(*static_cast<EbmlUInteger *>(Element=
));
+ NOTE1("- UID : %I64d", newChapter.chapterUID);
+ }
+ else if(IS_ELEMENT_ID(KaxChapterTimeStart))
+ { =09
+ newChapter.timeStart =3D uint64(*static_cast<EbmlUInteger *>(Element)=
); // it's in ns
+ NOTE1("- TimeStart : %I64d", newChapter.timeStart);
+ }
+ else if(IS_ELEMENT_ID(KaxChapterTimeEnd))
+ {
+ newChapter.timeEnd =3D uint64(*static_cast<EbmlUInteger *>(Element));=
// it's in ns
+ NOTE1("- TimeEnd : %I64d", newChapter.timeEnd);
+ }
+ else if(IS_ELEMENT_ID(KaxChapterTrack))
+ {
+ KaxChapterTrack *ChapterTrack =3D (KaxChapterTrack *)Element;
+ =09
+ for (j =3D 0; j < ChapterTrack->ListSize(); j++)
+ {
+ Element =3D (*ChapterTrack)[j];
+ if(IS_ELEMENT_ID(KaxChapterTrackNumber))
+ {
+ uint64 chapTrackNo =3D uint64(*static_cast<EbmlUInteger *>(Element)=
);
+ newChapter.tracks.push_back(chapTrackNo);
+ NOTE1("- TrackNumber : %I64d", chapTrackNo);
+ }
+ else if(IS_ELEMENT_ID(KaxChapterAtom))
+ { =09
+ // Ignore sub-chapter
+ NOTE("ignore sub-chapter");
+ //Parse_Chapter_Atom((KaxChapterAtom *)Element);
+ }
+ }
+ }
+ else if(IS_ELEMENT_ID(KaxChapterDisplay))
+ {
+ // A new chapter display string+lang+country
+ MatroskaChapterDisplayInfo newChapterDisplay; =09
+ KaxChapterDisplay *ChapterDisplay =3D (KaxChapterDisplay *)Element;
+ =09
+ for (j =3D 0; j < ChapterDisplay->ListSize(); j++) {
+ Element =3D (*ChapterDisplay)[j];
+ if(IS_ELEMENT_ID(KaxChapterString))
+ {
+ newChapterDisplay.string =3D UTFstring(*static_cast <EbmlUnicodeStr=
ing *>(Element)).c_str();
+ NOTE1("- String : %s", newChapterDisplay.string.GetUTF8().c_str());
+ }
+ else if(IS_ELEMENT_ID(KaxChapterAtom))
+ { =09
+ // Ignore sub-chapter
+ NOTE("ignore sub-chapter");
+ //Parse_Chapter_Atom((KaxChapterAtom *)Element);
+ }
+ }
+ // A emtpy string in a chapter display string is usless
+ if (newChapterDisplay.string.length() > 0)
+ newChapter.display.push_back(newChapterDisplay);
+ }
+ else if(IS_ELEMENT_ID(KaxChapterAtom))
+ {
+ /*
+ // Ignore sub-chapter
+ NOTE("ignore sub-chapter");
+ //Parse_Chapter_Atom((KaxChapterAtom *)Element);
+ */
+ Parse_Chapter_Atom((KaxChapterAtom *)Element, newChapter.subChapters)=
;
+ }
+ }
+ if ((newChapter.chapterUID !=3D 0) && !FindChapterUID(newChapter.chapte=
rUID))
+ p_chapters.push_back(newChapter);
+}
+
+void MatroskaAudioParser::Parse_Chapters(KaxChapters *chaptersElement)
+{
+ int i, j;=09
+ EbmlElement *Element =3D NULL;=09
+ int UpperEltFound =3D 0;
+
+ NOTE("New edition");
+
+ if (chaptersElement =3D=3D NULL)
+ return;
+
+ chaptersElement->Read(m_InputStream, KaxChapters::ClassInfos.Context,
+ UpperEltFound, Element, true);
+
+ for (i =3D 0; i < chaptersElement->ListSize(); i++)
+ {
+ Element =3D (*chaptersElement)[i];
+ if(IS_ELEMENT_ID(KaxEditionEntry))
+ {
+ MatroskaEditionInfo newEdition;
+ KaxEditionEntry *edition =3D (KaxEditionEntry *)Element;
+ for (j =3D 0; j < edition->ListSize(); j++)
+ {
+ Element =3D (*edition)[j];
+ if(IS_ELEMENT_ID(KaxEditionUID))
+ {
+ // A new edition :)
+ newEdition.editionUID =3D uint64(*static_cast<EbmlUInteger *>(Eleme=
nt));
+ NOTE1("- UID : %I64d", newEdition.editionUID);
+ }
+ else if(IS_ELEMENT_ID(KaxChapterAtom))
+ {
+ // A new chapter :)
+ Parse_Chapter_Atom((KaxChapterAtom *)Element);
+ }
+ }
+ if ((newEdition.editionUID !=3D 0) && !FindEditionUID(newEdition.edit=
ionUID))
+ m_Editions.push_back(newEdition);
+ }
+ }
+ FixChapterEndTimes();
+}
+
+void MatroskaAudioParser::Parse_Tags(KaxTags *tagsElement)
+{
+ int i, j, k;
+ EbmlElement *Element =3D NULL;
+ int UpperEltFound =3D 0;
+
+ if (tagsElement =3D=3D NULL)
+ return;
+
+ m_TagPos =3D tagsElement->GetElementPosition();
+ m_TagSize =3D tagsElement->GetSize();
+
+ tagsElement->Read(m_InputStream, KaxTags::ClassInfos.Context, UpperEltF=
ound, Element, true);
+
+ for (i =3D 0; i < tagsElement->ListSize(); i++)
+ {
+ Element =3D (*tagsElement)[i];
+ if(IS_ELEMENT_ID(KaxTag))
+ {
+ MatroskaTagInfo newTag;
+ newTag.targetTypeValue =3D 50;
+ KaxTag *tagElement =3D (KaxTag*)Element;
+ NOTE("New Tag");
+ for (j =3D 0; j < tagElement->ListSize(); j++)
+ {
+ Element =3D (*tagElement)[j];
+ if(IS_ELEMENT_ID(KaxTagTargets))
+ {
+ KaxTagTargets *tagTargetsElement =3D (KaxTagTargets*)Element; =09
+ for (k =3D 0; k < tagTargetsElement->ListSize(); k++)
+ {
+ Element =3D (*tagTargetsElement)[k];
+ if(IS_ELEMENT_ID(KaxTagTrackUID))
+ {
+ newTag.targetTrackUID =3D uint64(*static_cast<EbmlUInteger *>(Ele=
ment));
+ NOTE1("- TargetTrackUID : %I64d", newTag.targetTrackUID);
+ }
+ else if(IS_ELEMENT_ID(KaxTagEditionUID))
+ {
+ newTag.targetEditionUID =3D uint64(*static_cast<EbmlUInteger *>(E=
lement));
+ NOTE1("- TargetEditionUID : %I64d", newTag.targetEditionUID);
+ }
+ else if(IS_ELEMENT_ID(KaxTagChapterUID))
+ {
+ newTag.targetChapterUID =3D uint64(*static_cast<EbmlUInteger *>(E=
lement));
+ NOTE1("- TargetChapterUIDUID : %I64d", newTag.targetChapterUID);
+ }
+ else if(IS_ELEMENT_ID(KaxTagAttachmentUID))
+ {
+ newTag.targetAttachmentUID =3D uint64(*static_cast<EbmlUInteger *=
>(Element));
+ NOTE1("- TargetAttachmentUID : %I64d", newTag.targetAttachmentUID=
);
+ }
+ else if(IS_ELEMENT_ID(KaxTagTargetTypeValue))
+ {
+ newTag.targetTypeValue =3D uint32(*static_cast<EbmlUInteger *>(El=
ement));
+ NOTE1("- TargetTypeValue : %d", newTag.targetTypeValue);
+ }
+ else if(IS_ELEMENT_ID(KaxTagTargetType))
+ {
+ newTag.targetType =3D std::string(*static_cast<KaxTagTargetType *=
>(Element));
+ NOTE1("- TargetType : %s", newTag.targetType.c_str());
+ }
+ }
+ }
+ else if(IS_ELEMENT_ID(KaxTagSimple))
+ {
+ MatroskaSimpleTag newSimpleTag;
+ KaxTagSimple *tagSimpleElement =3D (KaxTagSimple*)Element;
+ NOTE("New SimpleTag");
+ for (k =3D 0; k < tagSimpleElement->ListSize(); k++)
+ {
+ Element =3D (*tagSimpleElement)[k];
+ if(IS_ELEMENT_ID(KaxTagName))
+ {
+ newSimpleTag.name =3D wcsupr((wchar_t *)UTFstring(*static_cast <E=
bmlUnicodeString *>(Element)).c_str());
+ NOTE1("- Name : %s", newSimpleTag.name.GetUTF8().c_str());
+ }
+ else if(IS_ELEMENT_ID(KaxTagString))
+ {
+ newSimpleTag.value =3D UTFstring(*static_cast <EbmlUnicodeString =
*>(Element)).c_str();
+ NOTE1("- Value : %s", newSimpleTag.value.GetUTF8().c_str());
+ }
+ else if(IS_ELEMENT_ID(KaxTagDefault))
+ {
+ newSimpleTag.defaultFlag =3D uint32(*static_cast<EbmlUInteger *>(=
Element));
+ NOTE1("- TargetTypeValue : %d", newSimpleTag.default);
+ }
+ else if(IS_ELEMENT_ID(KaxTagLangue))
+ {
+ newSimpleTag.language =3D std::string(*static_cast <KaxTagLangue =
*>(Element));
+ NOTE1("- Language : %s", newSimpleTag.language.c_str());
+ }
+ else if(IS_ELEMENT_ID(KaxTagSimple))
+ {
+ // ignore sub-tags
+ // if we want "sub-tags" put this loop in another
+ // function and call it recursively
+ }
+ }
+ newTag.tags.push_back(newSimpleTag);
+ }
+ }
+ m_Tags.push_back(newTag);
+ }
+ }
+};
+
+int MatroskaAudioParser::FillQueue()=20
+{
+ flush_queue();
+
+ NOTE("MatroskaAudioParser::FillQueue()");
+
+ int UpperElementLevel =3D 0;
+ bool bAllowDummy =3D false;
+ // Elements for different levels
+ ElementPtr ElementLevel1;
+ ElementPtr ElementLevel2;
+ ElementPtr ElementLevel3;
+ ElementPtr ElementLevel4;
+ ElementPtr ElementLevel5;
+ ElementPtr NullElement;
+ //m_framebuffer.set_size(0);
+
+ if (m_IOCallback.seekable()) {
+ cluster_entry_ptr currentCluster =3D FindCluster(m_CurrentTimecode);
+ if (currentCluster.get() =3D=3D NULL)
+ return 2;
+ int64 clusterFilePos =3D currentCluster->filePos;
+
+ //console::info(uStringPrintf("cluster %d", currentCluster->clusterNo)=
);
+
+ m_IOCallback.setFilePointer(clusterFilePos);
+ // Find the element data
+ ElementLevel1 =3D ElementPtr(m_InputStream.FindNextID(KaxCluster::Clas=
sInfos, 0xFFFFFFFFFFFFFFFFL));
+ if (ElementLevel1 =3D=3D NullElement)
+ return 1;
+
+ if (EbmlId(*ElementLevel1) =3D=3D KaxCluster::ClassInfos.GlobalId) {
+ KaxCluster *SegmentCluster =3D static_cast<KaxCluster *>(ElementLevel=
1.get());
+ uint32 ClusterTimecode =3D 0;
+ MatroskaAudioFrame *prevFrame =3D NULL;
+
+ // read blocks and discard the ones we don't care about
+ ElementLevel2 =3D ElementPtr(m_InputStream.FindNextElement(ElementLev=
el1->Generic().Context, UpperElementLevel, ElementLevel1->ElementSize(), =
bAllowDummy));
+ while (ElementLevel2 !=3D NullElement) {
+ if (UpperElementLevel > 0) {
+ break;
+ }
+ if (UpperElementLevel < 0) {
+ UpperElementLevel =3D 0;
+ }
+ if (EbmlId(*ElementLevel2) =3D=3D KaxClusterTimecode::ClassInfos.Glo=
balId) { =09
+ KaxClusterTimecode & ClusterTime =3D *static_cast<KaxClusterTimecod=
e*>(ElementLevel2.get());
+ ClusterTime.ReadData(m_InputStream.I_O());
+ ClusterTimecode =3D uint32(ClusterTime);
+ currentCluster->timecode =3D ClusterTimecode * m_TimecodeScale;
+ SegmentCluster->InitTimecode(ClusterTimecode, m_TimecodeScale);
+ } else if (EbmlId(*ElementLevel2) =3D=3D KaxBlockGroup::ClassInfos.=
GlobalId) {
+ //KaxBlockGroup & aBlockGroup =3D *static_cast<KaxBlockGroup*>(Elem=
entLevel2);
+
+ // Create a new frame
+ MatroskaAudioFrame *newFrame =3D new MatroskaAudioFrame;
+
+ ElementLevel3 =3D ElementPtr(m_InputStream.FindNextElement(ElementL=
evel2->Generic().Context, UpperElementLevel, ElementLevel2->ElementSize()=
, bAllowDummy));
+ while (ElementLevel3 !=3D NullElement) {
+ if (UpperElementLevel > 0) {
+ break;
+ }
+ if (UpperElementLevel < 0) {
+ UpperElementLevel =3D 0;
+ }
+ if (EbmlId(*ElementLevel3) =3D=3D KaxBlock::ClassInfos.GlobalId) {=
=09
+ KaxBlock & DataBlock =3D *static_cast<KaxBlock*>(ElementLevel3.ge=
t()); =09
+ DataBlock.ReadData(m_InputStream.I_O());
+ DataBlock.SetParent(*SegmentCluster);
+
+ //NOTE4("Track # %u / %u frame%s / Timecode %I64d", DataBlock.Tra=
ckNum(), DataBlock.NumberFrames(), (DataBlock.NumberFrames() > 1)?"s":"",=
DataBlock.GlobalTimecode()/m_TimecodeScale);
+ if (DataBlock.TrackNum() =3D=3D m_Tracks.at(m_CurrentTrackNo).tra=
ckNumber) { =09
+ newFrame->timecode =3D DataBlock.GlobalTimecode();
+
+ if (DataBlock.NumberFrames() > 1) {=09
+ // The evil lacing has been used
+ newFrame->duration =3D m_Tracks.at(m_CurrentTrackNo).defaultDur=
ation * DataBlock.NumberFrames();
+
+ newFrame->dataBuffer.resize(DataBlock.NumberFrames());
+ for (uint32 f =3D 0; f < DataBlock.NumberFrames(); f++) {
+ DataBuffer &buffer =3D DataBlock.GetBuffer(f);
+ newFrame->dataBuffer[f].resize(buffer.Size()); =09
+ memcpy(&newFrame->dataBuffer[f][0], buffer.Buffer(), buffer.Si=
ze());
+ }
+ } else {
+ // Non-lacing block =09
+ newFrame->duration =3D m_Tracks.at(m_CurrentTrackNo).defaultDur=
ation;
+
+ newFrame->dataBuffer.resize(1);
+ DataBuffer &buffer =3D DataBlock.GetBuffer(0);
+ newFrame->dataBuffer.at(0).resize(buffer.Size());
+ =20
+ memcpy(&newFrame->dataBuffer.at(0).at(0), buffer.Buffer(), buff=
er.Size());
+ }
+ } else {
+ //newFrame->timecode =3D MAX_UINT64;
+ }
+ /*
+ } else if (EbmlId(*ElementLevel3) =3D=3D KaxReferenceBlock::ClassI=
nfos.GlobalId) {
+ KaxReferenceBlock & RefTime =3D *static_cast<KaxReferenceBlock*>(=
ElementLevel3);
+ RefTime.ReadData(m_InputStream.I_O());
+ newFrame->frameReferences.push_back(int32(RefTime));
+ //wxLogDebug(" Reference frame at scaled (%d) timecode %ld\n", i=
nt32(RefTime), int32(int64(RefTime) * TimecodeScale));
+ */
+ } else if (EbmlId(*ElementLevel3) =3D=3D KaxBlockDuration::ClassIn=
fos.GlobalId) {
+ KaxBlockDuration & BlockDuration =3D *static_cast<KaxBlockDuratio=
n*>(ElementLevel3.get());
+ BlockDuration.ReadData(m_InputStream.I_O());
+ newFrame->duration =3D uint64(BlockDuration);
+ } else if (EbmlId(*ElementLevel3) =3D=3D KaxBloc=
kAdditions::ClassInfos.GlobalId) {
+ ElementLevel4 =3D ElementPtr(m_InputStream.F=
indNextElement(ElementLevel3->Generic().Context, UpperElementLevel, 0xFFF=
FFFFFL, bAllowDummy));
+ while (ElementLevel4 !=3D NullElement) {
+ if (UpperElementLevel > 0) {
+ break;
+ }
+ if (UpperElementLevel < 0) {
+ UpperElementLevel =3D 0;
+ }
+ if (EbmlId(*ElementLevel4) =3D=3D KaxBlo=
ckMore::ClassInfos.GlobalId) {
+ ElementLevel5 =3D ElementPtr(m_Input=
Stream.FindNextElement(ElementLevel4->Generic().Context, UpperElementLeve=
l, 0xFFFFFFFFL, bAllowDummy));
+ while (ElementLevel5 !=3D NullElemen=
t) {
+ if (UpperElementLevel > 0) {
+ break;
+ }
+ if (UpperElementLevel < 0) {
+ UpperElementLevel =3D 0;
+ }
+ if (EbmlId(*ElementLevel5) =3D=3D=
KaxBlockAddID::ClassInfos.GlobalId) {
+ KaxBlockAddID & AddId =3D *s=
tatic_cast<KaxBlockAddID*>(ElementLevel5.get());
+ AddId.ReadData(m_InputStream=
.I_O());
+ newFrame->add_id =3D uint64(=
AddId);
+ } else if (EbmlId(*ElementLevel5=
) =3D=3D KaxBlockAdditional::ClassInfos.GlobalId) {
+ KaxBlockAdditional & DataBlo=
ckAdditional =3D *static_cast<KaxBlockAdditional*>(ElementLevel5.get()); =
=09
+ DataBlockAdditional.ReadData(m_InputStream.I_O())=
; =09
+ newFrame->additional_data_bu=
ffer.resize(DataBlockAdditional.GetSize());
+ if (!newFrame->add_id) {
+ newFrame->add_id =3D 1;
+ }
+ memcpy(&newFrame->additional=
_data_buffer.at(0), DataBlockAdditional.GetBuffer(), DataBlockAdditional.=
GetSize());
+ }
+ ElementLevel5->SkipData(m_InputS=
tream, ElementLevel5->Generic().Context);
+ ElementLevel5 =3D ElementPtr(m_InputStream.FindNextEl=
ement(ElementLevel4->Generic().Context, UpperElementLevel, ElementLevel4-=
>ElementSize(), bAllowDummy));
+ }
+ }
+ if (UpperElementLevel > 0) {
+ UpperElementLevel--;
+ ElementLevel4 =3D ElementLevel5;
+ if (UpperElementLevel > 0)
+ break;
+ } else {
+ ElementLevel4->SkipData(m_InputStream, ElementLevel4->Gen=
eric().Context);
+ ElementLevel4 =3D ElementPtr(m_InputStream.FindNextElemen=
t(ElementLevel3->Generic().Context, UpperElementLevel, ElementLevel3->Ele=
mentSize(), bAllowDummy));
+ }
+ }
+ }
+ if (UpperElementLevel > 0) {
+ UpperElementLevel--;
+ ElementLevel3 =3D ElementLevel4;
+ if (UpperElementLevel > 0)
+ break;
+ } else {
+ ElementLevel3->SkipData(m_InputStream, ElementLevel3->Generic().C=
ontext);
+
+ ElementLevel3 =3D ElementPtr(m_InputStream.FindNextElement(Elemen=
tLevel2->Generic().Context, UpperElementLevel, ElementLevel2->ElementSize=
(), bAllowDummy));
+ } =09
+ //newFrame =3D new MatroskaReadFrame();
+ }
+ if (newFrame->dataBuffer.size()>0) {
+ m_Queue.push(newFrame);
+ if (prevFrame !=3D NULL && prevFrame->duration =3D=3D 0) {
+ prevFrame->duration =3D newFrame->timecode - prevFrame->timecode;
+ //if (newFrame->duration =3D=3D 0)
+ // newFrame->duration =3D prevFrame->duration;
+ }
+
+ // !!!!!!!!!!!!!!! HACK ALERT !!!!!!!!!!!!!!!!!!!!!!!!
+ // This is an ugly hack to keep us from re-seeking to the same clu=
ster
+ m_CurrentTimecode =3D newFrame->timecode + (newFrame->duration * 2=
);
+ if (newFrame->duration =3D=3D 0) {
+ m_CurrentTimecode +=3D (int64)m_Tracks.at(m_CurrentTrackNo).defau=
ltDuration * 2;
+ }
+ // !!!!!!!!!!!!!!! HACK ALERT !!!!!!!!!!!!!!!!!!!!!!!!
+
+ prevFrame =3D newFrame;
+ } else {
+ hprintf(L"newFrame =3D=3D!! delete!!\n");
+ _DELETE(newFrame);
+ }
+ }
+
+ if (UpperElementLevel > 0) {
+ UpperElementLevel--;
+ //delete ElementLevel2;
+ //_DELETE(ElementLevel2);
+ ElementLevel2 =3D ElementLevel3;
+ if (UpperElementLevel > 0)
+ break;
+ } else {
+ ElementLevel2->SkipData(m_InputStream, ElementLevel2->Generic().Con=
text);
+ //if (ElementLevel2 !=3D pChecksum)
+ // delete ElementLevel2; =09
+ //ElementLevel2 =3D NULL;
+ //_DELETE(ElementLevel2);
+
+ ElementLevel2 =3D ElementPtr(m_InputStream.FindNextElement(ElementL=
evel1->Generic().Context, UpperElementLevel, ElementLevel1->ElementSize()=
, bAllowDummy));
+ }
+ }
+ }
+ //_DELETE(ElementLevel3);
+ //_DELETE(ElementLevel2);
+ //_DELETE(ElementLevel1);
+ //delete ElementLevel1;
+ =09
+ if (currentCluster->clusterNo < m_ClusterIndex.size()-1) {
+ if (m_ClusterIndex.at(currentCluster->clusterNo+1)->timecode =3D=3D M=
AX_UINT64)
+ m_ClusterIndex.at(currentCluster->clusterNo+1)->timecode =3D GetClus=
terTimecode(m_ClusterIndex.at(currentCluster->clusterNo+1)->filePos);
+ m_CurrentTimecode =3D m_ClusterIndex.at(currentCluster->clusterNo+1)-=
>timecode;
+ if(m_CurrentTimecode =3D=3D 0)
+ {
+ console::error(uStringPrintf("clusterNo : %d, m_ClusterIndex.size() =
: %d", currentCluster->clusterNo, m_ClusterIndex.size()));
+ console::info("m_CurrentTimecode =3D=3D 0 (a)");
+ }
+ } else {
+ m_CurrentTimecode =3D MAX_UINT64;
+ }
+ =09
+ } else {
+ // Find the element data
+ ElementLevel1 =3D ElementPtr(m_InputStream.FindNextID(KaxCluster::Clas=
sInfos, 0xFFFFFFFFFFFFFFFFL));
+ if (ElementLevel1 =3D=3D NullElement)
+ return 1;
+
+ if (EbmlId(*ElementLevel1) =3D=3D KaxCluster::ClassInfos.GlobalId) {
+ KaxCluster *SegmentCluster =3D static_cast<KaxCluster *>(ElementLevel=
1.get());
+ uint32 ClusterTimecode =3D 0;
+
+ // read blocks and discard the ones we don't care about
+ ElementLevel2 =3D ElementPtr(m_InputStream.FindNextElement(ElementLev=
el1->Generic().Context, UpperElementLevel, ElementLevel1->ElementSize(), =
bAllowDummy));
+ while (ElementLevel2 !=3D NullElement) {
+ if (UpperElementLevel > 0) {
+ break;
+ }
+ if (UpperElementLevel < 0) {
+ UpperElementLevel =3D 0;
+ }
+ if (EbmlId(*ElementLevel2) =3D=3D KaxClusterTimecode::ClassInfos.Glo=
balId) { =09
+ KaxClusterTimecode & ClusterTime =3D *static_cast<KaxClusterTimecod=
e*>(ElementLevel2.get());
+ ClusterTime.ReadData(m_InputStream.I_O());
+ ClusterTimecode =3D uint32(ClusterTime);
+ SegmentCluster->InitTimecode(ClusterTimecode, m_TimecodeScale);
+ } else if (EbmlId(*ElementLevel2) =3D=3D KaxBlockGroup::ClassInfos.=
GlobalId) {
+ //KaxBlockGroup & aBlockGroup =3D *static_cast<KaxBlockGroup*>(Elem=
entLevel2);
+
+ // Create a new frame
+ MatroskaAudioFrame *newFrame =3D new MatroskaAudioFrame; =09
+
+ ElementLevel3 =3D ElementPtr(m_InputStream.FindNextElement(ElementL=
evel2->Generic().Context, UpperElementLevel, ElementLevel2->ElementSize()=
, bAllowDummy));
+ while (ElementLevel3 !=3D NullElement) {
+ if (UpperElementLevel > 0) {
+ break;
+ }
+ if (UpperElementLevel < 0) {
+ UpperElementLevel =3D 0;
+ }
+ if (EbmlId(*ElementLevel3) =3D=3D KaxBlock::ClassInfos.GlobalId) {=
=09
+ KaxBlock & DataBlock =3D *static_cast<KaxBlock*>(ElementLevel3.ge=
t()); =09
+ DataBlock.ReadData(m_InputStream.I_O()); =09
+ DataBlock.SetParent(*SegmentCluster);
+
+ //NOTE4("Track # %u / %u frame%s / Timecode %I64d", DataBlock.Tra=
ckNum(), DataBlock.NumberFrames(), (DataBlock.NumberFrames() > 1)?"s":"",=
DataBlock.GlobalTimecode()/m_TimecodeScale);
+ if (DataBlock.TrackNum() =3D=3D m_Tracks.at(m_CurrentTrackNo).tra=
ckNumber) { =09
+ newFrame->timecode =3D DataBlock.GlobalTimecode(); =09
+
+ if (DataBlock.NumberFrames() > 1) {=09
+ // The evil lacing has been used
+ newFrame->duration =3D m_Tracks.at(m_CurrentTrackNo).defaultDur=
ation * DataBlock.NumberFrames();
+
+ newFrame->dataBuffer.resize(DataBlock.NumberFrames());
+ for (uint32 f =3D 0; f < DataBlock.NumberFrames(); f++) {
+ DataBuffer &buffer =3D DataBlock.GetBuffer(f);
+ newFrame->dataBuffer[f].resize(buffer.Size()); =09
+ memcpy(&newFrame->dataBuffer[f][0], buffer.Buffer(), buffer.Si=
ze());
+ }
+ } else {
+ // Non-lacing block =09
+ newFrame->duration =3D m_Tracks.at(m_CurrentTrackNo).defaultDur=
ation;
+ =09
+ newFrame->dataBuffer.resize(1);
+ DataBuffer &buffer =3D DataBlock.GetBuffer(0);
+ newFrame->dataBuffer.at(0).resize(buffer.Size()); =09
+ memcpy(&newFrame->dataBuffer[0][0], buffer.Buffer(), buffer.Siz=
e());
+ }
+ } else {
+ //newFrame->timecode =3D MAX_UINT64;
+ }
+ /*
+ } else if (EbmlId(*ElementLevel3) =3D=3D KaxReferenceBlock::ClassI=
nfos.GlobalId) {
+ KaxReferenceBlock & RefTime =3D *static_cast<KaxReferenceBlock*>(=
ElementLevel3);
+ RefTime.ReadData(m_InputStream.I_O());
+ newFrame->frameReferences.push_back(int32(RefTime));
+ //wxLogDebug(" Reference frame at scaled (%d) timecode %ld\n", i=
nt32(RefTime), int32(int64(RefTime) * TimecodeScale));
+ */
+ } else if (EbmlId(*ElementLevel3) =3D=3D KaxBlockDuration::ClassIn=
fos.GlobalId) {
+ KaxBlockDuration & BlockDuration =3D *static_cast<KaxBlockDuratio=
n*>(ElementLevel3.get());
+ BlockDuration.ReadData(m_InputStream.I_O());
+ newFrame->duration =3D uint64(BlockDuration);
+ }
+ if (UpperElementLevel > 0) {
+ UpperElementLevel--;
+ //delete ElementLevel3;
+ //_DELETE(ElementLevel3);
+ ElementLevel3 =3D ElementLevel4;
+ if (UpperElementLevel > 0)
+ break;
+ } else {
+ ElementLevel3->SkipData(m_InputStream, ElementLevel3->Generic().C=
ontext);
+ //delete ElementLevel3;
+ //ElementLevel3 =3D NULL;
+ //_DELETE(ElementLevel3);
+
+ ElementLevel3 =3D ElementPtr(m_InputStream.FindNextElement(Elemen=
tLevel2->Generic().Context, UpperElementLevel, ElementLevel2->ElementSize=
(), bAllowDummy));
+ } =09
+ //newFrame =3D new MatroskaReadFrame();
+ }
+ if (newFrame->dataBuffer.size()>0)
+ m_Queue.push(newFrame);
+ }
+
+ if (UpperElementLevel > 0) {
+ UpperElementLevel--;
+ //delete ElementLevel2;
+ //_DELETE(ElementLevel2);
+ ElementLevel2 =3D ElementLevel3;
+ if (UpperElementLevel > 0)
+ break;
+ } else {
+ ElementLevel2->SkipData(m_InputStream, ElementLevel2->Generic().Con=
text);
+ //if (ElementLevel2 !=3D pChecksum)
+ // delete ElementLevel2; =09
+ //ElementLevel2 =3D NULL;
+ //_DELETE(ElementLevel2);
+
+ ElementLevel2 =3D ElementPtr(m_InputStream.FindNextElement(ElementL=
evel1->Generic().Context, UpperElementLevel, ElementLevel1->ElementSize()=
, bAllowDummy));
+ }
+ }
+ }
+ ElementLevel1->SkipData(m_InputStream, ElementLevel1->Generic().Contex=
t);
+ //_DELETE(ElementLevel3);
+ //_DELETE(ElementLevel2);
+ //_DELETE(ElementLevel1);
+ //delete ElementLevel1;
+ }
+ //NOTE1("MatroskaAudioParser::FillQueue() - Queue now has %u frames", m=
_Queue.size());
+ return 0;
+};
+
+uint64 MatroskaAudioParser::GetClusterTimecode(uint64 filePos) {=09
+ try {
+ uint64 ret =3D MAX_UINT64;
+
+ int UpperElementLevel =3D 0;
+ // Elements for different levels
+ ElementPtr ElementLevel1;
+ ElementPtr ElementLevel2; =09
+ ElementPtr ElementLevel3;
+ ElementPtr NullElement;
+
+ m_IOCallback.setFilePointer(filePos);
+ // Find the element data
+ ElementLevel1 =3D ElementPtr(m_InputStream.FindNextID(KaxCluster::Clas=
sInfos, 0xFFFFFFFFFFFFFFFFL));
+ if (ElementLevel1 =3D=3D NullElement)
+ return MAX_UINT64;
+
+ if (EbmlId(*ElementLevel1) =3D=3D KaxCluster::ClassInfos.GlobalId) {
+ //KaxCluster *SegmentCluster =3D static_cast<KaxCluster *>(ElementLev=
el1);
+ //uint32 ClusterTimecode =3D 0;
+
+ // read blocks and discard the ones we don't care about
+ ElementLevel2 =3D ElementPtr(m_InputStream.FindNextElement(ElementLev=
el1->Generic().Context, UpperElementLevel, ElementLevel1->ElementSize(), =
false));
+ while (ElementLevel2 !=3D NullElement) {
+ if (UpperElementLevel > 0) {
+ break;
+ }
+ if (UpperElementLevel < 0) {
+ UpperElementLevel =3D 0;
+ }
+ if (EbmlId(*ElementLevel2) =3D=3D KaxClusterTimecode::ClassInfos.Glo=
balId) { =09
+ KaxClusterTimecode & ClusterTime =3D *static_cast<KaxClusterTimecod=
e*>(ElementLevel2.get());
+ ClusterTime.ReadData(m_InputStream.I_O());
+ ret =3D uint64(ClusterTime) * m_TimecodeScale;
+ =09
+ }
+
+ if (UpperElementLevel > 0) {
+ UpperElementLevel--;
+ //delete ElementLevel2;
+ //_DELETE(ElementLevel2);
+ ElementLevel2 =3D ElementLevel3;
+ if (UpperElementLevel > 0)
+ break;
+ } else {
+ ElementLevel2->SkipData(m_InputStream, ElementLevel2->Generic().Con=
text);
+ //if (ElementLevel2 !=3D pChecksum)
+ //delete ElementLevel2; =09
+ //ElementLevel2 =3D NULL;
+ //_DELETE(ElementLevel2);
+ ElementLevel2 =3D NullElement;
+ if (ret =3D=3D -1)
+ ElementLevel2 =3D ElementPtr(m_InputStream.FindNextElement(Element=
Level1->Generic().Context, UpperElementLevel, ElementLevel1->ElementSize(=
), false));
+ }
+ }
+ }
+ //_DELETE(ElementLevel3);
+ //_DELETE(ElementLevel2);
+ //_DELETE(ElementLevel1);
+ //delete ElementLevel1;
+
+ return ret;
+ } catch (...) {
+ return MAX_UINT64;
+ }=09
+};
+
+cluster_entry_ptr MatroskaAudioParser::FindCluster(uint64 timecode)
+{
+ try {
+ #ifdef _DEBUG_NO_SEEKING
+ static size_t callCount =3D 0;
+ if (callCount < m_ClusterIndex.size())
+ return &m_ClusterIndex[callCount++];
+ else return NULL;
+ #endif
+
+ if (timecode =3D=3D 0)
+ // Special case
+ return m_ClusterIndex.at(0);
+ =09
+ cluster_entry_ptr correctEntry;
+ double clusterDuration =3D (double)(int64)m_ClusterIndex.size() / m_Du=
ration;
+ size_t clusterIndex =3D clusterDuration * (double)(int64)timecode;
+ //int lookCount =3D 0;
+ if (clusterIndex > m_ClusterIndex.size())
+ clusterIndex =3D m_ClusterIndex.size()-1;
+
+ cluster_entry_ptr clusterEntry;
+ cluster_entry_ptr prevClusterEntry;
+ cluster_entry_ptr nextClusterEntry;
+ while (correctEntry =3D=3D NULL) {
+ clusterEntry =3D m_ClusterIndex.at(clusterIndex); =09
+ if (clusterIndex > 0)
+ prevClusterEntry =3D m_ClusterIndex.at(clusterIndex-1);
+ if (clusterIndex+1 < m_ClusterIndex.size())
+ nextClusterEntry =3D m_ClusterIndex.at(clusterIndex+1); =09
+ =09
+ // We need timecodes to do good seeking
+ if (clusterEntry->timecode =3D=3D MAX_UINT64) { =09
+ clusterEntry->timecode =3D GetClusterTimecode(clusterEntry->filePos)=
; =09
+ }
+ if (prevClusterEntry !=3D NULL && prevClusterEntry->timecode =3D=3D M=
AX_UINT64) {
+ prevClusterEntry->timecode =3D GetClusterTimecode(prevClusterEntry->=
filePos); =09
+ }
+ if (nextClusterEntry !=3D NULL && nextClusterEntry->timecode =3D=3D M=
AX_UINT64) { =09
+ nextClusterEntry->timecode =3D GetClusterTimecode(nextClusterEntry->=
filePos); =09
+ }
+
+ if (clusterEntry->timecode =3D=3D timecode) {
+ // WOW, we are seeking directly to this cluster
+ correctEntry =3D clusterEntry;
+ break;
+ }
+
+ if (prevClusterEntry !=3D NULL) {
+ if (clusterEntry->timecode > timecode && timecode > prevClusterEntry=
->timecode) {
+ // We found it !!!
+ correctEntry =3D prevClusterEntry;
+ break;
+ }
+ if (prevClusterEntry->timecode =3D=3D timecode) {
+ // WOW, we are seeking directly to this cluster
+ correctEntry =3D prevClusterEntry;
+ break;
+ }
+ // Check if we overshot the needed cluster
+ if (timecode < prevClusterEntry->timecode) {
+ clusterIndex--;
+ //lookCount++; // This is how many times we have 'looked'
+ continue;
+ }
+ }
+ =09
+ if (nextClusterEntry !=3D NULL) {
+ if (clusterEntry->timecode < timecode && timecode < nextClusterEntry=
->timecode) {
+ // We found it !!!
+ correctEntry =3D clusterEntry;
+ break;
+ } =09
+ if (nextClusterEntry->timecode =3D=3D timecode) {
+ // WOW, we are seeking directly to this cluster
+ correctEntry =3D nextClusterEntry;
+ break;
+ }
+ // Check if we undershot the needed cluster
+ if (timecode > nextClusterEntry->timecode) {
+ clusterIndex++;
+ //lookCount--;
+ continue;
+ }
+ }
+ // We should never get here, unless this is the last cluster
+ assert(clusterEntry !=3D NULL);=09
+ if (timecode <=3D m_Duration)
+ correctEntry =3D clusterEntry;
+ else
+ break;
+ }
+
+ if (correctEntry !=3D NULL)
+ NOTE3("MatroskaAudioParser::FindCluster(timecode =3D %u) seeking to c=
luster %i at %u", (uint32)(timecode / m_TimecodeScale), (uint32)correctEn=
try->clusterNo, (uint32)correctEntry->filePos);
+ else
+ NOTE1("MatroskaAudioParser::FindCluster(timecode =3D %u) seeking fail=
ed", (uint32)(timecode / m_TimecodeScale));
+
+ return correctEntry;
+ } catch (...) {
+ cluster_entry_ptr null_ptr;
+ return null_ptr;
+ }
+}
+
+void MatroskaAudioParser::CountClusters()=20
+{
+ for (uint32 c =3D 0; c < m_ClusterIndex.size(); c++) {
+ cluster_entry_ptr clusterEntry =3D m_ClusterIndex.at(c); =09
+ clusterEntry->clusterNo =3D c;
+ }
+}
+
+void MatroskaAudioParser::FixChapterEndTimes()
+{
+ if (m_Chapters.size() > 0) {
+ MatroskaChapterInfo *nextChapter =3D &m_Chapters.at(m_Chapters.size()-=
1);
+ if (nextChapter->timeEnd =3D=3D 0) {
+ nextChapter->timeEnd =3D static_cast<uint64>(m_Duration);
+ }
+ for (uint32 c =3D 0; c < m_Chapters.size()-1; c++) {
+ MatroskaChapterInfo ¤tChapter =3D m_Chapters.at(c);=09
+ nextChapter =3D &m_Chapters.at(c+1);
+ if (currentChapter.timeEnd =3D=3D 0) {
+ currentChapter.timeEnd =3D nextChapter->timeStart;
+ }
+ }
+ nextChapter =3D &m_Chapters.at(m_Chapters.size()-1);
+ if ((nextChapter->timeEnd =3D=3D 0) || (nextChapter->timeEnd =3D=3D ne=
xtChapter->timeStart)) {
+ nextChapter->timeEnd =3D static_cast<uint64>(m_Duration);
+ }
+ }=09
+}
+
+bool MatroskaAudioParser::FindEditionUID(uint64 uid)
+{
+ for (uint32 c =3D 0; c < m_Editions.size(); c++) {
+ MatroskaEditionInfo ¤tEdition =3D m_Editions.at(c);=09
+ if (currentEdition.editionUID =3D=3D uid)
+ return true;
+ }=09
+ return false;
+}
+
+bool MatroskaAudioParser::FindChapterUID(uint64 uid)
+{
+ for (uint32 c =3D 0; c < m_Chapters.size(); c++) {
+ MatroskaChapterInfo ¤tChapter =3D m_Chapters.at(c);=09
+ if (currentChapter.chapterUID =3D=3D uid)
+ return true;
+ }=09
+ return false;
+}
+
+void PrintChapters(std::vector<MatroskaChapterInfo> &theChapters)=20
+{
+ for (uint32 c =3D 0; c < theChapters.size(); c++) {
+ MatroskaChapterInfo ¤tChapter =3D theChapters.at(c);=09
+ NOTE2("Chapter %u, UID: %u", c, (uint32)currentChapter.chapterUID);
+ NOTE1("\tStart Time: %u", (uint32)currentChapter.timeStart);
+ NOTE1("\tEnd Time: %u", (uint32)currentChapter.timeEnd);
+ for (uint32 d =3D 0; d < currentChapter.display.size(); d++) {
+ NOTE3("\tDisplay %u, String: %s Lang: %s", d, currentChapter.display.=
at(d).string.GetUTF8().c_str(), currentChapter.display.at(d).lang.c_str()=
);
+ }
+ for (uint32 t =3D 0; t < currentChapter.tracks.size(); t++) {
+ NOTE2("\tTrack %u, UID: %%u", t, (uint32)currentChapter.tracks.at(t))=
;
+ }
+
+ }
+};
+
+bool MatroskaSearch::Skip()
+{
+ int j;
+
+ for (j =3D 0; j < SEARCH_TABLE_SIZE; j++) skip[j] =3D SEARCH_PATTERN_SI=
ZE;
+ for (j =3D 0; j < SEARCH_PATTERN_SIZE - 1; j++)
+ skip[pattern[j] & 0x00ff] =3D SEARCH_PATTERN_SIZE-1-j;
+ return true;
+}
+
+bool MatroskaSearch::Next()
+{
+ int j, k, s;
+ int *g;
+
+ if ((g =3D (int *)malloc(sizeof(int)*SEARCH_PATTERN_SIZE)) =3D=3D NULL)=
return false;
+ for (j =3D 0; j < SEARCH_PATTERN_SIZE; j++) next[j] =3D 2*SEARCH_PATTER=
N_SIZE - 1 - j;
+ j =3D SEARCH_PATTERN_SIZE;
+ for (k =3D SEARCH_PATTERN_SIZE - 1; k >=3D 0; k--) {
+ g[k] =3D j;
+ while (j !=3D SEARCH_PATTERN_SIZE && pattern[j] !=3D pattern[k]) {
+ next[j] =3D (next[j] <=3D SEARCH_PATTERN_SIZE-1-k) ? next[j] : SEARCH=
_PATTERN_SIZE-1-k;
+ j =3D g[j];
+ }
+ j--;
+ }
+ s =3D j;
+ for (j =3D 0; j < SEARCH_PATTERN_SIZE; j++) {
+ next[j] =3D (next[j] <=3D s+SEARCH_PATTERN_SIZE-j) ? next[j] : s+SEARC=
H_PATTERN_SIZE-j;
+ if (j >=3D s) s =3D g[s];
+ }
+ free(g);
+ return true;
+}
+
+int MatroskaSearch::Match(unsigned int start)
+{
+ int i, j;
+
+ i =3D SEARCH_PATTERN_SIZE - 1 + start;
+ while (i < SEARCH_SOURCE_SIZE) {
+ j =3D SEARCH_PATTERN_SIZE - 1;
+ while (j >=3D 0 && source[i] =3D=3D pattern[j]) {
+ i--;
+ j--;
+ }
+ if (j < 0) return i + 1;
+ if (skip[source[i] & 0x00ff] >=3D next[j])
+ i +=3D skip[source[i] & 0x00ff];
+ else i +=3D next[j];
+ }
+ return -1;
};
\ No newline at end of file
Property changes on: trunk/foo_input_matroska/matroska_parser.cpp
___________________________________________________________________
Name: svn:eol-style
+ native