Project

General

Profile

Bug #555 » mkvmerge_support_bad_mkvh264.patch

mkvmerge patch to fix bogus mkv - patrick boissonade, 2011-10-20 14:44

View differences:

mbunkus-mkvtoolnix-f0d7c65_modif/src/output/p_mpeg4_p10.cpp 2011-10-14 15:34:55.807127012 +0200
22 22
#include "merge/output_control.h"
23 23
#include "output/p_mpeg4_p10.h"
24 24

  
25
static uint32_t RB32(const uint8_t *d)
26
{
27
  return (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3];
28
}
29

  
30
static uint32_t RB24(const uint8_t *d)
31
{
32
  return (d[0] << 16) | (d[1] << 8) | d[2];
33
}
34

  
35
class mpeg4_p10_io
36
{
37
public:
38
	mpeg4_p10_io(uint32_t len);
39
	virtual ~mpeg4_p10_io();
40

  
41
	void	put_le16(unsigned int val);
42
	void	put_be16(unsigned int val);
43
	void	put_le24(unsigned int val);
44
	void	put_le32(unsigned int val);
45
	void	put_be32(unsigned int val);
46
	void	put_byte(unsigned int val);
47
	void    put_buffer(const uint8_t* buffer,unsigned int len);
48
	
49
	int32_t	flush		(uint8_t **buf);
50

  
51

  
52
	uint8_t		*_buffer;
53
	int			_buffer_pos;
54
	uint32_t	_buffer_size;
55

  
56
};
57

  
58

  
59
mpeg4_p10_io::mpeg4_p10_io(uint32_t len)
60
{
61
	_buffer_size = len;
62
	_buffer			= (uint8_t*)malloc(_buffer_size);
63
	_buffer_pos = 0;
64
}
65
mpeg4_p10_io::~mpeg4_p10_io()
66
{
67
}
68

  
69
int32_t mpeg4_p10_io::flush(uint8_t **buf)
70
{
71
	*buf = _buffer;
72
	return (_buffer_pos);
73
}
74

  
75
void mpeg4_p10_io::put_byte(unsigned int val)
76
{
77
	if ((_buffer_pos + 1) > _buffer_size) {
78
		_buffer_size += 1024;
79
		_buffer = (uint8_t*)realloc(_buffer,_buffer_size);
80
	}
81
	_buffer[_buffer_pos++] = val & 0xFF;
82
}
83
void mpeg4_p10_io::put_buffer(const uint8_t* buffer,unsigned int len)
84
{
85
	if ((_buffer_pos + len) > _buffer_size) {
86
		_buffer_size += len +1024;
87
		_buffer = (uint8_t*)realloc(_buffer,_buffer_size);
88
	}
89
	memcpy(_buffer+_buffer_pos,buffer,len);
90
	_buffer_pos += len;
91
}
92
void mpeg4_p10_io::put_le16(unsigned int val)
93
{
94
	put_byte(val);
95
	put_byte(val >> 8);
96
}
97

  
98
void mpeg4_p10_io::put_be16(unsigned int val)
99
{
100
	put_byte(val >> 8);
101
	put_byte(val);
102
}
103

  
104
void mpeg4_p10_io::put_le24(unsigned int val)
105
{
106
	put_le16(val & 0xffff);
107
	put_byte(val >> 16);
108
}
109
void mpeg4_p10_io::put_le32(unsigned int val)
110
{ 
111
	put_byte(val);
112
	put_byte(val >> 8);
113
	put_byte(val >> 16);
114
	put_byte(val >> 24);
115

  
116
}
117
void mpeg4_p10_io::put_be32(unsigned int val)
118
{ 
119
	put_byte(val >> 24);
120
	put_byte(val >> 16);
121
	put_byte(val >> 8);
122
	put_byte(val);
123

  
124
}
125

  
126
const uint8_t *avc_find_startcode(const uint8_t *p, const uint8_t *end)
127
{
128
	int i;
129
	
130
	uint32_t sc=0xFFFFFFFF;
131
	size_t len = (end -p)+1;
132
	for (i=0;i<len;i++)
133
	{
134
		sc = (sc <<8) | p[i];
135
		if((sc & 0xffffff00) == 0x00000100) {
136
			return p+i-3;
137
		}
138
		
139
	}
140
	return end;
141
}
142

  
143
int avc_parse_nal_units(mpeg4_p10_io *pb, const uint8_t *buf_in, int size)
144
{
145
    const uint8_t *p = buf_in;
146
    const uint8_t *end = p + size;
147
    const uint8_t *nal_start, *nal_end;
148

  
149

  
150
    size = 0;
151
    nal_start = avc_find_startcode(p, end);
152
    while (nal_start < end) {
153
        while(!*(nal_start++));
154
        if (nal_start >= end)
155
			break;
156
        nal_end = avc_find_startcode(nal_start, end);
157

  
158
		int l = nal_end - nal_start;
159

  
160
	    if (l) {
161
			pb->put_be32(l);
162
			//printf("l %d\n",l);
163
			pb->put_buffer(nal_start, l);
164
			size += 4 + l;
165
        }
166
        nal_start = nal_end;
167
	
168
    }
169
    //printf("size=%d\n", size);
170
    return size;
171
}
172

  
173

  
174
int avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size)
175
{
176
    mpeg4_p10_io pb(*size*2);
177
 
178
    avc_parse_nal_units(&pb, buf_in, *size);
179
	if (*buf)
180
		free(*buf);
181
    *size = pb.flush( buf);
182
    return 0;
183
}
184
static int isom_write_avcc(mpeg4_p10_io *pb, const uint8_t *data, int len)
185
{
186
    if (len > 6) {
187
        /* check for h264 start code */
188
        if (RB32(data) == 0x00000001 ||
189
            RB24(data) == 0x000001) {
190
            uint8_t *buf=NULL, *end, *start;
191
            uint32_t *sps_size_array=0, *pps_size_array=0;
192
            uint32_t pps_count=0,sps_count=0;
193
            uint8_t **sps_array=0, **pps_array=0;
194
            int i;
195

  
196
            int ret = avc_parse_nal_units_buf(data, &buf, &len);
197
            if (ret < 0)
198
                return ret;
199
            start = buf;
200
            end = buf + len;
201

  
202
            /* look for sps and pps */
203
            while (buf < end) {
204
                unsigned int size;
205
                uint8_t nal_type;
206
                size = RB32(buf);
207
                nal_type = buf[4] & 0x1f;
208
                if (nal_type == 7) { /* SPS */
209
                    sps_array = (uint8_t**)realloc(sps_array,sizeof(uint8_t*)*(sps_count+1));
210
                    sps_size_array = (uint32_t*)realloc(sps_size_array,sizeof(uint32_t)*(sps_count+1));
211
                    sps_array[sps_count] = buf + 4;
212
                    sps_size_array[sps_count] = size;
213
                    sps_count++;
214
                } else if (nal_type == 8) { /* PPS */
215
                    pps_size_array = (uint32_t*)realloc(pps_size_array,sizeof(uint32_t)*(pps_count+1));
216
                    pps_array = (uint8_t**)realloc(pps_array,sizeof (uint8_t*)*(pps_count+1));
217
                    pps_array[pps_count] = buf + 4;
218
                    pps_size_array[pps_count] = size;
219
                    pps_count++;
220
                }
221
                buf += size + 4;
222
            }
223
	    if(!sps_count || !pps_count) {
224
	      free(start);
225
              if (sps_count)
226
                free(sps_array);
227
              if (pps_count)
228
                free(pps_array);
229
	      return -1;
230
	    }
231

  
232
            pb->put_byte( 1); /* version */
233
            pb->put_byte( sps_array[0][1]); /* profile */
234
            pb->put_byte( sps_array[0][2]); /* profile compat */
235
            pb->put_byte( sps_array[0][3]); /* level */
236
            pb->put_byte( 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */
237
            pb->put_byte( 0xe0+sps_count); /* 3 bits reserved (111) + 5 bits number of sps (00001) */
238
            for (i=0;i<(int)sps_count;i++) {
239
              pb->put_be16( sps_size_array[i]);
240
              pb->put_buffer(sps_array[i], sps_size_array[i]);
241
            }
242

  
243
            pb->put_byte(pps_count); /* number of pps */
244
            for (i=0;i<(int)pps_count;i++) {
245
              pb->put_be16(pps_size_array[i]);
246
              pb->put_buffer(pps_array[i], pps_size_array[i]);
247
            }
248
            free(start);
249

  
250
            if (sps_count)
251
              free(sps_array);
252
            if (pps_count)
253
              free(pps_array);
254
        } else {
255
            //put_buffer(pb, data, len);
256
        }
257
    }
258
    return 0;
259
}
25 260
mpeg4_p10_video_packetizer_c::
26 261
mpeg4_p10_video_packetizer_c(generic_reader_c *p_reader,
27 262
                             track_info_c &p_ti,
......
32 267
  , m_nalu_size_len_src(0)
33 268
  , m_nalu_size_len_dst(0)
34 269
  , m_max_nalu_size(0)
270
  , m_header(0)
271
  , m_header_len(0)
35 272
{
273
	
36 274
  m_relaxed_timecode_checking = true;
37 275

  
38
  setup_nalu_size_len_change();
39 276

  
40
  if ((NULL != m_ti.m_private_data) && (0 < m_ti.m_private_size))
41
    set_codec_private(m_ti.m_private_data, m_ti.m_private_size);
277
  if ((NULL != m_ti.m_private_data) && (0 < m_ti.m_private_size))  {
278
	  
279
	uint8_t *privateData;
280
	int32_t privateDataLen;
281
	
282
	m_header_len = m_ti.m_private_size;
283
	m_header = (uint8_t *)malloc(m_header_len);
284
	memcpy(m_header,m_ti.m_private_data,m_header_len);
285
	mpeg4_p10_io pb(m_ti.m_private_size*2);
286
	isom_write_avcc(&pb, m_ti.m_private_data, m_ti.m_private_size);
287
	privateDataLen = pb.flush(&privateData);
288
	
289
    set_codec_private(privateData, privateDataLen);
290
    
291
    free( m_ti.m_private_data);
292
     m_ti.m_private_data = privateData;
293
     m_ti.m_private_size = privateDataLen;
294
  }
42 295

  
296
  setup_nalu_size_len_change();
43 297
  if (4 == m_nalu_size_len_dst)
44 298
    set_default_compression_method(COMPRESSION_MPEG4_P10);
45 299
}
46 300

  
47 301
void
48 302
mpeg4_p10_video_packetizer_c::set_headers() {
303
	
49 304
  if ((NULL != m_ti.m_private_data) && (0 < m_ti.m_private_size))
50 305
    extract_aspect_ratio();
51 306

  
......
54 309

  
55 310
void
56 311
mpeg4_p10_video_packetizer_c::extract_aspect_ratio() {
312
	
57 313
  uint32_t num, den;
58 314

  
59 315
  if (mpeg4::p10::extract_par(m_ti.m_private_data, m_ti.m_private_size, num, den) && (0 != num) && (0 != den)) {
......
71 327
  }
72 328
}
73 329

  
330

  
331

  
332
void
333
mpeg4_p10_video_packetizer_c::patch_packet(packet_cptr packet) {
334
	
335
  unsigned char *src = packet->data->get_buffer();
336
  int size           = packet->data->get_size();
337
  uint8_t*new_payload=0;
338
  uint32_t new_payload_len=0;
339

  
340
  if (!src || !size)
341
    return;
342
  mpeg4_p10_io pb(size*2);
343
    
344
  if (packet->is_key_frame() && m_header)
345
	avc_parse_nal_units(&pb, m_header, m_header_len);
346
  avc_parse_nal_units(&pb, src, size);
347
  
348
  new_payload_len = pb.flush( &new_payload);
349
  
350

  
351
	
352
  packet->data = memory_cptr(new memory_c((unsigned char *)safemalloc(new_payload_len), new_payload_len, true));
353

  
354
  // Copy the NALUs and write the new sized length field.
355
  unsigned char *dst = packet->data->get_buffer();
356
  memcpy(dst,new_payload,new_payload_len);
357

  
358
  packet->data->set_size(new_payload_len);
359
  
360
  free (new_payload);
361
}
362

  
74 363
int
75 364
mpeg4_p10_video_packetizer_c::process(packet_cptr packet) {
365
	
76 366
  if (VFT_PFRAMEAUTOMATIC == packet->bref) {
77 367
    packet->fref = -1;
78 368
    packet->bref = m_ref_timecode;
......
80 370

  
81 371
  m_ref_timecode = packet->timecode;
82 372

  
373
  
374
  patch_packet(packet);
83 375
  if (m_nalu_size_len_dst && (m_nalu_size_len_dst != m_nalu_size_len_src))
84 376
    change_nalu_size_len(packet);
85 377

  
......
91 383
connection_result_e
92 384
mpeg4_p10_video_packetizer_c::can_connect_to(generic_packetizer_c *src,
93 385
                                             std::string &error_message) {
386
	
94 387
  mpeg4_p10_video_packetizer_c *vsrc = dynamic_cast<mpeg4_p10_video_packetizer_c *>(src);
95 388
  if (NULL == vsrc)
96 389
    return CAN_CONNECT_NO_FORMAT;
......
109 402

  
110 403
void
111 404
mpeg4_p10_video_packetizer_c::setup_nalu_size_len_change() {
405
	
112 406
  if (!m_ti.m_private_data || (5 > m_ti.m_private_size))
113 407
    return;
114 408

  
115 409
  m_nalu_size_len_src = (m_ti.m_private_data[4] & 0x03) + 1;
116 410
  m_nalu_size_len_dst = m_nalu_size_len_src;
117

  
411
  
118 412
  if (!m_ti.m_nalu_size_length || (m_ti.m_nalu_size_length == m_nalu_size_len_src))
119 413
    return;
120 414

  
......
129 423

  
130 424
void
131 425
mpeg4_p10_video_packetizer_c::change_nalu_size_len(packet_cptr packet) {
426
	
132 427
  unsigned char *src = packet->data->get_buffer();
133 428
  int size           = packet->data->get_size();
134 429

  
......
146 441

  
147 442
    int nalu_size = 0;
148 443
    int i;
444
    
149 445
    for (i = 0; i < m_nalu_size_len_src; ++i)
150 446
      nalu_size = (nalu_size << 8) + src[src_pos + i];
151 447

  
......
160 456
    nalu_sizes.push_back(nalu_size);
161 457
  }
162 458

  
459
	
163 460
  // Allocate memory if the new NALU size length is greater
164 461
  // than the previous one. Otherwise reuse the existing memory.
165 462
  if (m_nalu_size_len_dst > m_nalu_size_len_src) {
......
167 464
    packet->data = memory_cptr(new memory_c((unsigned char *)safemalloc(new_size), new_size, true));
168 465
  }
169 466

  
467
	
170 468
  // Copy the NALUs and write the new sized length field.
171 469
  unsigned char *dst = packet->data->get_buffer();
172 470
  src_pos            = 0;
173 471
  int dst_pos        = 0;
174 472

  
473
	
175 474
  size_t i;
176 475
  for (i = 0; nalu_sizes.size() > i; ++i) {
177 476
    int nalu_size = nalu_sizes[i];
477
    
178 478

  
179 479
    int shift;
180 480
    for (shift = 0; shift < m_nalu_size_len_dst; ++shift)
......
186 486
    dst_pos += m_nalu_size_len_dst + nalu_size;
187 487
  }
188 488

  
489
	
189 490
  packet->data->set_size(dst_pos);
190 491
}
mbunkus-mkvtoolnix-f0d7c65_modif/src/output/p_mpeg4_p10.h 2011-10-12 15:37:44.508127017 +0200
22 22
protected:
23 23
  int m_nalu_size_len_src, m_nalu_size_len_dst;
24 24
  int64_t m_max_nalu_size;
25
  uint8_t* m_header;
26
  uint32_t m_header_len;
25 27

  
26 28
public:
27 29
  mpeg4_p10_video_packetizer_c(generic_reader_c *p_reader, track_info_c &p_ti, double fps, int width, int height);
......
38 40
  virtual void extract_aspect_ratio();
39 41
  virtual void setup_nalu_size_len_change();
40 42
  virtual void change_nalu_size_len(packet_cptr packet);
43
  virtual void patch_packet(packet_cptr packet);
41 44
};
42 45

  
43 46
#endif  // __P_MPEG4_P10_H
(3-3/6)