1 /*****************************************************************************
2 * ffmpeg.c: video decoder using ffmpeg library
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: ffmpeg.c,v 1.9 2002/05/13 21:55:30 fenrir Exp $
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
27 #include <stdlib.h> /* malloc(), free() */
29 #include <videolan/vlc.h>
32 #include <unistd.h> /* getpid() */
38 #ifdef HAVE_SYS_TIMES_H
39 # include <sys/times.h>
43 #include "video_output.h"
45 #include "stream_control.h"
46 #include "input_ext-dec.h"
47 #include "input_ext-intf.h"
48 #include "input_ext-plugins.h"
51 #include "vdec_ext-plugins.h"
52 #include "avcodec.h" /* ffmpeg */
58 static int decoder_Probe ( u8 * );
59 static int decoder_Run ( decoder_config_t * );
60 static int InitThread ( videodec_thread_t * );
61 static void EndThread ( videodec_thread_t * );
62 static void DecodeThread ( videodec_thread_t * );
65 static int b_ffmpeginit = 0;
67 /*****************************************************************************
69 *****************************************************************************/
70 void _M( vdec_getfunctions )( function_list_t * p_function_list )
72 p_function_list->functions.dec.pf_probe = decoder_Probe;
73 p_function_list->functions.dec.pf_run = decoder_Run;
76 /*****************************************************************************
77 * Build configuration tree.
78 *****************************************************************************/
84 SET_DESCRIPTION( "ffmpeg video decoder (MSMPEG4v123,MPEG4)" )
85 ADD_CAPABILITY( DECODER, 70 )
86 ADD_SHORTCUT( "ffmpeg" )
90 _M( vdec_getfunctions )( &p_module->p_functions->dec );
93 MODULE_DEACTIVATE_START
94 MODULE_DEACTIVATE_STOP
97 static __inline__ u16 __GetWordLittleEndianFromBuff( byte_t *p_buff )
100 i = (*p_buff) + ( *(p_buff + 1) <<8 );
104 static __inline__ u32 __GetDoubleWordLittleEndianFromBuff( byte_t *p_buff )
107 i = (*p_buff) + ( *(p_buff + 1) <<8 ) +
108 ( *(p_buff + 2) <<16 ) + ( *(p_buff + 3) <<24 );
112 /*****************************************************************************
113 * decoder_Probe: probe the decoder and return score
114 *****************************************************************************
115 * Tries to launch a decoder and return score so that the interface is able
117 *****************************************************************************/
118 static int decoder_Probe( u8 *pi_type )
122 #if LIBAVCODEC_BUILD >= 4608
123 case( MSMPEG4v1_VIDEO_ES):
124 case( MSMPEG4v2_VIDEO_ES):
126 case( MSMPEG4v3_VIDEO_ES):
127 case( MPEG4_VIDEO_ES ):
134 /*****************************************************************************
136 *****************************************************************************/
138 static void __ParseBitMapInfoHeader( bitmapinfoheader_t *h, byte_t *p_data )
140 h->i_size = __GetDoubleWordLittleEndianFromBuff( p_data );
141 h->i_width = __GetDoubleWordLittleEndianFromBuff( p_data + 4 );
142 h->i_height = __GetDoubleWordLittleEndianFromBuff( p_data + 8 );
143 h->i_planes = __GetWordLittleEndianFromBuff( p_data + 12 );
144 h->i_bitcount = __GetWordLittleEndianFromBuff( p_data + 14 );
145 h->i_compression = __GetDoubleWordLittleEndianFromBuff( p_data + 16 );
146 h->i_sizeimage = __GetDoubleWordLittleEndianFromBuff( p_data + 20 );
147 h->i_xpelspermeter = __GetDoubleWordLittleEndianFromBuff( p_data + 24 );
148 h->i_ypelspermeter = __GetDoubleWordLittleEndianFromBuff( p_data + 28 );
149 h->i_clrused = __GetDoubleWordLittleEndianFromBuff( p_data + 32 );
150 h->i_clrimportant = __GetDoubleWordLittleEndianFromBuff( p_data + 36 );
152 /* get the first pes from fifo */
153 static pes_packet_t *__PES_GET( decoder_fifo_t *p_fifo )
157 vlc_mutex_lock( &p_fifo->data_lock );
159 /* if fifo is emty wait */
160 while( !p_fifo->p_first )
164 vlc_mutex_unlock( &p_fifo->data_lock );
167 vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
169 p_pes = p_fifo->p_first;
171 vlc_mutex_unlock( &p_fifo->data_lock );
175 /* free the first pes and go to next */
176 static void __PES_NEXT( decoder_fifo_t *p_fifo )
178 pes_packet_t *p_next;
180 vlc_mutex_lock( &p_fifo->data_lock );
182 p_next = p_fifo->p_first->p_next;
183 p_fifo->p_first->p_next = NULL;
184 input_DeletePES( p_fifo->p_packets_mgt, p_fifo->p_first );
185 p_fifo->p_first = p_next;
188 if( !p_fifo->p_first )
190 /* No PES in the fifo */
191 /* pp_last no longer valid */
192 p_fifo->pp_last = &p_fifo->p_first;
193 while( !p_fifo->p_first )
195 vlc_cond_signal( &p_fifo->data_wait );
196 vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
199 vlc_mutex_unlock( &p_fifo->data_lock );
202 static __inline__ void __GetFrame( videodec_thread_t *p_vdec )
205 data_packet_t *p_data;
208 p_pes = __PES_GET( p_vdec->p_fifo );
209 p_vdec->i_pts = p_pes->i_pts;
211 while( ( !p_pes->i_nb_data )||( !p_pes->i_pes_size ) )
213 __PES_NEXT( p_vdec->p_fifo );
214 p_pes = __PES_GET( p_vdec->p_fifo );
216 p_vdec->i_framesize = p_pes->i_pes_size;
217 if( p_pes->i_nb_data == 1 )
219 p_vdec->p_framedata = p_pes->p_first->p_payload_start;
222 /* get a buffer and gather all data packet */
223 p_vdec->p_framedata = p_buffer = malloc( p_pes->i_pes_size );
224 p_data = p_pes->p_first;
227 FAST_MEMCPY( p_buffer,
228 p_data->p_payload_start,
229 p_data->p_payload_end - p_data->p_payload_start );
230 p_buffer += p_data->p_payload_end - p_data->p_payload_start;
231 p_data = p_data->p_next;
235 static __inline__ void __NextFrame( videodec_thread_t *p_vdec )
239 p_pes = __PES_GET( p_vdec->p_fifo );
240 if( p_pes->i_nb_data != 1 )
242 free( p_vdec->p_framedata ); /* FIXME keep this buffer */
244 __PES_NEXT( p_vdec->p_fifo );
249 /*****************************************************************************
250 * decoder_Run: this function is called just after the thread is created
251 *****************************************************************************/
252 static int decoder_Run ( decoder_config_t * p_config )
254 videodec_thread_t *p_vdec;
257 if ( (p_vdec = (videodec_thread_t*)malloc( sizeof(videodec_thread_t)))
260 intf_ErrMsg( "vdec error: not enough memory "
261 "for vdec_CreateThread() to create the new thread");
262 DecoderError( p_config->p_decoder_fifo );
265 memset( p_vdec, 0, sizeof( videodec_thread_t ) );
267 p_vdec->p_fifo = p_config->p_decoder_fifo;
268 p_vdec->p_config = p_config;
270 if( InitThread( p_vdec ) != 0 )
272 DecoderError( p_config->p_decoder_fifo );
276 while( (!p_vdec->p_fifo->b_die) && (!p_vdec->p_fifo->b_error) )
278 /* decode a picture */
279 DecodeThread( p_vdec );
282 if( ( b_error = p_vdec->p_fifo->b_error ) )
284 DecoderError( p_vdec->p_fifo );
297 /*****************************************************************************
298 * InitThread: initialize vdec output thread
299 *****************************************************************************
300 * This function is called from decoder_Run and performs the second step
301 * of the initialization. It returns 0 on success. Note that the thread's
302 * flag are not modified inside this function.
303 *****************************************************************************/
304 static int InitThread( videodec_thread_t *p_vdec )
307 if( p_vdec->p_config->p_demux_data != NULL )
309 __ParseBitMapInfoHeader( &p_vdec->format,
310 (byte_t*)p_vdec->p_config->p_demux_data );
314 intf_ErrMsg( "vdec error: cannot get informations" );
322 avcodec_register_all();
324 intf_WarnMsg( 1, "vdec init: library ffmpeg initialised" );
328 intf_WarnMsg( 1, "vdec init: library ffmpeg already initialised" );
331 switch( p_vdec->p_config->i_type)
333 #if LIBAVCODEC_BUILD >= 4608 /* what is the true version */
334 case( MSMPEG4v1_VIDEO_ES):
335 p_vdec->p_codec = avcodec_find_decoder( CODEC_ID_MSMPEG4V1 );
336 p_vdec->psz_namecodec = "MS MPEG-4 v1";
338 case( MSMPEG4v2_VIDEO_ES):
339 p_vdec->p_codec = avcodec_find_decoder( CODEC_ID_MSMPEG4V2 );
340 p_vdec->psz_namecodec = "MS MPEG-4 v2";
342 case( MSMPEG4v3_VIDEO_ES):
343 p_vdec->p_codec = avcodec_find_decoder( CODEC_ID_MSMPEG4V3 );
344 p_vdec->psz_namecodec = "MS MPEG-4 v3";
347 /* fallback on this */
348 case( MSMPEG4v3_VIDEO_ES):
349 p_vdec->p_codec = avcodec_find_decoder( CODEC_ID_MSMPEG4 );
350 p_vdec->psz_namecodec = "MS MPEG-4";
353 case( MPEG4_VIDEO_ES):
354 p_vdec->p_codec = avcodec_find_decoder( CODEC_ID_MPEG4 );
355 p_vdec->psz_namecodec = "MPEG-4";
358 p_vdec->p_codec = NULL;
359 p_vdec->psz_namecodec = "Unknown";
362 if( !p_vdec->p_codec )
364 intf_ErrMsg( "vdec error: codec not found (%s)",
365 p_vdec->psz_namecodec );
369 p_vdec->p_context = &p_vdec->context;
370 memset( p_vdec->p_context, 0, sizeof( AVCodecContext ) );
372 p_vdec->p_context->width = p_vdec->format.i_width;
373 p_vdec->p_context->height = p_vdec->format.i_height;
374 p_vdec->p_context->pix_fmt = PIX_FMT_YUV420P; /* I420 */
376 if (avcodec_open(p_vdec->p_context, p_vdec->p_codec) < 0)
378 intf_ErrMsg( "vdec error: cannot open codec (%s)",
379 p_vdec->psz_namecodec );
384 intf_WarnMsg( 1, "vdec info: ffmpeg codec (%s) started",
385 p_vdec->psz_namecodec );
389 p_vdec->p_vout = vout_CreateThread(
391 p_vdec->format.i_width,
392 p_vdec->format.i_height,
394 VOUT_ASPECT_FACTOR * p_vdec->format.i_width /
395 p_vdec->format.i_height );
397 if( !p_vdec->p_vout )
399 intf_ErrMsg( "vdec error: can't open vout, aborting" );
400 avcodec_close( p_vdec->p_context );
401 intf_WarnMsg(1, "vdec info: ffmpeg codec (%s) stopped",
402 p_vdec->psz_namecodec);
406 vlc_mutex_lock( &p_vout_bank->lock );
407 if( p_vout_bank->i_count != 0 )
409 vlc_mutex_unlock( &p_vout_bank->lock );
410 vout_DestroyThread( p_vout_bank->pp_vout[ 0 ], NULL );
411 vlc_mutex_lock( &p_vout_bank->lock );
412 p_vout_bank->i_count--;
414 p_vout_bank->i_count++;
415 p_vout_bank->pp_vout[0] = p_vdec->p_vout;
416 vlc_mutex_unlock( &p_vout_bank->lock );
421 /*****************************************************************************
422 * EndThread: thread destruction
423 *****************************************************************************
424 * This function is called when the thread ends after a sucessful
426 *****************************************************************************/
427 static void EndThread( videodec_thread_t *p_vdec )
431 intf_ErrMsg( "vdec error: cannot free structures" );
435 if( p_vdec->p_context != NULL)
437 avcodec_close( p_vdec->p_context );
438 intf_WarnMsg(1, "vdec info: ffmpeg codec (%s) stopped",
439 p_vdec->psz_namecodec);
442 vlc_mutex_lock( &p_vout_bank->lock );
443 if( p_vout_bank->i_count != 0 )
445 vlc_mutex_unlock( &p_vout_bank->lock );
446 vout_DestroyThread( p_vout_bank->pp_vout[ 0 ], NULL );
447 vlc_mutex_lock( &p_vout_bank->lock );
448 p_vout_bank->i_count--;
449 p_vout_bank->pp_vout[ 0 ] = NULL;
451 vlc_mutex_unlock( &p_vout_bank->lock );
456 static void DecodeThread( videodec_thread_t *p_vdec )
461 AVPicture avpicture; /* ffmpeg picture */
462 picture_t *p_pic; /* videolan picture */
463 /* we have to get a frame stored in a pes
464 give it to ffmpeg decoder
465 and send the image to the output */
467 __GetFrame( p_vdec );
469 i_status = avcodec_decode_video( p_vdec->p_context,
473 p_vdec->i_framesize);
474 __NextFrame( p_vdec );
478 intf_WarnMsg( 2, "vdec error: cannot decode one frame (%d bytes)",
479 p_vdec->i_framesize );
487 /* Send decoded frame to vout */
489 while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
491 if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
495 msleep( VOUT_OUTMEM_SLEEP );
498 for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
502 byte_t *p_dest = p_pic->p[i_plane].p_pixels;
503 byte_t *p_src = avpicture.data[i_plane];
504 if( ( !p_dest )||( !p_src ))
508 i_size = __MIN( p_pic->p[i_plane].i_pitch,
509 avpicture.linesize[i_plane] );
510 for( i_line = 0; i_line < p_pic->p[i_plane].i_lines; i_line++ )
512 FAST_MEMCPY( p_dest, p_src, i_size );
513 p_dest += p_pic->p[i_plane].i_pitch;
514 p_src += avpicture.linesize[i_plane];
518 vout_DatePicture( p_vdec->p_vout, p_pic, p_vdec->i_pts);
519 vout_DisplayPicture( p_vdec->p_vout, p_pic );