1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: mpegvideo.c,v 1.5 2003/01/20 02:15: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 /*****************************************************************************
27 *****************************************************************************/
29 #include <vlc/decoder.h>
30 #include <vlc/input.h>
32 #include "codecs.h" /* WAVEFORMATEX BITMAPINFOHEADER */
34 #include <stdlib.h> /* malloc(), free() */
35 #include <string.h> /* strdup() */
37 /*****************************************************************************
39 *****************************************************************************/
40 typedef struct packetizer_s
42 /* Input properties */
43 decoder_fifo_t *p_fifo;
44 bit_stream_t bit_stream;
46 /* Output properties */
47 sout_input_t *p_sout_input;
48 sout_packet_format_t output_format;
51 mtime_t i_last_ref_pts;
53 int i_progressive_sequence;
54 uint8_t p_sequence_header[150];
55 int i_sequence_header_length;
56 int i_last_sequence_header;
60 static int Open ( vlc_object_t * );
61 static int Run ( decoder_fifo_t * );
63 static int InitThread ( packetizer_t * );
64 static void PacketizeThread ( packetizer_t * );
65 static void EndThread ( packetizer_t * );
67 /*****************************************************************************
69 *****************************************************************************/
72 set_description( _("MPEG-I/II video packetizer") );
73 set_capability( "packetizer", 50 );
74 set_callbacks( Open, NULL );
77 /*****************************************************************************
78 * OpenDecoder: probe the packetizer and return score
79 *****************************************************************************
80 * Tries to launch a decoder and return score so that the interface is able
82 *****************************************************************************/
83 static int Open( vlc_object_t *p_this )
85 decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
87 if( p_fifo->i_fourcc != VLC_FOURCC( 'm', 'p', 'g', 'v') &&
88 p_fifo->i_fourcc != VLC_FOURCC( 'm', 'p', 'g', '1') &&
89 p_fifo->i_fourcc != VLC_FOURCC( 'm', 'p', 'g', '2') )
98 /*****************************************************************************
99 * RunDecoder: this function is called just after the thread is created
100 *****************************************************************************/
101 static int Run( decoder_fifo_t *p_fifo )
103 packetizer_t *p_pack;
106 msg_Info( p_fifo, "Running mpegvideo packetizer" );
107 if( !( p_pack = malloc( sizeof( packetizer_t ) ) ) )
109 msg_Err( p_fifo, "out of memory" );
110 DecoderError( p_fifo );
113 memset( p_pack, 0, sizeof( packetizer_t ) );
115 p_pack->p_fifo = p_fifo;
117 if( InitThread( p_pack ) != 0 )
119 DecoderError( p_fifo );
123 while( ( !p_pack->p_fifo->b_die )&&( !p_pack->p_fifo->b_error ) )
125 PacketizeThread( p_pack );
129 if( ( b_error = p_pack->p_fifo->b_error ) )
131 DecoderError( p_pack->p_fifo );
150 /*****************************************************************************
151 * InitThread: initialize data before entering main loop
152 *****************************************************************************/
154 static int InitThread( packetizer_t *p_pack )
157 p_pack->output_format.i_cat = VIDEO_ES;
158 p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'p', 'g', 'v');
160 p_pack->p_sout_input = NULL;
162 if( InitBitstream( &p_pack->bit_stream, p_pack->p_fifo,
163 NULL, NULL ) != VLC_SUCCESS )
165 msg_Err( p_pack->p_fifo, "cannot initialize bitstream" );
172 /* from ISO 13818-2 */
173 /* converting frame_rate_code to frame_rate */
174 static const double pd_frame_rates[16] =
176 0, 24000/1001, 24, 25, 30000/1001, 30, 50, 60000/1001, 60,
180 static int CopyUntilNextStartCode( packetizer_t *p_pack,
181 sout_buffer_t *p_sout_buffer,
188 p_sout_buffer->p_buffer[(*pi_pos)++] =
189 GetBits( &p_pack->bit_stream, 8 );
192 if( *pi_pos + 2048 > p_sout_buffer->i_buffer_size )
194 sout_BufferRealloc( p_pack->p_sout_input->p_sout,
196 p_sout_buffer->i_buffer_size + 50 * 1024);
199 } while( ShowBits( &p_pack->bit_stream, 24 ) != 0x01 &&
200 !p_pack->p_fifo->b_die && !p_pack->p_fifo->b_error );
205 /*****************************************************************************
206 * PacketizeThread: packetize an unit (here copy a complete pes)
207 *****************************************************************************/
208 static void PacketizeThread( packetizer_t *p_pack )
210 sout_buffer_t *p_sout_buffer = NULL;
212 int i_temporal_ref = 0;
215 if( !p_pack->p_sout_input )
217 byte_t p_temp[512];/* 150 bytes is the maximal size
218 of a sequence_header + sequence_extension */
219 int i_frame_rate_code;
220 BITMAPINFOHEADER *p_bih;
222 p_bih = malloc( sizeof( BITMAPINFOHEADER ) );
223 p_pack->output_format.p_format = (void*)p_bih;
225 /* skip data until we find a sequence_header_code */
226 /* TODO: store skipped somewhere so can send it to the mux
227 * after the input is created */
229 while( ShowBits( &p_pack->bit_stream, 32 ) != 0x1B3 )
231 RemoveBits( &p_pack->bit_stream, 8 );
234 msg_Warn( p_pack->p_fifo, "sequence_header_code found (%d skipped)",
237 /* copy the start_code */
239 GetChunk( &p_pack->bit_stream, p_temp, 4 ); i_pos += 4;
241 p_bih->biSize = sizeof( BITMAPINFOHEADER );
242 /* horizontal_size_value */
243 p_bih->biWidth = ShowBits( &p_pack->bit_stream, 12 );
244 /* vertical_size_value */
245 p_bih->biHeight = ShowBits( &p_pack->bit_stream, 24 ) & 0xFFF;
246 /* frame_rate_code */
247 i_frame_rate_code = ShowBits( &p_pack->bit_stream, 32 ) & 0xF;
249 p_bih->biBitCount = 0;
250 p_bih->biCompression = VLC_FOURCC( 'm', 'p', 'g', '2' );
251 p_bih->biSizeImage = 0;
252 p_bih->biXPelsPerMeter = 0;
253 p_bih->biYPelsPerMeter = 0;
254 p_bih->biClrUsed = 0;
255 p_bih->biClrImportant = 0;
258 GetChunk( &p_pack->bit_stream, p_temp + i_pos, 7 ); i_pos += 7;
260 /* intra_quantiser_matrix [non_intra_quantiser_matrix] */
261 if( ShowBits( &p_pack->bit_stream, 7 ) & 0x1 )
264 GetChunk( &p_pack->bit_stream, p_temp + i_pos, 64 ); i_pos += 64;
266 if( ShowBits( &p_pack->bit_stream, 8 ) & 0x1 )
268 GetChunk( &p_pack->bit_stream, p_temp + i_pos, 65); i_pos += 65;
271 /* non_intra_quantiser_matrix */
272 else if( ShowBits( &p_pack->bit_stream, 8 ) & 0x1 )
274 GetChunk( &p_pack->bit_stream, p_temp + i_pos, 65); i_pos += 65;
279 GetChunk( &p_pack->bit_stream, p_temp + i_pos, 1 ); i_pos += 1;
282 /* sequence_extension (10 bytes) */
283 if( ShowBits( &p_pack->bit_stream, 32 ) != 0x1B5 )
285 msg_Dbg( p_pack->p_fifo, "ARRGG no extension_start_code" );
286 p_pack->i_progressive_sequence = 1;
290 GetChunk( &p_pack->bit_stream, p_temp + i_pos, 10 );
291 p_pack->i_progressive_sequence = ( p_temp[i_pos+5]&0x08 ) ? 1 : 0;
296 /* remember sequence_header and sequence_extention */
297 memcpy( p_pack->p_sequence_header, p_temp, i_pos );
298 p_pack->i_sequence_header_length = i_pos;
300 p_pack->d_frame_rate = pd_frame_rates[i_frame_rate_code];
302 msg_Warn( p_pack->p_fifo,
303 "creating input (image size %dx%d, frame rate %.2f)",
304 p_bih->biWidth, p_bih->biHeight, p_pack->d_frame_rate );
306 /* now we have informations to create the input */
307 p_pack->p_sout_input = sout_InputNew( p_pack->p_fifo,
308 &p_pack->output_format );
310 if( !p_pack->p_sout_input )
312 msg_Err( p_pack->p_fifo, "cannot add a new stream" );
316 p_sout_buffer = sout_BufferNew( p_pack->p_sout_input->p_sout,
318 p_sout_buffer->i_size = i_pos;
319 memcpy( p_sout_buffer->p_buffer, p_temp, i_pos );
325 sout_BufferNew( p_pack->p_sout_input->p_sout, 100 * 1024 );
329 p_pack->i_last_sequence_header++;
334 if( p_pack->p_fifo->b_die || p_pack->p_fifo->b_error )
339 i_code = ShowBits( &p_pack->bit_stream, 32 );
341 if( i_code == 0x1B8 ) /* GOP */
343 /* usefull for bad MPEG-1 : repeat the sequence_header
345 if( p_pack->i_last_sequence_header > (int) p_pack->d_frame_rate )
347 memcpy( p_sout_buffer->p_buffer + i_pos,
348 p_pack->p_sequence_header,
349 p_pack->i_sequence_header_length );
350 i_pos += p_pack->i_sequence_header_length;
351 p_pack->i_last_sequence_header = 0;
354 p_pack->i_last_ref_pts =
355 p_pack->i_last_dts + 40000; /* FIXME */
356 CopyUntilNextStartCode( p_pack, p_sout_buffer, &i_pos );
358 else if( i_code == 0x100 ) /* Picture */
360 /* picture_start_code */
361 GetChunk( &p_pack->bit_stream,
362 p_sout_buffer->p_buffer + i_pos, 4 ); i_pos += 4;
363 i_temporal_ref = ShowBits( &p_pack->bit_stream, 10 );
365 CopyUntilNextStartCode( p_pack, p_sout_buffer, &i_pos );
370 if( i_code == 0x1B3 )
372 p_pack->i_last_sequence_header = 0;
374 CopyUntilNextStartCode( p_pack, p_sout_buffer, &i_pos );
378 sout_BufferRealloc( p_pack->p_sout_input->p_sout,
379 p_sout_buffer, i_pos );
380 p_sout_buffer->i_size = i_pos;
382 p_sout_buffer->i_dts = p_pack->i_last_dts;
383 p_sout_buffer->i_pts = p_pack->i_last_ref_pts +
384 i_temporal_ref * (mtime_t)( 1000000 / p_pack->d_frame_rate );
386 msg_Dbg( p_pack->p_fifo, "dts:%lld pst:%lld tmp_ref:%d",
387 p_sout_buffer->i_dts, p_sout_buffer->i_pts, i_temporal_ref );
389 p_sout_buffer->i_length = (uint64_t)1000000 / p_pack->d_frame_rate;
390 p_sout_buffer->i_bitrate = (int)( 8 * i_pos * p_pack->d_frame_rate );
392 // msg_Dbg( p_pack->p_fifo, "frame length %d b", i_pos );
394 sout_InputSendBuffer( p_pack->p_sout_input, p_sout_buffer );
396 if( p_pack->i_progressive_sequence )
398 p_pack->i_last_dts += (mtime_t)( 1000000 / p_pack->d_frame_rate );
402 p_pack->i_last_dts += (mtime_t)( 1000000 / p_pack->d_frame_rate / 2 );
407 /*****************************************************************************
408 * EndThread : packetizer thread destruction
409 *****************************************************************************/
410 static void EndThread ( packetizer_t *p_pack)
412 if( p_pack->p_sout_input )
414 sout_InputDelete( p_pack->p_sout_input );