~ubuntu-branches/ubuntu/wily/mkvtoolnix/wily

« back to all changes in this revision

Viewing changes to src/info/mkvinfo.cpp

  • Committer: Package Import Robot
  • Author(s): Christian Marillat
  • Date: 2015-04-26 10:36:27 UTC
  • mfrom: (1.1.29) (4.2.45 sid)
  • Revision ID: package-import@ubuntu.com-20150426103627-k53p8hrai2ynikaa
Tags: 7.8.0-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
   mkvinfo -- utility for gathering information about Matroska files
3
3
 
4
 
   Distributed under the GPL
 
4
   Distributed under the GPL v2
5
5
   see the file COPYING for details
6
6
   or visit http://www.gnu.org/copyleft/gpl.html
7
7
 
12
12
 
13
13
#include "common/common_pch.h"
14
14
 
15
 
#include <errno.h>
16
 
#include <ctype.h>
17
 
#include <limits.h>
18
 
#include <stdarg.h>
19
 
#include <stdlib.h>
20
 
#include <stdio.h>
21
 
#include <string.h>
22
 
#include <time.h>
23
 
 
24
 
#if defined(COMP_MSC)
25
 
#include <cassert>
26
 
#else
27
 
#include <unistd.h>
28
 
#endif
29
 
 
30
15
#include <algorithm>
31
16
#include <iostream>
32
17
#include <typeinfo>
33
18
 
34
 
#include <avilib.h>
 
19
#include <boost/math/special_functions/round.hpp>
35
20
 
36
21
#include <ebml/EbmlHead.h>
37
22
#include <ebml/EbmlSubHead.h>
66
51
#define MATROSKA_VERSION 2
67
52
#endif
68
53
 
 
54
#include "avilib.h"
69
55
#include "common/chapters/chapters.h"
70
 
#include "common/checksums.h"
 
56
#include "common/checksums/base.h"
71
57
#include "common/codec.h"
72
58
#include "common/command_line.h"
73
59
#include "common/ebml.h"
74
60
#include "common/endian.h"
 
61
#include "common/fourcc.h"
75
62
#include "common/hevc.h"
76
63
#include "common/kax_file.h"
77
64
#include "common/mm_io.h"
114
101
  , mkvmerge_track_id(0)
115
102
{
116
103
}
117
 
typedef std::shared_ptr<kax_track_t> kax_track_cptr;
 
104
using kax_track_cptr = std::shared_ptr<kax_track_t>;
118
105
 
119
106
track_info_t::track_info_t()
120
107
  : m_size(0)
332
319
                                    char track_type,
333
320
                                    const std::string &codec_id) {
334
321
  if ((codec_id == MKV_V_MSCOMP) && ('v' == track_type) && (c_priv.GetSize() >= sizeof(alBITMAPINFOHEADER))) {
335
 
    alBITMAPINFOHEADER *bih = reinterpret_cast<alBITMAPINFOHEADER *>(c_priv.GetBuffer());
336
 
    unsigned char *fcc      = reinterpret_cast<unsigned char *>(&bih->bi_compression);
337
 
    return (boost::format(Y(" (FourCC: %1%%2%%3%%4%, 0x%|5$08x|)"))
338
 
            % fcc[0] % fcc[1] % fcc[2] % fcc[3] % get_uint32_le(&bih->bi_compression)).str();
 
322
    auto bih = reinterpret_cast<alBITMAPINFOHEADER *>(c_priv.GetBuffer());
 
323
    return (boost::format(Y(" (FourCC: %1%)")) % fourcc_c{&bih->bi_compression}.description()).str();
339
324
 
340
325
  } else if ((codec_id == MKV_A_ACM) && ('a' == track_type) && (c_priv.GetSize() >= sizeof(alWAVEFORMATEX))) {
341
326
    alWAVEFORMATEX *wfe     = reinterpret_cast<alWAVEFORMATEX *>(c_priv.GetBuffer());
361
346
               :                             Y("Unknown"))
362
347
            % (avcc.m_level_idc / 10) % (avcc.m_level_idc % 10)).str();
