]> git.sesse.net Git - vlc/blob - modules/packetizer/mpegvideo.c
* modules/packetizer/mpegvideo.c: Fixed a 3:2 pulldown bug (not tested).
[vlc] / modules / packetizer / mpegvideo.c
1 /*****************************************************************************
2  * mpegvideo.c
3  *****************************************************************************
4  * Copyright (C) 2001, 2002 VideoLAN
5  * $Id: mpegvideo.c,v 1.14 2003/06/06 13:34:21 gbazin Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *          Eric Petit <titer@videolan.org>
9  *
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.
14  *
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.
19  *
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  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <vlc/vlc.h>
29 #include <vlc/decoder.h>
30 #include <vlc/input.h>
31 #include <vlc/sout.h>
32 #include "codecs.h"                         /* WAVEFORMATEX BITMAPINFOHEADER */
33
34 #include <stdlib.h>                                      /* malloc(), free() */
35 #include <string.h>                                              /* strdup() */
36
37 /*****************************************************************************
38  * Local prototypes
39  *****************************************************************************/
40 typedef struct packetizer_s
41 {
42     /* Input properties */
43     decoder_fifo_t          *p_fifo;
44     bit_stream_t            bit_stream;
45
46     /* Output properties */
47     sout_packetizer_input_t *p_sout_input;
48     sout_format_t           output_format;
49
50     mtime_t                 i_last_dts;
51     mtime_t                 i_last_ref_pts;
52     double                  d_frame_rate;
53     int                     i_progressive_sequence;
54     uint8_t                 p_sequence_header[150];
55     int                     i_sequence_header_length;
56     int                     i_last_sequence_header;
57
58     int                     i_last_picture_structure;
59 } packetizer_t;
60
61 static int  Open    ( vlc_object_t * );
62 static int  Run     ( decoder_fifo_t * );
63
64 static int  InitThread     ( packetizer_t * );
65 static void PacketizeThread   ( packetizer_t * );
66 static void EndThread      ( packetizer_t * );
67
68 /*****************************************************************************
69  * Module descriptor
70  *****************************************************************************/
71
72 vlc_module_begin();
73     set_description( _("MPEG-I/II video packetizer") );
74     set_capability( "packetizer", 50 );
75     set_callbacks( Open, NULL );
76 vlc_module_end();
77
78 /*****************************************************************************
79  * OpenDecoder: probe the packetizer and return score
80  *****************************************************************************
81  * Tries to launch a decoder and return score so that the interface is able
82  * to choose.
83  *****************************************************************************/
84 static int Open( vlc_object_t *p_this )
85 {
86     decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
87
88     if( p_fifo->i_fourcc != VLC_FOURCC( 'm', 'p', 'g', 'v') &&
89         p_fifo->i_fourcc != VLC_FOURCC( 'm', 'p', 'g', '1') &&
90         p_fifo->i_fourcc != VLC_FOURCC( 'm', 'p', 'g', '2') )
91     {
92         return VLC_EGENERIC;
93     }
94
95     p_fifo->pf_run = Run;
96     return VLC_SUCCESS;
97 }
98
99 /*****************************************************************************
100  * RunDecoder: this function is called just after the thread is created
101  *****************************************************************************/
102 static int Run( decoder_fifo_t *p_fifo )
103 {
104     packetizer_t *p_pack;
105     int b_error;
106
107     msg_Info( p_fifo, "Running mpegvideo packetizer" );
108     if( !( p_pack = malloc( sizeof( packetizer_t ) ) ) )
109     {
110         msg_Err( p_fifo, "out of memory" );
111         DecoderError( p_fifo );
112         return( -1 );
113     }
114     memset( p_pack, 0, sizeof( packetizer_t ) );
115
116     p_pack->p_fifo = p_fifo;
117
118     if( InitThread( p_pack ) != 0 )
119     {
120         DecoderError( p_fifo );
121         return( -1 );
122     }
123
124     while( ( !p_pack->p_fifo->b_die )&&( !p_pack->p_fifo->b_error ) )
125     {
126         PacketizeThread( p_pack );
127     }
128
129
130     if( ( b_error = p_pack->p_fifo->b_error ) )
131     {
132         DecoderError( p_pack->p_fifo );
133     }
134
135     EndThread( p_pack );
136
137     if( p_pack )
138     {
139         free( p_pack );
140     }
141
142     if( b_error )
143     {
144         return( -1 );
145     }
146
147     return( 0 );
148 }
149
150
151 /*****************************************************************************
152  * InitThread: initialize data before entering main loop
153  *****************************************************************************/
154
155 static int InitThread( packetizer_t *p_pack )
156 {
157
158     p_pack->output_format.i_cat = VIDEO_ES;
159     p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'p', 'g', 'v');
160     p_pack->output_format.i_width  = 0;
161     p_pack->output_format.i_height = 0;
162     p_pack->output_format.i_bitrate= 0;
163     p_pack->output_format.i_extra_data = 0;
164     p_pack->output_format.p_extra_data = NULL;
165
166     p_pack->p_sout_input = NULL;
167
168     if( InitBitstream( &p_pack->bit_stream, p_pack->p_fifo,
169                        NULL, NULL ) != VLC_SUCCESS )
170     {
171         msg_Err( p_pack->p_fifo, "cannot initialize bitstream" );
172         return -1;
173     }
174
175     p_pack->i_last_picture_structure = 0x03; /* frame picture */
176     return( 0 );
177 }
178
179 /* from ISO 13818-2 */
180 /* converting frame_rate_code to frame_rate */
181 static const double pd_frame_rates[16] =
182 {
183     0, 24000/1001, 24, 25, 30000/1001, 30, 50, 60000/1001, 60,
184     0, 0, 0, 0, 0, 0, 0
185 };
186
187 static int CopyUntilNextStartCode( packetizer_t   *p_pack,
188                                    sout_buffer_t  *p_sout_buffer,
189                                    unsigned int   *pi_pos )
190 {
191     int i_copy = 0;
192
193     do
194     {
195         p_sout_buffer->p_buffer[(*pi_pos)++] =
196                 GetBits( &p_pack->bit_stream, 8 );
197         i_copy++;
198
199         if( *pi_pos + 2048 > p_sout_buffer->i_buffer_size )
200         {
201             sout_BufferRealloc( p_pack->p_sout_input->p_sout,
202                                 p_sout_buffer,
203                                 p_sout_buffer->i_buffer_size + 50 * 1024);
204         }
205
206     } while( ShowBits( &p_pack->bit_stream, 24 ) != 0x01 &&
207              !p_pack->p_fifo->b_die && !p_pack->p_fifo->b_error );
208
209     return( i_copy );
210 }
211
212 /*****************************************************************************
213  * PacketizeThread: packetize an unit (here copy a complete pes)
214  *****************************************************************************/
215 static void PacketizeThread( packetizer_t *p_pack )
216 {
217     sout_buffer_t *p_sout_buffer = NULL;
218     vlc_bool_t    b_seen_slice = VLC_FALSE;
219     int32_t       i_pos;
220     int           i_skipped;
221     mtime_t       i_duration; /* of the parsed picture */
222
223     mtime_t       i_pts;
224     mtime_t       i_dts;
225
226     /* needed to calculate pts/dts */
227     int i_temporal_ref = 0;
228     int i_picture_structure = 0x03; /* frame picture */
229     int i_top_field_first = 0;
230     int i_repeat_first_field = 0;
231     int i_progressive_frame = 0;
232
233     if( !p_pack->p_sout_input )
234     {
235         byte_t p_temp[512];/* 150 bytes is the maximal size
236                                of a sequence_header + sequence_extension */
237         int i_frame_rate_code;
238
239
240         /* skip data until we find a sequence_header_code */
241         /* TODO: store skipped somewhere so can send it to the mux
242          * after the input is created */
243         i_skipped = 0;
244         while( ShowBits( &p_pack->bit_stream, 32 ) != 0x1B3 &&
245                !p_pack->p_fifo->b_die && !p_pack->p_fifo->b_error )
246         {
247             RemoveBits( &p_pack->bit_stream, 8 );
248             i_skipped++;
249         }
250         msg_Warn( p_pack->p_fifo, "sequence_header_code found (%d skipped)",
251                  i_skipped );
252
253         /* copy the start_code */
254         i_pos = 0;
255         GetChunk( &p_pack->bit_stream, p_temp, 4 ); i_pos += 4;
256
257         /* horizontal_size_value */
258         p_pack->output_format.i_width = ShowBits( &p_pack->bit_stream, 12 );
259         /* vertical_size_value */
260         p_pack->output_format.i_height= ShowBits( &p_pack->bit_stream, 24 ) & 0xFFF;
261         /* frame_rate_code */
262         i_frame_rate_code = ShowBits( &p_pack->bit_stream, 32 ) & 0xF;
263
264         /* copy headers */
265         GetChunk( &p_pack->bit_stream, p_temp + i_pos, 7 ); i_pos += 7;
266
267         /* intra_quantiser_matrix [non_intra_quantiser_matrix] */
268         if( ShowBits( &p_pack->bit_stream, 7 ) & 0x1 )
269         {
270
271             GetChunk( &p_pack->bit_stream, p_temp + i_pos, 64 ); i_pos += 64;
272
273             if( ShowBits( &p_pack->bit_stream, 8 ) & 0x1 )
274             {
275                 GetChunk( &p_pack->bit_stream, p_temp + i_pos, 65); i_pos += 65;
276             }
277         }
278         /* non_intra_quantiser_matrix */
279         else if( ShowBits( &p_pack->bit_stream, 8 ) & 0x1 )
280         {
281             GetChunk( &p_pack->bit_stream, p_temp + i_pos, 65); i_pos += 65;
282         }
283         /* nothing */
284         else
285         {
286             GetChunk( &p_pack->bit_stream, p_temp + i_pos, 1 ); i_pos += 1;
287         }
288
289         /* sequence_extension (10 bytes) */
290         if( ShowBits( &p_pack->bit_stream, 32 ) != 0x1B5 )
291         {
292             msg_Dbg( p_pack->p_fifo, "ARRGG no extension_start_code" );
293             p_pack->i_progressive_sequence = 1;
294         }
295         else
296         {
297             GetChunk( &p_pack->bit_stream, p_temp + i_pos, 10 );
298             p_pack->i_progressive_sequence = ( p_temp[i_pos+5]&0x08 ) ? 1 : 0;
299
300             i_pos += 10;
301         }
302
303         /* remember sequence_header and sequence_extention */
304         memcpy( p_pack->p_sequence_header, p_temp, i_pos );
305         p_pack->i_sequence_header_length = i_pos;
306
307         p_pack->d_frame_rate =  pd_frame_rates[i_frame_rate_code];
308
309         msg_Warn( p_pack->p_fifo,
310                   "creating input (image size %dx%d, frame rate %.2f)",
311                   p_pack->output_format.i_width,
312                   p_pack->output_format.i_height,
313                   p_pack->d_frame_rate );
314
315         /* now we have informations to create the input */
316         p_pack->p_sout_input = sout_InputNew( p_pack->p_fifo,
317                                               &p_pack->output_format );
318
319         if( !p_pack->p_sout_input )
320         {
321             msg_Err( p_pack->p_fifo, "cannot add a new stream" );
322             p_pack->p_fifo->b_error = VLC_TRUE;
323             return;
324         }
325
326         p_sout_buffer = sout_BufferNew( p_pack->p_sout_input->p_sout,
327                                         100 * 1024 );
328         p_sout_buffer->i_size = i_pos;
329         memcpy( p_sout_buffer->p_buffer, p_temp, i_pos );
330
331     }
332     else
333     {
334         p_sout_buffer =
335                 sout_BufferNew( p_pack->p_sout_input->p_sout, 100 * 1024 );
336         i_pos = 0;
337     }
338
339     p_pack->i_last_sequence_header++;
340
341     for( ;; )
342     {
343         uint32_t    i_code;
344         if( p_pack->p_fifo->b_die || p_pack->p_fifo->b_error )
345         {
346             break;
347         }
348
349         i_code = ShowBits( &p_pack->bit_stream, 32 );
350
351         if( b_seen_slice && ( i_code < 0x101 || i_code > 0x1af ) )
352         {
353             break;
354         }
355
356         if( i_code == 0x1B8 ) /* GOP */
357         {
358             /* usefull for bad MPEG-1 : repeat the sequence_header
359                every second */
360             if( p_pack->i_last_sequence_header > (int) p_pack->d_frame_rate )
361             {
362                memcpy( p_sout_buffer->p_buffer + i_pos,
363                        p_pack->p_sequence_header,
364                        p_pack->i_sequence_header_length );
365                i_pos += p_pack->i_sequence_header_length;
366                p_pack->i_last_sequence_header = 0;
367             }
368 #if 1
369             p_pack->i_last_ref_pts =
370                    p_pack->i_last_dts +
371                         (mtime_t)( 1000000 / p_pack->d_frame_rate); /* FIXME */
372 #endif
373             CopyUntilNextStartCode( p_pack, p_sout_buffer, &i_pos );
374         }
375         else if( i_code == 0x100 ) /* Picture */
376         {
377             /* picture_start_code */
378             GetChunk( &p_pack->bit_stream,
379                       p_sout_buffer->p_buffer + i_pos, 4 ); i_pos += 4;
380
381             NextPTS( &p_pack->bit_stream, &i_pts, &i_dts );
382             i_temporal_ref = ShowBits( &p_pack->bit_stream, 10 );
383
384             CopyUntilNextStartCode( p_pack, p_sout_buffer, &i_pos );
385         }
386         else if( i_code == 0x1b5 )
387         {
388             /* extention start code                   32 */
389             GetChunk( &p_pack->bit_stream,
390                       p_sout_buffer->p_buffer + i_pos, 4 ); i_pos += 4;
391
392             if( ShowBits( &p_pack->bit_stream, 4 ) == 0x08 )
393             {
394                 /* picture coding extention */
395
396                 /* extention start code identifier(b1000)  4 */
397                 /* f_code[2][2]                           16 */
398                 /* intra_dc_precision                      2 */
399                 /* picture_structure                       2 */
400                 /* top_field_first                         1 */
401                 i_picture_structure =
402                     ShowBits( &p_pack->bit_stream, 24 ) & 0x03;
403                 i_top_field_first =
404                     ShowBits( &p_pack->bit_stream, 25 ) & 0x01;
405                 i_repeat_first_field =
406                     ShowBits( &p_pack->bit_stream, 31 ) & 0x01;
407
408                 GetChunk( &p_pack->bit_stream,
409                           p_sout_buffer->p_buffer + i_pos, 4 ); i_pos += 4;
410
411                 i_progressive_frame =
412                     ShowBits( &p_pack->bit_stream, 1 ) & 0x01;
413             }
414             CopyUntilNextStartCode( p_pack, p_sout_buffer, &i_pos );
415         }
416         else
417         {
418             if( i_code >= 0x101 && i_code <= 0x1af )
419             {
420                 b_seen_slice = VLC_TRUE;
421             }
422
423             if( i_code == 0x1B3 )
424             {
425                 p_pack->i_last_sequence_header = 0;
426             }
427             CopyUntilNextStartCode( p_pack, p_sout_buffer, &i_pos );
428         }
429     }
430
431     sout_BufferRealloc( p_pack->p_sout_input->p_sout,
432                         p_sout_buffer, i_pos );
433     p_sout_buffer->i_size = i_pos;
434
435     /* calculate dts/pts */
436     if( p_pack->i_progressive_sequence || i_picture_structure == 0x03)
437     {
438         i_duration = (mtime_t)( 1000000 / p_pack->d_frame_rate );
439     }
440     else
441     {
442         i_duration = (mtime_t)( 1000000 / p_pack->d_frame_rate / 2);
443     }
444
445     /* fix i_last_dts and i_last_ref_pts with i_dts and i_pts from stream */
446     if( i_dts <= 0 && p_pack->i_last_dts <= 0 )
447     {
448         msg_Dbg( p_pack->p_fifo, "need a starting pts" );
449         sout_BufferDelete( p_pack->p_sout_input->p_sout,
450                            p_sout_buffer );
451         return;
452     }
453
454 #if 1
455     if( i_dts > 0 )
456     {
457         //if( i_dts - p_pack->i_last_dts > 200000 ||
458         //    i_dts - p_pack->i_last_dts < 200000 )
459         {
460             p_pack->i_last_dts = i_dts;
461             if( i_pts > 0 )
462             {
463                 p_pack->i_last_ref_pts = i_pts -
464                     i_temporal_ref * (mtime_t)( 1000000 / p_pack->d_frame_rate );
465             }
466         }
467     }
468 #endif
469
470     p_sout_buffer->i_dts = p_pack->i_last_dts;
471     p_sout_buffer->i_pts = p_pack->i_last_ref_pts + 
472         i_temporal_ref * (mtime_t)( 1000000 / p_pack->d_frame_rate );
473     p_sout_buffer->i_length = i_duration;
474     p_sout_buffer->i_bitrate = (int)( 8 * i_pos * p_pack->d_frame_rate );
475     sout_InputSendBuffer( p_pack->p_sout_input, p_sout_buffer );
476
477     if( p_pack->i_progressive_sequence )
478     {
479         if( i_top_field_first == 0 && i_repeat_first_field == 0 )
480         {
481             p_pack->i_last_dts += i_duration;
482         }
483         else if( i_top_field_first == 0 && i_repeat_first_field == 1 )
484         {
485             p_pack->i_last_dts += 2 * i_duration;
486         }
487         else if( i_top_field_first == 1 && i_repeat_first_field == 1 )
488         {
489             p_pack->i_last_dts += 3 * i_duration;
490         }
491     }
492     else
493     {
494         if( i_picture_structure == 0x03 )
495         {
496             p_pack->i_last_dts += i_duration;
497
498             if( i_progressive_frame && i_repeat_first_field )
499             {
500                 p_pack->i_last_dts += i_duration / 2;
501             }
502         }
503         else if( i_picture_structure == p_pack->i_last_picture_structure )
504         {
505             p_pack->i_last_dts += 2 * i_duration;
506         }
507         else if( ( !i_top_field_first && i_picture_structure == 0x01 ) ||
508                  (  i_top_field_first && i_picture_structure == 0x02 ) )
509         {
510             p_pack->i_last_dts += 2 * i_duration;
511         }
512     }
513     p_pack->i_last_picture_structure = i_picture_structure;
514 }
515
516
517 /*****************************************************************************
518  * EndThread : packetizer thread destruction
519  *****************************************************************************/
520 static void EndThread ( packetizer_t *p_pack)
521 {
522     if( p_pack->p_sout_input )
523     {
524         sout_InputDelete( p_pack->p_sout_input );
525     }
526 }