matroska/test/ebml/test00.cpp

247 lines
9.0 KiB
C++

/****************************************************************************
** libmatroska : parse Matroska files, see http://www.matroska.org/
**
** <file/class description>
**
** Copyright (C) 2002-2004 Steve Lhomme. All rights reserved.
**
** This file is part of libmatroska.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** See http://www.gnu.org/licenses/lgpl-2.1.html for LGPL licensing information.**
** Contact license@matroska.org if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
/*!
\file
\version \$Id$
\author Steve Lhomme <robux4 @ users.sf.net>
Test the writing a basic EBML file
*/
#include <stdio.h>
#include <string>
#include "ebml/StdIOCallback.h"
#include "ebml/EbmlHead.h"
#include "ebml/EbmlSubHead.h"
#include "ebml/EbmlStream.h"
#include "ebml/EbmlVoid.h"
#include "ebml/EbmlContexts.h"
#include "matroska/KaxSegment.h"
#include "matroska/KaxContexts.h"
#include "matroska/KaxSemantic.h"
#include "ebml/EbmlVersion.h"
#include "matroska/KaxVersion.h"
using namespace LIBMATROSKA_NAMESPACE;
const char RW_FILENAME[] = "test.kax";
#undef SKIP_ATTACHED
/*!
\test Some test on the Cluster use
\todo each Master element should have a context !
\todo move the base EBML classes to a template of each type ? (defining the default value and the ID)
\todo find another way than using all those static_cast (using a template ?)
*/
int main(void)
{
printf("Test00 :\nEBML %s %s / Matroska %s %s\n", EbmlCodeVersion.c_str(), EbmlCodeDate.c_str(), KaxCodeVersion.c_str(), KaxCodeDate.c_str());
StdIOCallback Ebml_file(RW_FILENAME, ::MODE_CREATE);
///// Writing test
EbmlHead TestHead;
printf("Write EBML + Matroska elements\n");
EDocType & MyDocType = GetChild<EDocType>(TestHead);
*static_cast<EbmlString *>(&MyDocType) = "matroska";
EDocTypeVersion & MyDocTypeVer = GetChild<EDocTypeVersion>(TestHead);
*(static_cast<EbmlUInteger *>(&MyDocTypeVer)) = 1;
EDocTypeReadVersion & MyDocTypeReadVer = GetChild<EDocTypeReadVersion>(TestHead);
*(static_cast<EbmlUInteger *>(&MyDocTypeReadVer)) = 1;
TestHead.Render(Ebml_file);
KaxSegment FirstSegment;
// size is unknown and will always be, we can render it right away
FirstSegment.Render(Ebml_file);
KaxAttachments * pAllAttachments = static_cast<KaxAttachments *>(FirstSegment.FindFirstElt(KaxAttachments::ClassInfos, true));
if (pAllAttachments == NULL)
return -1;
pAllAttachments->SetSizeInfinite();
// size is unknown and will always be, we can render it right away
pAllAttachments->Render(Ebml_file);
KaxAttached * pAttachment1 = static_cast<KaxAttached *>(pAllAttachments->FindFirstElt(KaxAttached::ClassInfos, true));
if (pAttachment1 == NULL)
return -1;
KaxFileName * pFileName1 = static_cast<KaxFileName *>(pAttachment1->FindFirstElt(KaxFileName::ClassInfos, true));
if (pFileName1 == NULL)
return -1;
*static_cast<EbmlUnicodeString *>(pFileName1) = "file1.txt";
KaxFileData * pFileData1 = static_cast<KaxFileData *>(pAttachment1->FindFirstElt(KaxFileData::ClassInfos, true));
if (pFileData1 == NULL)
return -1;
char Buffer1[] = "Ah ah ah !";
static_cast<EbmlBinary *>(pFileData1)->SetBuffer((const binary*) Buffer1, countof(Buffer1));
// should produce an error if the size is not infinite and the data has been rendered
pAttachment1->Render(Ebml_file);
KaxAttached * pAttachment2 = static_cast<KaxAttached *>(pAllAttachments->AddNewElt(KaxAttached::ClassInfos));
if (pAttachment2 == NULL)
return -1;
KaxFileName * pFileName2 = static_cast<KaxFileName *>(pAttachment2->FindFirstElt(KaxFileName::ClassInfos, true));
if (pFileName2 == NULL)
return -1;
*static_cast<EbmlUnicodeString *>(pFileName2) = "file2.txt";
// Add a void element (data is discarded)
EbmlVoid * pVoid = static_cast<EbmlVoid *>(pAttachment2->FindFirstElt(EbmlVoid::ClassInfos, true));
if (pVoid == NULL)
return -1;
static_cast<EbmlBinary *>(pVoid)->SetBuffer((const binary*) Buffer1, countof(Buffer1));
pAttachment2->Render(Ebml_file);
#ifdef SKIP_ATTACHED
KaxSegment SecondSegment;
// size is unknown and will always be, we can render it right away
SecondSegment.Render(Ebml_file);
#endif // SKIP_ATTACHED
Ebml_file.close();
///// Reading test
StdIOCallback Ebml_Wfile(RW_FILENAME, ::MODE_READ);
// example 1 skip all the elements found
EbmlStream aStream(Ebml_Wfile);
EbmlElement * ElementLevel0;
EbmlElement * ElementLevel1;
EbmlElement * ElementLevel2;
EbmlElement * ElementLevel3;
// read the data until a possible element is found (valid ID + size combination)
printf("Read EBML elements & skip data\n");
// find the EBML head in the file
ElementLevel0 = aStream.FindNextID(EbmlHead::ClassInfos, 0xFFFFFFFFL, false);
if (ElementLevel0 != NULL)
{
printf("ID : ");
for (unsigned int i=0; i<EbmlId(*ElementLevel0).Length; i++)
{
printf("[%02X]", EbmlId(*ElementLevel0).Value[i]);
}
printf("\n");
ElementLevel0->SkipData(aStream, EbmlHead_Context);
if (ElementLevel0 != NULL)
delete ElementLevel0;
}
// example to read attachements in the file
ElementLevel0 = aStream.FindNextID(KaxSegment::ClassInfos, 0xFFFFFFFFL, false);
while (ElementLevel0 != NULL)
{
printf("ID : ");
for (unsigned int i=0; i<EbmlId(*ElementLevel0).Length; i++)
{
printf("[%02X]", EbmlId(*ElementLevel0).Value[i]);
}
printf("\n");
int bUpperElement = 0;
ElementLevel1 = aStream.FindNextID(KaxSegment_Context, bUpperElement, 0xFFFFFFFFL, true);
while (ElementLevel1 != NULL) {
/// \todo switch the type of the element to check if it's one we want to handle, like attachements
if (EbmlId(*ElementLevel1) == KaxAttachments::ClassInfos.GlobalId) {
printf("Attachments detected\n");
ElementLevel2 = aStream.FindNextID(KaxAttachments_Context, bUpperElement, 0xFFFFFFFFL, true);
while (ElementLevel2 != NULL) {
/// \todo switch the type of the element to check if it's one we want to handle, like attachements
if (EbmlId(*ElementLevel2) == KaxAttached::ClassInfos.GlobalId) {
printf("Attached file detected\n");
}
#ifdef SKIP_ATTACHED
ElementLevel2 = ElementLevel2->SkipData(aStream, KaxAttached_Context);
if (ElementLevel2 == NULL) {
ElementLevel2 = aStream.FindNextID(KaxAttachments_Context, bUpperElement, 0xFFFFFFFFL, true);
if (bUpperElement) {
printf("Upper level1 element found\n");
delete ElementLevel1;
ElementLevel1 = ElementLevel2;
ElementLevel2 = NULL;
}
}
#else // SKIP_ATTACHED
// Display the filename (if it exists)
ElementLevel3 = aStream.FindNextID(KaxAttached_Context, bUpperElement, 0xFFFFFFFFL, false);
while (ElementLevel3 != NULL) {
/// \todo switch the type of the element to check if it's one we want to handle, like attachements
if (EbmlId(*ElementLevel3) == KaxFileName::ClassInfos.GlobalId) {
KaxFileName & tmp = *static_cast<KaxFileName*>(ElementLevel3);
tmp.ReadData(aStream.I_O());
printf("File Name = %ls\n", UTFstring(tmp).c_str());
} else {
ElementLevel3->SkipData(aStream, KaxAttached_Context);
}
delete ElementLevel3;
ElementLevel3 = aStream.FindNextID(KaxAttached_Context, bUpperElement, 0xFFFFFFFFL, false);
if (bUpperElement)
break;
}
if (bUpperElement) {
delete ElementLevel2;
ElementLevel2 = ElementLevel3;
} else {
ElementLevel2->SkipData(aStream, KaxAttached_Context);
delete ElementLevel2;
ElementLevel2 = aStream.FindNextID(KaxAttachments_Context, bUpperElement, 0xFFFFFFFFL, true);
}
#endif // SKIP_ATTACHED
}
}
ElementLevel1->SkipData(aStream, KaxAttachments_Context);
delete ElementLevel1;
ElementLevel1 = aStream.FindNextID(KaxSegment_Context, bUpperElement, 0xFFFFFFFFL, true);
}
ElementLevel0->SkipData(aStream, KaxSegment_Context);
if (ElementLevel0 != NULL)
delete ElementLevel0;
ElementLevel0 = aStream.FindNextID(KaxSegment_Context, bUpperElement, 0xFFFFFFFFL, true);
}
Ebml_Wfile.close();
return 0;
}