summaryrefslogtreecommitdiff
path: root/src/iso11172-1.h
blob: e1121ab3838f2b1506b9dc39af8e39658aa4bdc4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/***************************************************************************
 *            iso11172-1.h
 *
 *  Wed Aug 31 13:48:30 CEST 2005
 *  Copyright  2005 Bent Bisballe Nyeng
 *  deva@aasimon.org
 ****************************************************************************/

/*
 *  This file is part of MIaV.
 *
 *  MIaV is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  MIaV is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with MIaV; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
 */

/*
 *  This file contains symbols used to create an ISO11172-1 compatible multiplexed 
 *  MPEG stream.
 */
#ifndef __MIAV_ISO11172_1_H__
#define __MIAV_ISO11172_1_H__

#include <stdint.h>

#define CLOCK_90KHZ 90000

namespace ISO11172_1 {
  ////////////////////////////////////////////////////
  // Types
  ////////////////////////////////////////////////////
  // 64 bits (8 bytes)
  typedef union {
    struct {
      uint64_t marker_bit3:1;
      uint64_t system_clock_reference3:15;
      uint64_t marker_bit2:1;
      uint64_t system_clock_reference2:15;
      uint64_t marker_bit1:1;
      uint64_t system_clock_reference1:3;
      uint64_t padding:4;
      uint64_t stuffing_byte:8;
      uint64_t packet_length:16;
    } bits;
    uint64_t ulli;
  } packet_header;

#define MASK3 0x7
#define MASK15 0x7FFF
#define TIMECODE32_30(x) ((x >> 30) & MASK3 )
#define TIMECODE29_15(x) ((x >> 15) & MASK15)
#define TIMECODE14_0(x)  ((x >>  0) & MASK15)

  typedef union { // <============ you are here...
    struct {
      uint64_t marker_bit5:1;
      uint64_t mux_rate:22;
      uint64_t marker_bit4:1;
      uint64_t marker_bit3:1;
      uint64_t system_clock_reference3:15;
      uint64_t marker_bit2:1;
      uint64_t system_clock_reference2:15;
      uint64_t marker_bit1:1;
      uint64_t system_clock_reference1:3;
      uint64_t padding:4;
    } bits;
    uint64_t ulli;
  } pack_header;

  typedef union {
    struct {
      uint32_t reserved_byte:8;
      uint32_t video_bound:5;
      uint32_t marker_bit:1;
      uint32_t system_video_clock_flag:1;
      uint32_t system_audio_clock_flag:1;
      uint32_t CSPS_flag:1;
      uint32_t fixed_flag:1;
      uint32_t audio_bound:6;
    } bits;
    uint32_t ulli;
  } system_header;

  typedef union {
    struct {
      uint32_t STD_buffer_size_bound:13;
      uint32_t STD_buffer_bound_scale:1;
      uint32_t market_bits:2;
      uint32_t stream_id:8;
    } bits;
    uint32_t uli;
  } stream_description;

  ////////////////////////////////////////////////////
  // Constants
  ////////////////////////////////////////////////////
  const char pack_start_code[]          = "\x00\x00\x01\xBA";
  const char system_header_start_code[] = "\x00\x00\x01\xBB";
  const char packet_start_code_prefix[] = "\x00\x00\x01";
  const char stream_id_video1[]         = "\xE3";
  const char stream_id_video2[]         = "\xE4";
  const char stream_id_video3[]         = "\xE5";
  const char stream_id_video4[]         = "\xE6";
  const char stream_id_video5[]         = "\xE7";
  const char stream_id_video6[]         = "\xE8";
  const char stream_id_video7[]         = "\xE9";
  const char stream_id_video8[]         = "\xEA";
  const char stream_id_audio1[]         = "\xC0";
  const char stream_id_audio2[]         = "\xC1";
  const char stream_id_audio3[]         = "\xC2";
  const char stream_id_audio4[]         = "\xC3";
  const char stream_id_audio5[]         = "\xC4";
  const char stream_id_audio6[]         = "\xC5";
  const char stream_id_audio7[]         = "\xC6";
  const char stream_id_audio8[]         = "\xC7";
  const char stream_id_padding[]        = "\xBE";
  const char end_code[]                 = "\x00\x00\x01\xB9";

  ////////////////////////////////////////////////////
  // Methods
  ////////////////////////////////////////////////////
  /**
   * SCR stands for System Clock Reference
   */
  inline uint32_t SCR(uint32_t previous_SCR,
                      uint32_t pack_header_size,
                      uint32_t packets_per_pack,
                      uint32_t packet_data_size,
                      uint32_t Rmux)
  {
    // To prevent a crash when doing division.
    if(Rmux == 0) Rmux = 1;
    return previous_SCR + (uint32_t)((double)(pack_header_size + 
                                              (packets_per_pack * packet_data_size)) * 
                                         (double)CLOCK_90KHZ / (double)Rmux);
  }

  /**
   * Calculates Rmux according to subclause A.6.4
   * mux stands for multiplexing and R for Rate,
   * so Rmux is the rate of the multiplexing.
   * IMPORTANT: The formula is wrong...
   * See
   *  https://www.iso.org/obp/ui/#iso:std:iso-iec:11172:-1:ed-1:v1:cor:2:v1:en
   * for the correct formula:
   * Rmux = (video_data_rate + audio_data_rate) *
   *        packet_header_size + pack_header_size / packets_per_pack
   * ( 1 + ---------------------------------------------------------- )
   *                             packet_data_size
   */
  inline uint32_t Rmux(uint32_t video_data_rate,
                       uint32_t audio_data_rate,
                       uint32_t packet_header_size,
                       uint32_t pack_header_size,
                       uint32_t packets_per_pack,
                       uint32_t packet_data_size)
  {
    // To prevent a crash when doing division.
    if(packets_per_pack == 0) packets_per_pack = 1;
    if(packet_data_size == 0) packet_data_size = 1;
    
    return (uint32_t)(
                      ((double)video_data_rate + (double)audio_data_rate) *
                      (1.0 + ((double)packet_header_size + (double)pack_header_size / (double)packets_per_pack) 
                       / (double)packet_data_size)
                      );
  }

  
};

#endif/*__MIAV_ISO11172_1_H__*/