1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: mpegvideo.c,v 1.21 2003/11/21 15:32:08 fenrir Exp $
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * Eric Petit <titer@videolan.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
25 /*****************************************************************************
26 * Problem with this implementation:
28 * Although we should time-stamp each picture with a PTS, this isn't possible
29 * with the current implementation.
30 * The problem comes from the fact that for non-low-delay streams we can't
31 * calculate the PTS of pictures used as backward reference. Even the temporal
32 * reference number doesn't help here because all the pictures don't
33 * necessarily have the same duration (eg. 3:2 pulldown).
35 * However this doesn't really matter as far as the MPEG muxers are concerned
36 * because they allow having empty PTS fields. --gibalou
37 *****************************************************************************/
39 /*****************************************************************************
41 *****************************************************************************/
43 #include <vlc/decoder.h>
44 #include <vlc/input.h>
46 #include "codecs.h" /* WAVEFORMATEX BITMAPINFOHEADER */
48 #include <stdlib.h> /* malloc(), free() */
49 #include <string.h> /* strdup() */
51 /*****************************************************************************
53 *****************************************************************************/
54 typedef struct packetizer_s
56 /* Input properties */
57 decoder_fifo_t *p_fifo;
58 bit_stream_t bit_stream;
60 /* Output properties */
61 sout_packetizer_input_t *p_sout_input;
62 es_format_t output_format;
64 mtime_t i_interpolated_dts;
65 mtime_t i_old_duration;
66 mtime_t i_last_ref_pts;
68 int i_progressive_sequence;
70 uint8_t p_sequence_header[150];
71 int i_sequence_header_length;
72 int i_last_sequence_header;
73 vlc_bool_t b_expect_discontinuity;
77 static int Open ( vlc_object_t * );
78 static int Run ( decoder_fifo_t * );
80 static int InitThread ( packetizer_t * );
81 static void PacketizeThread ( packetizer_t * );
82 static void EndThread ( packetizer_t * );
83 static void BitstreamCallback ( bit_stream_t *, vlc_bool_t );
85 /*****************************************************************************
87 *****************************************************************************/
90 set_description( _("MPEG-I/II video packetizer") );
91 set_capability( "packetizer", 50 );
92 set_callbacks( Open, NULL );
95 /*****************************************************************************
96 * OpenDecoder: probe the packetizer and return score
97 *****************************************************************************
98 * Tries to launch a decoder and return score so that the interface is able
100 *****************************************************************************/
101 static int Open( vlc_object_t *p_this )
103 decoder_t *p_dec = (decoder_t*)p_this;
105 if( p_dec->p_fifo->i_fourcc != VLC_FOURCC( 'm', 'p', 'g', 'v') &&
106 p_dec->p_fifo->i_fourcc != VLC_FOURCC( 'm', 'p', 'g', '1') &&
107 p_dec->p_fifo->i_fourcc != VLC_FOURCC( 'm', 'p', 'g', '2') )
116 /*****************************************************************************
117 * RunDecoder: this function is called just after the thread is created
118 *****************************************************************************/
119 static int Run( decoder_fifo_t *p_fifo )
121 packetizer_t *p_pack;
124 msg_Info( p_fifo, "Running mpegvideo packetizer" );
125 if( !( p_pack = malloc( sizeof( packetizer_t ) ) ) )
127 msg_Err( p_fifo, "out of memory" );
128 DecoderError( p_fifo );
131 memset( p_pack, 0, sizeof( packetizer_t ) );
133 p_pack->p_fifo = p_fifo;
135 if( InitThread( p_pack ) != 0 )
137 DecoderError( p_fifo );
141 while( ( !p_pack->p_fifo->b_die )&&( !p_pack->p_fifo->b_error ) )
143 PacketizeThread( p_pack );
147 if( ( b_error = p_pack->p_fifo->b_error ) )
149 DecoderError( p_pack->p_fifo );
168 /*****************************************************************************
169 * InitThread: initialize data before entering main loop
170 *****************************************************************************/
172 static int InitThread( packetizer_t *p_pack )
175 p_pack->output_format.i_cat = VIDEO_ES;
176 p_pack->output_format.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'v');
177 p_pack->output_format.video.i_width = 0;
178 p_pack->output_format.video.i_height = 0;
179 p_pack->output_format.i_bitrate= 0;
180 p_pack->output_format.i_extra = 0;
181 p_pack->output_format.p_extra = NULL;
183 p_pack->b_expect_discontinuity = 0;
184 p_pack->p_sout_input = NULL;
186 if( InitBitstream( &p_pack->bit_stream, p_pack->p_fifo,
187 BitstreamCallback, (void *)p_pack ) != VLC_SUCCESS )
189 msg_Err( p_pack->p_fifo, "cannot initialize bitstream" );
196 /* from ISO 13818-2 */
197 /* converting frame_rate_code to frame_rate */
198 static const double pd_frame_rates[16] =
200 0, 24000.0/1001, 24, 25, 30000.0/1001, 30, 50, 60000.0/1001, 60,
204 static int CopyUntilNextStartCode( packetizer_t *p_pack,
205 sout_buffer_t *p_sout_buffer,
206 unsigned int *pi_pos )
212 p_sout_buffer->p_buffer[(*pi_pos)++] =
213 GetBits( &p_pack->bit_stream, 8 );
216 if( *pi_pos + 2048 > p_sout_buffer->i_buffer_size )
218 sout_BufferRealloc( p_pack->p_sout_input->p_sout,
220 p_sout_buffer->i_buffer_size + 50 * 1024);
223 } while( ShowBits( &p_pack->bit_stream, 24 ) != 0x01 &&
224 !p_pack->p_fifo->b_die && !p_pack->p_fifo->b_error );
229 /*****************************************************************************
230 * PacketizeThread: packetize an unit (here copy a complete pes)
231 *****************************************************************************/
232 static void PacketizeThread( packetizer_t *p_pack )
234 sout_buffer_t *p_sout_buffer = NULL;
235 vlc_bool_t b_seen_slice = VLC_FALSE;
238 mtime_t i_duration; /* of the parsed picture */
243 /* needed to calculate pts/dts */
244 int i_temporal_ref = 0;
245 int i_picture_coding_type = 0;
246 int i_picture_structure = 0x03; /* frame picture */
247 int i_top_field_first = 0;
248 int i_repeat_first_field = 0;
249 int i_progressive_frame = 0;
251 if( !p_pack->p_sout_input )
253 byte_t p_temp[512];/* 150 bytes is the maximal size
254 of a sequence_header + sequence_extension */
255 int i_frame_rate_code;
258 /* skip data until we find a sequence_header_code */
259 /* TODO: store skipped somewhere so can send it to the mux
260 * after the input is created */
262 while( ShowBits( &p_pack->bit_stream, 32 ) != 0x1B3 &&
263 !p_pack->p_fifo->b_die && !p_pack->p_fifo->b_error )
265 RemoveBits( &p_pack->bit_stream, 8 );
268 msg_Warn( p_pack->p_fifo, "sequence_header_code found (%d skipped)",
271 /* copy the start_code */
273 GetChunk( &p_pack->bit_stream, p_temp, 4 ); i_pos += 4;
275 /* horizontal_size_value */
276 p_pack->output_format.video.i_width = ShowBits( &p_pack->bit_stream, 12 );
277 /* vertical_size_value */
278 p_pack->output_format.video.i_height= ShowBits( &p_pack->bit_stream, 24 ) & 0xFFF;
279 /* frame_rate_code */
280 i_frame_rate_code = ShowBits( &p_pack->bit_stream, 32 ) & 0xF;
283 GetChunk( &p_pack->bit_stream, p_temp + i_pos, 7 ); i_pos += 7;
285 /* intra_quantiser_matrix [non_intra_quantiser_matrix] */
286 if( ShowBits( &p_pack->bit_stream, 7 ) & 0x1 )
289 GetChunk( &p_pack->bit_stream, p_temp + i_pos, 64 ); i_pos += 64;
291 if( ShowBits( &p_pack->bit_stream, 8 ) & 0x1 )
293 GetChunk( &p_pack->bit_stream, p_temp + i_pos, 65); i_pos += 65;
296 /* non_intra_quantiser_matrix */
297 else if( ShowBits( &p_pack->bit_stream, 8 ) & 0x1 )
299 GetChunk( &p_pack->bit_stream, p_temp + i_pos, 65); i_pos += 65;
304 GetChunk( &p_pack->bit_stream, p_temp + i_pos, 1 ); i_pos += 1;
307 /* sequence_extension (10 bytes) */
308 if( ShowBits( &p_pack->bit_stream, 32 ) != 0x1B5 )
310 msg_Dbg( p_pack->p_fifo, "ARRGG no extension_start_code" );
311 p_pack->i_progressive_sequence = 1;
312 p_pack->i_low_delay = 1;
316 GetChunk( &p_pack->bit_stream, p_temp + i_pos, 10 );
317 p_pack->i_progressive_sequence = ( p_temp[i_pos+5]&0x08 ) ? 1 : 0;
318 p_pack->i_low_delay = ( p_temp[i_pos+9]&0x80 ) ? 1 : 0;
322 /* remember sequence_header and sequence_extention */
323 memcpy( p_pack->p_sequence_header, p_temp, i_pos );
324 p_pack->i_sequence_header_length = i_pos;
326 p_pack->d_frame_rate = pd_frame_rates[i_frame_rate_code];
328 msg_Warn( p_pack->p_fifo,
329 "creating input (image size %dx%d, frame rate %.2f)",
330 p_pack->output_format.video.i_width,
331 p_pack->output_format.video.i_height,
332 p_pack->d_frame_rate );
334 /* now we have informations to create the input */
335 p_pack->p_sout_input = sout_InputNew( p_pack->p_fifo,
336 &p_pack->output_format );
338 if( !p_pack->p_sout_input )
340 msg_Err( p_pack->p_fifo, "cannot add a new stream" );
341 p_pack->p_fifo->b_error = VLC_TRUE;
345 p_sout_buffer = sout_BufferNew( p_pack->p_sout_input->p_sout,
347 p_sout_buffer->i_size = i_pos;
348 memcpy( p_sout_buffer->p_buffer, p_temp, i_pos );
354 sout_BufferNew( p_pack->p_sout_input->p_sout, 100 * 1024 );
358 p_pack->i_last_sequence_header++;
363 if( p_pack->p_fifo->b_die || p_pack->p_fifo->b_error )
368 i_code = ShowBits( &p_pack->bit_stream, 32 );
370 if( b_seen_slice && ( i_code < 0x101 || i_code > 0x1af ) )
375 if( i_code == 0x1B8 ) /* GOP */
377 /* usefull for bad MPEG-1 : repeat the sequence_header
379 if( p_pack->i_last_sequence_header > (int) p_pack->d_frame_rate )
381 memcpy( p_sout_buffer->p_buffer + i_pos,
382 p_pack->p_sequence_header,
383 p_pack->i_sequence_header_length );
384 i_pos += p_pack->i_sequence_header_length;
385 p_pack->i_last_sequence_header = 0;
387 p_sout_buffer->i_flags |= SOUT_BUFFER_FLAGS_GOP;
388 CopyUntilNextStartCode( p_pack, p_sout_buffer, &i_pos );
390 else if( i_code == 0x100 ) /* Picture */
392 /* picture_start_code */
393 GetChunk( &p_pack->bit_stream,
394 p_sout_buffer->p_buffer + i_pos, 4 ); i_pos += 4;
396 NextPTS( &p_pack->bit_stream, &i_pts, &i_dts );
397 i_temporal_ref = ShowBits( &p_pack->bit_stream, 10 );
398 i_picture_coding_type = ShowBits( &p_pack->bit_stream, 13 ) & 0x3;
400 CopyUntilNextStartCode( p_pack, p_sout_buffer, &i_pos );
402 else if( i_code == 0x1b5 )
404 /* extention start code 32 */
405 GetChunk( &p_pack->bit_stream,
406 p_sout_buffer->p_buffer + i_pos, 4 ); i_pos += 4;
408 if( ShowBits( &p_pack->bit_stream, 4 ) == 0x08 )
410 /* picture coding extention */
412 /* extention start code identifier(b1000) 4 */
413 /* f_code[2][2] 16 */
414 /* intra_dc_precision 2 */
415 /* picture_structure 2 */
416 /* top_field_first 1 */
417 i_picture_structure =
418 ShowBits( &p_pack->bit_stream, 24 ) & 0x03;
420 ShowBits( &p_pack->bit_stream, 25 ) & 0x01;
421 i_repeat_first_field =
422 ShowBits( &p_pack->bit_stream, 31 ) & 0x01;
424 GetChunk( &p_pack->bit_stream,
425 p_sout_buffer->p_buffer + i_pos, 4 ); i_pos += 4;
427 i_progressive_frame =
428 ShowBits( &p_pack->bit_stream, 1 ) & 0x01;
430 CopyUntilNextStartCode( p_pack, p_sout_buffer, &i_pos );
434 if( i_code >= 0x101 && i_code <= 0x1af )
436 b_seen_slice = VLC_TRUE;
439 if( i_code == 0x1B3 )
441 p_pack->i_last_sequence_header = 0;
443 CopyUntilNextStartCode( p_pack, p_sout_buffer, &i_pos );
447 if( i_pts <= 0 && i_dts <= 0 && p_pack->i_interpolated_dts <= 0 )
449 msg_Dbg( p_pack->p_fifo, "need a starting pts/dts" );
450 sout_BufferDelete( p_pack->p_sout_input->p_sout, p_sout_buffer );
454 sout_BufferRealloc( p_pack->p_sout_input->p_sout,
455 p_sout_buffer, i_pos );
456 p_sout_buffer->i_size = i_pos;
458 /* calculate frame duration */
459 if( p_pack->i_progressive_sequence || i_picture_structure == 0x03)
461 i_duration = (mtime_t)( 1000000 / p_pack->d_frame_rate );
465 i_duration = (mtime_t)( 1000000 / p_pack->d_frame_rate / 2);
468 if( p_pack->i_progressive_sequence )
470 if( i_top_field_first == 0 && i_repeat_first_field == 1 )
472 i_duration = 2 * i_duration;
474 else if( i_top_field_first == 1 && i_repeat_first_field == 1 )
476 i_duration = 3 * i_duration;
481 if( i_picture_structure == 0x03 )
483 if( i_progressive_frame && i_repeat_first_field )
485 i_duration += i_duration / 2;
490 if( p_pack->i_low_delay || i_picture_coding_type == 0x03 )
492 /* Trivial case (DTS == PTS) */
493 /* Correct interpolated dts when we receive a new pts/dts */
494 if( i_pts > 0 ) p_pack->i_interpolated_dts = i_pts;
495 if( i_dts > 0 ) p_pack->i_interpolated_dts = i_dts;
499 /* Correct interpolated dts when we receive a new pts/dts */
500 if( p_pack->i_last_ref_pts )
501 p_pack->i_interpolated_dts = p_pack->i_last_ref_pts;
502 if( i_dts > 0 ) p_pack->i_interpolated_dts = i_dts;
504 p_pack->i_last_ref_pts = i_pts;
507 /* Don't even try to calculate the PTS unless it is given in the
509 p_sout_buffer->i_pts = i_pts ? i_pts : -1;
511 p_sout_buffer->i_dts = p_pack->i_interpolated_dts;
513 if( p_pack->i_low_delay || i_picture_coding_type == 0x03 )
515 /* Trivial case (DTS == PTS) */
516 p_pack->i_interpolated_dts += i_duration;
520 p_pack->i_interpolated_dts += p_pack->i_old_duration;
521 p_pack->i_old_duration = i_duration;
524 p_sout_buffer->i_length = p_pack->i_interpolated_dts -
525 p_sout_buffer->i_dts;
527 p_sout_buffer->i_bitrate = (int)( 8 * i_pos * p_pack->d_frame_rate );
530 msg_Dbg( p_pack->p_fifo, "------------> dts=%lld pts=%lld duration=%lld",
531 p_sout_buffer->i_dts, p_sout_buffer->i_pts,
532 p_sout_buffer->i_length );
535 if ( p_pack->b_expect_discontinuity )
537 msg_Warn( p_pack->p_fifo, "discontinuity encountered, dropping a frame" );
538 p_pack->b_expect_discontinuity = 0;
539 sout_BufferDelete( p_pack->p_sout_input->p_sout, p_sout_buffer );
543 sout_InputSendBuffer( p_pack->p_sout_input, p_sout_buffer );
548 /*****************************************************************************
549 * EndThread : packetizer thread destruction
550 *****************************************************************************/
551 static void EndThread ( packetizer_t *p_pack)
553 if( p_pack->p_sout_input )
555 sout_InputDelete( p_pack->p_sout_input );
559 /*****************************************************************************
560 * BitstreamCallback: Import parameters from the new data/PES packet
561 *****************************************************************************
562 * This function is called by input's NextDataPacket.
563 *****************************************************************************/
564 static void BitstreamCallback ( bit_stream_t * p_bit_stream,
565 vlc_bool_t b_new_pes )
567 packetizer_t * p_pack = (packetizer_t *)p_bit_stream->p_callback_arg;
569 if( p_bit_stream->p_data->b_discard_payload
570 || (b_new_pes && p_bit_stream->p_pes->b_discontinuity) )
572 p_pack->b_expect_discontinuity = 1;