]> git.sesse.net Git - vlc/blob - modules/packetizer/mpegvideo.c
* all: remove sout_format_t and use es_format_t instead.
[vlc] / modules / packetizer / mpegvideo.c
1 /*****************************************************************************
2  * mpegvideo.c
3  *****************************************************************************
4  * Copyright (C) 2001, 2002 VideoLAN
5  * $Id: mpegvideo.c,v 1.21 2003/11/21 15:32:08 fenrir 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     es_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     vlc_bool_t              b_expect_discontinuity;
74
75 } packetizer_t;
76
77 static int  Open    ( vlc_object_t * );
78 static int  Run     ( decoder_fifo_t * );
79
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 );
84
85 /*****************************************************************************
86  * Module descriptor
87  *****************************************************************************/
88
89 vlc_module_begin();
90     set_description( _("MPEG-I/II video packetizer") );
91     set_capability( "packetizer", 50 );
92     set_callbacks( Open, NULL );
93 vlc_module_end();
94
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
99  * to choose.
100  *****************************************************************************/
101 static int Open( vlc_object_t *p_this )
102 {
103     decoder_t *p_dec = (decoder_t*)p_this;
104
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') )
108     {
109         return VLC_EGENERIC;
110     }
111
112     p_dec->pf_run = Run;
113     return VLC_SUCCESS;
114 }
115
116 /*****************************************************************************
117  * RunDecoder: this function is called just after the thread is created
118  *****************************************************************************/
119 static int Run( decoder_fifo_t *p_fifo )
120 {
121     packetizer_t *p_pack;
122     int b_error;
123
124     msg_Info( p_fifo, "Running mpegvideo packetizer" );
125     if( !( p_pack = malloc( sizeof( packetizer_t ) ) ) )
126     {
127         msg_Err( p_fifo, "out of memory" );
128         DecoderError( p_fifo );
129         return( -1 );
130     }
131     memset( p_pack, 0, sizeof( packetizer_t ) );
132
133     p_pack->p_fifo = p_fifo;
134
135     if( InitThread( p_pack ) != 0 )
136     {
137         DecoderError( p_fifo );
138         return( -1 );
139     }
140
141     while( ( !p_pack->p_fifo->b_die )&&( !p_pack->p_fifo->b_error ) )
142     {
143         PacketizeThread( p_pack );
144     }
145
146
147     if( ( b_error = p_pack->p_fifo->b_error ) )
148     {
149         DecoderError( p_pack->p_fifo );
150     }
151
152     EndThread( p_pack );
153
154     if( p_pack )
155     {
156         free( p_pack );
157     }
158
159     if( b_error )
160     {
161         return( -1 );
162     }
163
164     return( 0 );
165 }
166
167
168 /*****************************************************************************
169  * InitThread: initialize data before entering main loop
170  *****************************************************************************/
171
172 static int InitThread( packetizer_t *p_pack )
173 {
174
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;
182
183     p_pack->b_expect_discontinuity = 0;
184     p_pack->p_sout_input = NULL;
185
186     if( InitBitstream( &p_pack->bit_stream, p_pack->p_fifo,
187                        BitstreamCallback, (void *)p_pack ) != VLC_SUCCESS )
188     {
189         msg_Err( p_pack->p_fifo, "cannot initialize bitstream" );
190         return -1;
191     }
192
193     return( 0 );
194 }
195
196 /* from ISO 13818-2 */
197 /* converting frame_rate_code to frame_rate */
198 static const double pd_frame_rates[16] =
199 {
200     0, 24000.0/1001, 24, 25, 30000.0/1001, 30, 50, 60000.0/1001, 60,
201     0, 0, 0, 0, 0, 0, 0
202 };
203
204 static int CopyUntilNextStartCode( packetizer_t   *p_pack,
205                                    sout_buffer_t  *p_sout_buffer,
206                                    unsigned int   *pi_pos )
207 {
208     int i_copy = 0;
209
210     do
211     {
212         p_sout_buffer->p_buffer[(*pi_pos)++] =
213                 GetBits( &p_pack->bit_stream, 8 );
214         i_copy++;
215
216         if( *pi_pos + 2048 > p_sout_buffer->i_buffer_size )
217         {
218             sout_BufferRealloc( p_pack->p_sout_input->p_sout,
219                                 p_sout_buffer,
220                                 p_sout_buffer->i_buffer_size + 50 * 1024);
221         }
222
223     } while( ShowBits( &p_pack->bit_stream, 24 ) != 0x01 &&
224              !p_pack->p_fifo->b_die && !p_pack->p_fifo->b_error );
225
226     return( i_copy );
227 }
228
229 /*****************************************************************************
230  * PacketizeThread: packetize an unit (here copy a complete pes)
231  *****************************************************************************/
232 static void PacketizeThread( packetizer_t *p_pack )
233 {
234     sout_buffer_t *p_sout_buffer = NULL;
235     vlc_bool_t    b_seen_slice = VLC_FALSE;
236     int32_t       i_pos;
237     int           i_skipped;
238     mtime_t       i_duration; /* of the parsed picture */
239
240     mtime_t       i_pts = 0;
241     mtime_t       i_dts = 0;
242
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;
250
251     if( !p_pack->p_sout_input )
252     {
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;
256
257
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 */
261         i_skipped = 0;
262         while( ShowBits( &p_pack->bit_stream, 32 ) != 0x1B3 &&
263                !p_pack->p_fifo->b_die && !p_pack->p_fifo->b_error )
264         {
265             RemoveBits( &p_pack->bit_stream, 8 );
266             i_skipped++;
267         }
268         msg_Warn( p_pack->p_fifo, "sequence_header_code found (%d skipped)",
269                  i_skipped );
270
271         /* copy the start_code */
272         i_pos = 0;
273         GetChunk( &p_pack->bit_stream, p_temp, 4 ); i_pos += 4;
274
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;
281
282         /* copy headers */
283         GetChunk( &p_pack->bit_stream, p_temp + i_pos, 7 ); i_pos += 7;
284
285         /* intra_quantiser_matrix [non_intra_quantiser_matrix] */
286         if( ShowBits( &p_pack->bit_stream, 7 ) & 0x1 )
287         {
288
289             GetChunk( &p_pack->bit_stream, p_temp + i_pos, 64 ); i_pos += 64;
290
291             if( ShowBits( &p_pack->bit_stream, 8 ) & 0x1 )
292             {
293                 GetChunk( &p_pack->bit_stream, p_temp + i_pos, 65); i_pos += 65;
294             }
295         }
296         /* non_intra_quantiser_matrix */
297         else if( ShowBits( &p_pack->bit_stream, 8 ) & 0x1 )
298         {
299             GetChunk( &p_pack->bit_stream, p_temp + i_pos, 65); i_pos += 65;
300         }
301         /* nothing */
302         else
303         {
304             GetChunk( &p_pack->bit_stream, p_temp + i_pos, 1 ); i_pos += 1;
305         }
306
307         /* sequence_extension (10 bytes) */
308         if( ShowBits( &p_pack->bit_stream, 32 ) != 0x1B5 )
309         {
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;
313         }
314         else
315         {
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;
319             i_pos += 10;
320         }
321
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;
325
326         p_pack->d_frame_rate =  pd_frame_rates[i_frame_rate_code];
327
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 );
333
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 );
337
338         if( !p_pack->p_sout_input )
339         {
340             msg_Err( p_pack->p_fifo, "cannot add a new stream" );
341             p_pack->p_fifo->b_error = VLC_TRUE;
342             return;
343         }
344
345         p_sout_buffer = sout_BufferNew( p_pack->p_sout_input->p_sout,
346                                         100 * 1024 );
347         p_sout_buffer->i_size = i_pos;
348         memcpy( p_sout_buffer->p_buffer, p_temp, i_pos );
349
350     }
351     else
352     {
353         p_sout_buffer =
354             sout_BufferNew( p_pack->p_sout_input->p_sout, 100 * 1024 );
355         i_pos = 0;
356     }
357
358     p_pack->i_last_sequence_header++;
359
360     for( ;; )
361     {
362         uint32_t    i_code;
363         if( p_pack->p_fifo->b_die || p_pack->p_fifo->b_error )
364         {
365             break;
366         }
367
368         i_code = ShowBits( &p_pack->bit_stream, 32 );
369
370         if( b_seen_slice && ( i_code < 0x101 || i_code > 0x1af ) )
371         {
372             break;
373         }
374
375         if( i_code == 0x1B8 ) /* GOP */
376         {
377             /* usefull for bad MPEG-1 : repeat the sequence_header
378                every second */
379             if( p_pack->i_last_sequence_header > (int) p_pack->d_frame_rate )
380             {
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;
386             }
387             p_sout_buffer->i_flags |= SOUT_BUFFER_FLAGS_GOP;
388             CopyUntilNextStartCode( p_pack, p_sout_buffer, &i_pos );
389         }
390         else if( i_code == 0x100 ) /* Picture */
391         {
392             /* picture_start_code */
393             GetChunk( &p_pack->bit_stream,
394                       p_sout_buffer->p_buffer + i_pos, 4 ); i_pos += 4;
395
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;
399
400             CopyUntilNextStartCode( p_pack, p_sout_buffer, &i_pos );
401         }
402         else if( i_code == 0x1b5 )
403         {
404             /* extention start code                   32 */
405             GetChunk( &p_pack->bit_stream,
406                       p_sout_buffer->p_buffer + i_pos, 4 ); i_pos += 4;
407
408             if( ShowBits( &p_pack->bit_stream, 4 ) == 0x08 )
409             {
410                 /* picture coding extention */
411
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;
419                 i_top_field_first =
420                     ShowBits( &p_pack->bit_stream, 25 ) & 0x01;
421                 i_repeat_first_field =
422                     ShowBits( &p_pack->bit_stream, 31 ) & 0x01;
423
424                 GetChunk( &p_pack->bit_stream,
425                           p_sout_buffer->p_buffer + i_pos, 4 ); i_pos += 4;
426
427                 i_progressive_frame =
428                     ShowBits( &p_pack->bit_stream, 1 ) & 0x01;
429             }
430             CopyUntilNextStartCode( p_pack, p_sout_buffer, &i_pos );
431         }
432         else
433         {
434             if( i_code >= 0x101 && i_code <= 0x1af )
435             {
436                 b_seen_slice = VLC_TRUE;
437             }
438
439             if( i_code == 0x1B3 )
440             {
441                 p_pack->i_last_sequence_header = 0;
442             }
443             CopyUntilNextStartCode( p_pack, p_sout_buffer, &i_pos );
444         }
445     }
446
447     if( i_pts <= 0 && i_dts <= 0 && p_pack->i_interpolated_dts <= 0 )
448     {
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 );
451         return;
452     }
453
454     sout_BufferRealloc( p_pack->p_sout_input->p_sout,
455                         p_sout_buffer, i_pos );
456     p_sout_buffer->i_size = i_pos;
457
458     /* calculate frame duration */
459     if( p_pack->i_progressive_sequence || i_picture_structure == 0x03)
460     {
461         i_duration = (mtime_t)( 1000000 / p_pack->d_frame_rate );
462     }
463     else
464     {
465         i_duration = (mtime_t)( 1000000 / p_pack->d_frame_rate / 2);
466     }
467
468     if( p_pack->i_progressive_sequence )
469     {
470         if( i_top_field_first == 0 && i_repeat_first_field == 1 )
471         {
472             i_duration = 2 * i_duration;
473         }
474         else if( i_top_field_first == 1 && i_repeat_first_field == 1 )
475         {
476             i_duration = 3 * i_duration;
477         }
478     }
479     else
480     {
481         if( i_picture_structure == 0x03 )
482         {
483             if( i_progressive_frame && i_repeat_first_field )
484             {
485                 i_duration += i_duration / 2;
486             }
487         }
488     }
489
490     if( p_pack->i_low_delay || i_picture_coding_type == 0x03 )
491     {
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;
496     }
497     else
498     {
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;
503
504         p_pack->i_last_ref_pts = i_pts;
505     }
506
507     /* Don't even try to calculate the PTS unless it is given in the
508      * original stream */
509     p_sout_buffer->i_pts = i_pts ? i_pts : -1;
510
511     p_sout_buffer->i_dts = p_pack->i_interpolated_dts;
512
513     if( p_pack->i_low_delay || i_picture_coding_type == 0x03 )
514     {
515         /* Trivial case (DTS == PTS) */
516         p_pack->i_interpolated_dts += i_duration;
517     }
518     else
519     {
520         p_pack->i_interpolated_dts += p_pack->i_old_duration;
521         p_pack->i_old_duration = i_duration;
522     }
523
524     p_sout_buffer->i_length = p_pack->i_interpolated_dts -
525                                 p_sout_buffer->i_dts;
526
527     p_sout_buffer->i_bitrate = (int)( 8 * i_pos * p_pack->d_frame_rate );
528
529 #if 0
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 );
533 #endif
534
535     if ( p_pack->b_expect_discontinuity )
536     {
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 );
540     }
541     else
542     {
543         sout_InputSendBuffer( p_pack->p_sout_input, p_sout_buffer );
544     }
545 }
546
547
548 /*****************************************************************************
549  * EndThread : packetizer thread destruction
550  *****************************************************************************/
551 static void EndThread ( packetizer_t *p_pack)
552 {
553     if( p_pack->p_sout_input )
554     {
555         sout_InputDelete( p_pack->p_sout_input );
556     }
557 }
558
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 )
566 {
567     packetizer_t * p_pack = (packetizer_t *)p_bit_stream->p_callback_arg;
568
569     if( p_bit_stream->p_data->b_discard_payload
570             || (b_new_pes && p_bit_stream->p_pes->b_discontinuity) )
571     {
572         p_pack->b_expect_discontinuity = 1;
573     }
574 }
575