363
348
  } else if ((codec_id == MKV_V_MPEGH_HEVC) && ('v' == track_type) && (c_priv.GetSize() >= 4)) {
364
 
    auto hevcc = hevc::hevcc_c::unpack(std::make_shared<memory_c>(c_priv.GetBuffer(), c_priv.GetSize(), false));
 
349
    auto hevcc = mtx::hevc::hevcc_c::unpack(std::make_shared<memory_c>(c_priv.GetBuffer(), c_priv.GetSize(), false));
365
350
 
366
351
    return (boost::format(Y(" (HEVC profile: %1% @L%2%.%3%)"))
367
352
            % (  hevcc.m_general_profile_idc == 1 ? "Main"
444
429
    result += "...";
445
430
 
446
431
  if (g_options.m_calc_checksums)
447
 
    result += (BF_FORMAT_BINARY_2 % calc_adler32(bin.GetBuffer(), bin.GetSize())).str();
 
432
    result += (BF_FORMAT_BINARY_2 % mtx::checksum::calculate_as_uint(mtx::checksum::adler32, bin.GetBuffer(), bin.GetSize())).str();
448
433
 
449
434
  strip(result);
450
435
 
866
851
          fourcc_buffer = create_codec_dependent_private_info(c_priv, track->type, kax_codec_id);
867
852
 
868
853
          if (g_options.m_calc_checksums && !g_options.m_show_summary)
869
 
            fourcc_buffer += (boost::format(Y(" (adler: 0x%|1$08x|)"))        % calc_adler32(c_priv.GetBuffer(), c_priv.GetSize())).str();
 
854
            fourcc_buffer += (boost::format(Y(" (adler: 0x%|1$08x|)"))        % mtx::checksum::calculate_as_uint(mtx::checksum::adler32, c_priv.GetBuffer(), c_priv.GetSize())).str();
870
855
 
871
856
          if (g_options.m_show_hexdump)
872
857
            fourcc_buffer += create_hexdump(c_priv.GetBuffer(), c_priv.GetSize());
1148
1133
  std::vector<uint32_t> frame_adlers;
1149
1134
  std::vector<std::string> frame_hexdumps;
1150
1135
 
1151
 
  bool bref_found     = false;
1152
 
  bool fref_found     = false;
1153
 
 
 
1136
  auto num_references = 0u;
1154
1137
  int64_t lf_timecode = 0;
1155
1138
  int64_t lf_tnum     = 0;
1156
1139
  int64_t frame_pos   = 0;
1161
1144
    if (Is<KaxBlock>(l3)) {
1162
1145
      KaxBlock &block = *static_cast<KaxBlock *>(l3);
1163
1146
      block.SetParent(*cluster);
 
1147
 
 
1148
      lf_timecode = block.GlobalTimecode();
 
1149
      lf_tnum     = block.TrackNum();
 
1150
      bduration   = -1.0;
 
1151
      frame_pos   = block.GetElementPosition() + block.ElementSize();
 
1152
 
1164
1153
      show_element(l3, 3,
1165
1154
                   BF_BLOCK_GROUP_BLOCK_BASICS
1166
1155
                   % block.TrackNum()
1167
1156
                   % block.NumberFrames()
1168
 
                   % (static_cast<double>(block.GlobalTimecode()) / 1000000000.0)
1169
 
                   % format_timecode(block.GlobalTimecode(), 3));
1170
 
 
1171
 
      lf_timecode = block.GlobalTimecode();
1172
 
      lf_tnum     = block.TrackNum();
1173
 
      bduration   = -1.0;
1174
 
      frame_pos   = block.GetElementPosition() + block.ElementSize();
 
1157
                   % (static_cast<double>(lf_timecode) / 1000000000.0)
 
1158
                   % format_timecode(lf_timecode, 3));
1175
1159
 
1176
1160
      for (size_t i = 0; i < block.NumberFrames(); ++i) {
1177
1161
        auto &data = block.GetBuffer(i);
1178
 
        auto adler = calc_adler32(data.Buffer(), data.Size());
 
1162
        auto adler = mtx::checksum::calculate_as_uint(mtx::checksum::adler32, data.Buffer(), data.Size());
1179
1163
 
1180
1164
        std::string adler_str;
1181
1165
        if (g_options.m_calc_checksums)
1199
1183
      show_element(l3, 3, BF_BLOCK_GROUP_DURATION % (duration * s_tc_scale / 1000000) % (duration * s_tc_scale % 1000000));
1200
1184
 
1201
1185
    } else if (Is<KaxReferenceBlock>(l3)) {
 
1186
      ++num_references;
 
1187
 
1202
1188
      int64_t reference = static_cast<KaxReferenceBlock *>(l3)->GetValue() * s_tc_scale;
1203
1189
 
1204
 
      if (0 >= reference) {
1205
 
        bref_found  = true;
1206
 
        reference  *= -1;
1207
 
        show_element(l3, 3, BF_BLOCK_GROUP_REFERENCE_1 % (reference / 1000000) % (reference % 1000000));
 
1190
      if (0 >= reference)
 
1191
        show_element(l3, 3, BF_BLOCK_GROUP_REFERENCE_1 % (std::abs(reference) / 1000000) % (std::abs(reference) % 1000000));
1208
1192
 
1209
 
      } else if (0 < reference) {
1210
 
        fref_found = true;
 
1193
      else if (0 < reference)
1211
1194
        show_element(l3, 3, BF_BLOCK_GROUP_REFERENCE_2 % (reference / 1000000) % (reference % 1000000));
1212
 
      }
1213
1195
 
1214
1196
    } else if (Is<KaxReferencePriority>(l3))
1215
1197
      show_element(l3, 3, BF_BLOCK_GROUP_REFERENCE_PRIORITY % static_cast<KaxReferencePriority *>(l3)->GetValue());
1294
1276
 
1295
1277
      if (bduration != -1.0)
1296
1278
        mxinfo(BF_BLOCK_GROUP_SUMMARY_WITH_DURATION
1297
 
               % (bref_found && fref_found ? 'B' : bref_found ? 'P' : !fref_found ? 'I' : 'P')
 
1279
               % (num_references >= 2 ? 'B' : num_references == 1 ? 'P' : 'I')
1298
1280
               % lf_tnum
1299
 
               % (lf_timecode / 1000000)
 
1281
               % boost::math::llround(lf_timecode / 1000000.0)
1300
1282
               % format_timecode(lf_timecode, 3)
1301
1283
               % bduration
1302
1284
               % frame_sizes[fidx]
1305
1287
               % position);
1306
1288
      else
1307
1289
        mxinfo(BF_BLOCK_GROUP_SUMMARY_NO_DURATION
1308
 
               % (bref_found && fref_found ? 'B' : bref_found ? 'P' : !fref_found ? 'I' : 'P')
 
1290
               % (num_references >= 2 ? 'B' : num_references == 1 ? 'P' : 'I')
1309
1291
               % lf_tnum
1310
 
               % (lf_timecode / 1000000)
 
1292
               % boost::math::llround(lf_timecode / 1000000.0)
1311
1293
               % format_timecode(lf_timecode, 3)
1312
1294
               % frame_sizes[fidx]
1313
1295
               % frame_adlers[fidx]
1318
1300
  } else if (g_options.m_verbose > 2)
1319
1301
    show_element(nullptr, 2,
1320
1302
                 BF_BLOCK_GROUP_SUMMARY_V2
1321
 
                 % (bref_found && fref_found ? 'B' : bref_found ? 'P' : !fref_found ? 'I' : 'P')
 
1303
                 % (num_references >= 2 ? 'B' : num_references == 1 ? 'P' : 'I')
1322
1304
                 % lf_tnum
1323
 
                 % (lf_timecode / 1000000));
 
1305
                 % boost::math::llround(lf_timecode / 1000000.0));
1324
1306
 
1325
1307
  track_info_t &tinfo = s_track_info[lf_tnum];
1326
1308
 
1327
 
  tinfo.m_blocks                                                                                 += frame_sizes.size();
1328
 
  tinfo.m_blocks_by_ref_num[bref_found && fref_found ? 2 : bref_found ? 1 : !fref_found ? 0 : 1] += frame_sizes.size();
1329
 
  tinfo.m_min_timecode                                                                             = std::min(tinfo.m_min_timecode, lf_timecode);
1330
 
  tinfo.m_size                                                                                    += boost::accumulate(frame_sizes, 0);
 
1309
  tinfo.m_blocks                                          += frame_sizes.size();
 
1310
  tinfo.m_blocks_by_ref_num[std::min(num_references, 2u)] += frame_sizes.size();
 
1311
  tinfo.m_min_timecode                                     = std::min(tinfo.m_min_timecode, lf_timecode);
 
1312
  tinfo.m_size                                            += boost::accumulate(frame_sizes, 0);
1331
1313
 
1332
1314
  if (!tinfo.max_timecode_unset() && (tinfo.m_max_timecode >= lf_timecode))
1333
1315
    return;
1353
1335
  block.SetParent(*cluster);
1354
1336
 
1355
1337
  int64_t frame_pos   = block.GetElementPosition() + block.ElementSize();
1356
 
  uint64_t timecode   = block.GlobalTimecode() / 1000000;
 
1338
  auto timecode_ns    = block.GlobalTimecode();
 
1339
  auto timecode_ms    = boost::math::llround(static_cast<double>(timecode_ns) / 1000000.0);
1357
1340
  track_info_t &tinfo = s_track_info[block.TrackNum()];
1358
1341
 
1359
1342
  std::string info;
1367
1350
               % info
1368
1351
               % block.TrackNum()
1369
1352
               % block.NumberFrames()
1370
 
               % ((float)timecode / 1000.0)
1371
 
               % format_timecode(block.GlobalTimecode(), 3));
 
1353
               % (timecode_ns / 1000000000.0)
 
1354
               % format_timecode(timecode_ns, 3));
