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