私はパラメータとしてwebMファイル(メディア)を受け取り、できるだけ詳しくTTY経由でストリームの詳細を出力するプログラムを作成しようとしています。バイナリモードでファイルを開こうとしていたのですが、どこから起動するのか分かりません。webMファイルをC++のパラメータとして渡しますか?
ありがとうございました。
私はパラメータとしてwebMファイル(メディア)を受け取り、できるだけ詳しくTTY経由でストリームの詳細を出力するプログラムを作成しようとしています。バイナリモードでファイルを開こうとしていたのですが、どこから起動するのか分かりません。webMファイルをC++のパラメータとして渡しますか?
ありがとうございました。
これは非常に高いレベルの質問のように聞こえるので、私はそのようにお答えします:
あなたはパラメータを受け入れる必要があるC/C++でのコマンドラインプログラムを作成している場合は、使用方法を見上げます'argc'と 'argv'パラメータをmain()関数に渡します。
パラメータをメイン関数に渡したら、ファイル読み込みライブラリを使用してパラメータをオープンしようとします(ニーズやプラットフォームに応じていくつか選択できます)。はい。ファイルライブラリがその違いを気にしている場合は、バイナリモードでWebMファイルを開くことができます。 fopen()を使用している場合、バイナリモードで読み込むには "rb"を指定します。これはUnix(普通の "r")との違いはありませんが、Windowsでは大きな違いがあります。
そこから、WebMファイルからバイトを読み込んで処理することができます。 WebMはMatroskaのマルチメディアフォーマットに基づいており、これはかなり関わっていることに注意してください。あなたが学問的なエクササイズとしてこれをやっているのであれば、あなたはもっと力を発揮します。厳しい締め切り期限内に何かを達成するために探しているなら、あなたのためにMatroska解析を大量に行うために呼び出すことのできるライブラリがあります。
これは、libwebmを使用して行うことができます。サンプルコードを以下に示します。これは、ヘッダ、クラスタ、セグメント等を印刷
main.cppに
#include "stdio.h"
#include "stdlib.h"
#include "stdbool.h"
#include "string.h"
#include <memory>
#include <mkv/mkvreader.hpp>
#include <mkv/mkvparser.hpp>
#include <mkv/mkvparser.hpp>
#include "webm_parser.h"
static const wchar_t* utf8towcs(const char* str);
bool InputHasCues(const mkvparser::Segment* const segment);
using namespace mkvparser;
/**
* This file reads an webm file. Generates a new file with random number
* of packets in a single webm page.
*/
int webm_parse(int argc, char **argv)
{
int ret = -1;
char *file_out;
char *file_in;
FILE *fd_out = NULL;
MkvReader reader;
if(argc != 3)
{
printf("Usage: ./webm <input webm file> <output webm file>\n");
exit(0);
}
file_in = argv[1];
file_out = argv[2];
printf("\n\nInput webm file = %s , Output webm file = %s\n", file_in, file_out);
fd_out = fopen(file_out, "w+");
if(fd_out == NULL) goto on_error;
if(reader.Open(file_in))
{
printf("Error opening input file %s", file_in);
}
else
{
printf("Successfully opened input file %s\n", file_in);
}
webm_parse_header(&reader);
/** Return 0 on success */
printf("\n");
return ret;
on_error:
if(fd_out) fclose(fd_out);
printf("Error while parse/generate webm file\n");
/** Return -1 on failure */
return -1;
}
int webm_parse_header(void *reader)
{
int maj, min, build, rev;
long long pos = 0;
typedef mkvparser::Segment seg_t;
seg_t* pSegment_;
long long ret;
MkvReader *mkvrdr = (MkvReader *)reader;
EBMLHeader ebmlHeader;
GetVersion(maj, min, build, rev);
printf("libmkv verison: %d.%d.%d.%d\n", maj, min, build, rev);
ebmlHeader.Parse(mkvrdr, pos);
printf("\t\t\t EBML Header\n");
printf("\t\tEBML Version\t\t: %lld\n", ebmlHeader.m_version);
printf("\t\tEBML MaxIDLength\t: %lld\n", ebmlHeader.m_maxIdLength);
printf("\t\tEBML MaxSizeLength\t: %lld\n", ebmlHeader.m_maxSizeLength);
printf("\t\tDoc Type\t\t: %s\n", ebmlHeader.m_docType);
printf("\t\tPos\t\t\t: %lld\n", pos);
ret = seg_t::CreateInstance(mkvrdr, pos, pSegment_);
if (ret)
{
printf("Segment::CreateInstance() failed.\n");
return -1;
}
else
{
printf("Segment::CreateInstance() successful.\n");
}
const std::auto_ptr<seg_t> pSegment(pSegment_);
ret = pSegment->Load();
if (ret < 0)
{
printf("Segment::Load() failed.\n");
return -1;
}
else
{
printf("Segment::Load() successful.\n");
}
const SegmentInfo* const pSegmentInfo = pSegment->GetInfo();
const long long timeCodeScale = pSegmentInfo->GetTimeCodeScale();
const long long duration_ns = pSegmentInfo->GetDuration();
const char* const pTitle_ = pSegmentInfo->GetTitleAsUTF8();
const wchar_t* const pTitle = utf8towcs(pTitle_);
const char* const pMuxingApp_ = pSegmentInfo->GetMuxingAppAsUTF8();
const wchar_t* const pMuxingApp = utf8towcs(pMuxingApp_);
const char* const pWritingApp_ = pSegmentInfo->GetWritingAppAsUTF8();
const wchar_t* const pWritingApp = utf8towcs(pWritingApp_);
printf("\n");
printf("\t\t\t Segment Info\n");
printf("\t\tTimeCodeScale\t\t: %lld \n", timeCodeScale);
printf("\t\tDuration\t\t: %lld\n", duration_ns);
const double duration_sec = double(duration_ns)/1000000000;
printf("\t\tDuration(secs)\t\t: %7.3lf\n", duration_sec);
if (pTitle == NULL)
printf("\t\tTrack Name\t\t: NULL\n");
else
{
printf("\t\tTrack Name\t\t: %ls\n", pTitle);
delete[] pTitle;
}
if (pMuxingApp == NULL)
printf("\t\tMuxing App\t\t: NULL\n");
else
{
printf("\t\tMuxing App\t\t: %ls\n", pMuxingApp);
delete[] pMuxingApp;
}
if (pWritingApp == NULL)
printf("\t\tWriting App\t\t: NULL\n");
else
{
printf("\t\tWriting App\t\t: %ls\n", pWritingApp);
delete[] pWritingApp;
}
// pos of segment payload
printf("\t\tPosition(Segment)\t: %lld\n", pSegment->m_start);
// size of segment payload
printf("\t\tSize(Segment)\t\t: %lld\n", pSegment->m_size);
const mkvparser::Tracks* pTracks = pSegment->GetTracks();
unsigned long track_num = 0;
const unsigned long num_tracks = pTracks->GetTracksCount();
printf("\n\t\t\t Track Info\n");
while (track_num != num_tracks)
{
const Track* const pTrack = pTracks->GetTrackByIndex(track_num++);
if (pTrack == NULL)
continue;
const long trackType = pTrack->GetType();
const long trackNumber = pTrack->GetNumber();
const unsigned long long trackUid = pTrack->GetUid();
const wchar_t* const pTrackName = utf8towcs(pTrack->GetNameAsUTF8());
printf("\t\tTrack Type\t\t: %ld\n", trackType);
printf("\t\tTrack Number\t\t: %ld\n", trackNumber);
printf("\t\tTrack Uid\t\t: %lld\n", trackUid);
if (pTrackName == NULL)
printf("\t\tTrack Name\t\t: NULL\n");
else
{
printf("\t\tTrack Name\t\t: %ls \n", pTrackName);
delete[] pTrackName;
}
const char* const pCodecId = pTrack->GetCodecId();
if (pCodecId == NULL)
printf("\t\tCodec Id\t\t: NULL\n");
else
printf("\t\tCodec Id\t\t: %s\n", pCodecId);
const char* const pCodecName_ = pTrack->GetCodecNameAsUTF8();
const wchar_t* const pCodecName = utf8towcs(pCodecName_);
if (pCodecName == NULL)
printf("\t\tCodec Name\t\t: NULL\n");
else
{
printf("\t\tCodec Name\t\t: %ls\n", pCodecName);
delete[] pCodecName;
}
if (trackType == mkvparser::Track::kVideo)
{
const VideoTrack* const pVideoTrack =
static_cast<const VideoTrack*>(pTrack);
const long long width = pVideoTrack->GetWidth();
printf("\t\tVideo Width\t\t: %lld\n", width);
const long long height = pVideoTrack->GetHeight();
printf("\t\tVideo Height\t\t: %lld\n", height);
const double rate = pVideoTrack->GetFrameRate();
printf("\t\tVideo Rate\t\t: %f\n", rate);
}
if (trackType == mkvparser::Track::kAudio)
{
const AudioTrack* const pAudioTrack =
static_cast<const AudioTrack*>(pTrack);
const long long channels = pAudioTrack->GetChannels();
printf("\t\tAudio Channels\t\t: %lld\n", channels);
const long long bitDepth = pAudioTrack->GetBitDepth();
printf("\t\tAudio BitDepth\t\t: %lld\n", bitDepth);
const double sampleRate = pAudioTrack->GetSamplingRate();
printf("\t\tAddio Sample Rate\t: %.3f\n", sampleRate);
const long long codecDelay = pAudioTrack->GetCodecDelay();
printf("\t\tAudio Codec Delay\t: %lld\n", codecDelay);
const long long seekPreRoll = pAudioTrack->GetSeekPreRoll();
printf("\t\tAudio Seek Pre Roll\t: %lld\n", seekPreRoll);
}
}
printf("\n\n\t\t\t Cluster Info\n");
const unsigned long clusterCount = pSegment->GetCount();
printf("\t\tCluster Count\t: %ld\n\n", clusterCount);
if (clusterCount == 0)
{
printf("\t\tSegment has no clusters.\n");
return -1;
}
const mkvparser::Cluster* pCluster = pSegment->GetFirst();
while ((pCluster != NULL) && !pCluster->EOS())
{
const long long timeCode = pCluster->GetTimeCode();
printf("\t\tCluster Time Code\t: %lld\n", timeCode);
const long long time_ns = pCluster->GetTime();
printf("\t\tCluster Time (ns)\t: %lld\n", time_ns);
const BlockEntry* pBlockEntry;
long status = pCluster->GetFirst(pBlockEntry);
if (status < 0) // error
{
printf("\t\tError parsing first block of cluster\n");
fflush(stdout);
return -1;
}
while ((pBlockEntry != NULL) && !pBlockEntry->EOS())
{
const Block* const pBlock = pBlockEntry->GetBlock();
const long long trackNum = pBlock->GetTrackNumber();
const unsigned long tn = static_cast<unsigned long>(trackNum);
const Track* const pTrack = pTracks->GetTrackByNumber(tn);
if (pTrack == NULL)
printf("\t\t\tBlock\t\t:UNKNOWN TRACK TYPE\n");
else
{
const long long trackType = pTrack->GetType();
const int frameCount = pBlock->GetFrameCount();
const long long time_ns = pBlock->GetTime(pCluster);
const long long discard_padding = pBlock->GetDiscardPadding();
printf("\t\t\tBlock\t\t:%s,%s,%15lld,%lld\n",
(trackType == mkvparser::Track::kVideo) ? "V" : "A",
pBlock->IsKey() ? "I" : "P", time_ns, discard_padding);
for (int i = 0; i < frameCount; ++i)
{
const Block::Frame& theFrame = pBlock->GetFrame(i);
const long size = theFrame.len;
const long long offset = theFrame.pos;
printf("\t\t\t %15ld,%15llx\n", size, offset);
}
}
status = pCluster->GetNext(pBlockEntry, pBlockEntry);
if (status < 0)
{
printf("\t\t\tError parsing next block of cluster\n");
fflush(stdout);
return -1;
}
}
pCluster = pSegment->GetNext(pCluster);
}
if (InputHasCues(pSegment.get()))
{
// Walk them.
const mkvparser::Cues* const cues = pSegment->GetCues();
const mkvparser::CuePoint* cue = cues->GetFirst();
int cue_point_num = 1;
printf("\t\tCues\n");
do
{
for (track_num = 0; track_num < num_tracks; ++track_num)
{
const mkvparser::Track* const track =
pTracks->GetTrackByIndex(track_num);
const mkvparser::CuePoint::TrackPosition* const track_pos =
cue->Find(track);
if (track_pos != NULL)
{
const char track_type =
(track->GetType() == mkvparser::Track::kVideo) ? 'V' : 'A';
printf(
"\t\t\tCue Point %4d Track %3lu(%c) Time %14lld "
"Block %4lld Pos %8llx\n",
cue_point_num, track->GetNumber(), track_type,
cue->GetTime(pSegment.get()), track_pos->m_block,
track_pos->m_pos);
}
}
cue = cues->GetNext(cue);
++cue_point_num;
} while (cue != NULL);
}
const mkvparser::Tags* const tags = pSegment->GetTags();
if (tags && tags->GetTagCount() > 0)
{
printf("\t\tTags\n");
for (int i = 0; i < tags->GetTagCount(); ++i)
{
const mkvparser::Tags::Tag* const tag = tags->GetTag(i);
printf("\t\t\tTag\n");
for (int j = 0; j < tag->GetSimpleTagCount(); j++)
{
const mkvparser::Tags::SimpleTag* const simple_tag =
tag->GetSimpleTag(j);
printf("\t\t\t\tSimple Tag \"%s\" Value \"%s\"\n",
simple_tag->GetTagName(), simple_tag->GetTagString());
}
}
}
fflush(stdout);
return 0;
on_error:
return -1;
}
static const wchar_t* utf8towcs(const char* str)
{
if (str == NULL)
return NULL;
// TODO: this probably requires that the locale be
// configured somehow:
const size_t size = mbstowcs(NULL, str, 0);
if (size == 0)
return NULL;
wchar_t* const val = new wchar_t[size + 1];
mbstowcs(val, str, size);
val[size] = L'\0';
return val;
}
bool InputHasCues(const mkvparser::Segment* const segment)
{
const mkvparser::Cues* const cues = segment->GetCues();
if (cues == NULL)
return false;
while (!cues->DoneParsing())
cues->LoadCuePoint();
const mkvparser::CuePoint* const cue_point = cues->GetFirst();
if (cue_point == NULL)
return false;
return true;
}