1372
1355
 
1373
1356
  int i;
1374
1357
  for (i = 0; i < (int)block.NumberFrames(); i++) {
1375
1358
    DataBuffer &data = block.GetBuffer(i);
1376
 
    uint32_t adler   = calc_adler32(data.Buffer(), data.Size());
 
1359
    uint32_t adler   = mtx::checksum::calculate_as_uint(mtx::checksum::adler32, data.Buffer(), data.Size());
1377
1360
 
1378
1361
    std::string adler_str;
1379
1362
    if (g_options.m_calc_checksums)
1403
1386
      mxinfo(BF_SIMPLE_BLOCK_SUMMARY
1404
1387
             % (block.IsKeyframe() ? 'I' : block.IsDiscardable() ? 'B' : 'P')
1405
1388
             % block.TrackNum()
1406
 
             % timecode
1407
 
             % format_timecode(block.GlobalTimecode(), 3)
 
1389
             % timecode_ms
 
1390
             % format_timecode(timecode_ns, 3)
1408
1391
             % frame_sizes[fidx]
1409
1392
             % frame_adlers[fidx]
1410
1393
             % position);
1415
1398
                 BF_SIMPLE_BLOCK_SUMMARY_V2
1416
1399
                 % (block.IsKeyframe() ? 'I' : block.IsDiscardable() ? 'B' : 'P')
1417
1400
                 % block.TrackNum()
1418
 
                 % timecode);
 
1401
                 % timecode_ms);
1419
1402
 
1420
1403
  tinfo.m_blocks                                                                    += block.NumberFrames();
1421
1404
  tinfo.m_blocks_by_ref_num[block.IsKeyframe() ? 0 : block.IsDiscardable() ? 2 : 1] += block.NumberFrames();
1422
 
  tinfo.m_min_timecode                                                                = std::min(tinfo.m_min_timecode, static_cast<int64_t>(block.GlobalTimecode()));
1423
 
  tinfo.m_max_timecode                                                                = std::max(tinfo.m_min_timecode, static_cast<int64_t>(block.GlobalTimecode()));
 
1405
  tinfo.m_min_timecode                                                                = std::min(tinfo.m_min_timecode, static_cast<int64_t>(timecode_ns));
 
1406
  tinfo.m_max_timecode                                                                = std::max(tinfo.max_timecode_unset() ? 0 : tinfo.m_max_timecode, static_cast<int64_t>(timecode_ns));
1424
1407
  tinfo.m_add_duration_for_n_packets                                                  = block.NumberFrames();
1425
1408
  tinfo.m_size                                                                       += boost::accumulate(frame_sizes, 0);
1426
1409
}
1632
1615
 
1633
1616
    // Find the EbmlHead element. Must be the first one.
1634
1617
    l0 = es->FindNextID(EBML_INFO(EbmlHead), 0xFFFFFFFFL);
1635
 
    if (!l0) {
 
1618
    if (!l0 || !Is<EbmlHead>(l0)) {
1636
1619
      show_error(Y("No EBML head found."));
1637
1620
      delete es;
1638
1621
 
1763
1746
  else
1764
1747
    console_main();
1765
1748
 
1766
 
  mxexit(0);
 
1749
  mxexit();
1767
1750
}