Commit 968cc6bf authored by Laurent Aimar's avatar Laurent Aimar

* all: added mjpeg support, some clean up in video part.

parent e0ac4474
......@@ -2,7 +2,7 @@
* audio.c: audio decoder using ffmpeg library
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: audio.c,v 1.3 2002/11/14 22:38:47 massiot Exp $
* $Id: audio.c,v 1.4 2002/11/27 12:41:45 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -196,14 +196,14 @@ void E_( DecodeThread_Audio )( adec_thread_t *p_adec )
if( i_frame_size > 0 )
{
if( p_adec->i_buffer < i_frame_size + 16 )
if( p_adec->i_buffer_size < i_frame_size + 16 )
{
FREE( p_adec->p_buffer );
p_adec->p_buffer = malloc( i_frame_size + 16 );
p_adec->i_buffer = i_frame_size + 16;
p_adec->i_buffer_size = i_frame_size + 16;
}
E_( GetPESData )( p_adec->p_buffer, p_adec->i_buffer, p_pes );
E_( GetPESData )( p_adec->p_buffer, p_adec->i_buffer_size, p_pes );
}
input_DeletePES( p_adec->p_fifo->p_packets_mgt, p_pes );
} while( i_frame_size <= 0 );
......
......@@ -2,7 +2,7 @@
* ffmpeg.c: video decoder using ffmpeg library
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: ffmpeg.c,v 1.17 2002/11/18 02:46:10 fenrir Exp $
* $Id: ffmpeg.c,v 1.18 2002/11/27 12:41:45 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -294,6 +294,10 @@ static int InitThread( generic_thread_t *p_decoder )
}
p_decoder->pts = 0;
p_decoder->p_buffer = NULL;
p_decoder->i_buffer = 0;
p_decoder->i_buffer_size = 0;
return( i_result );
}
......@@ -313,7 +317,6 @@ static void EndThread( generic_thread_t *p_decoder )
if( p_decoder->p_context != NULL)
{
FREE( p_decoder->p_context->quant_store );
FREE( p_decoder->p_context->extradata );
avcodec_close( p_decoder->p_context );
msg_Dbg( p_decoder->p_fifo,
......@@ -341,7 +344,7 @@ static void EndThread( generic_thread_t *p_decoder )
* locales Functions
*****************************************************************************/
void E_( GetPESData )( u8 *p_buf, int i_max, pes_packet_t *p_pes )
int E_( GetPESData )( u8 *p_buf, int i_max, pes_packet_t *p_pes )
{
int i_copy;
int i_count;
......@@ -372,6 +375,7 @@ void E_( GetPESData )( u8 *p_buf, int i_max, pes_packet_t *p_pes )
{
memset( p_buf, 0, i_max - i_count );
}
return( i_count );
}
......@@ -386,6 +390,14 @@ static int ffmpeg_GetFfmpegCodec( vlc_fourcc_t i_fourcc,
switch( i_fourcc )
{
#if 0
/* XXX don't use it */
case FOURCC_mpgv:
i_cat = VIDEO_ES;
i_codec = CODEC_ID_MPEG1VIDEO;
psz_name = "MPEG-1/2 Video";
break;
#endif
#if LIBAVCODEC_BUILD >= 4608
case FOURCC_DIV1:
case FOURCC_div1:
......@@ -479,7 +491,21 @@ static int ffmpeg_GetFfmpegCodec( vlc_fourcc_t i_fourcc,
i_codec = CODEC_ID_WMV2;
psz_name ="Windows Media Video 2";
break;
case FOURCC_MJPG:
case FOURCC_mjpg:
case FOURCC_mjpa:
case FOURCC_jpeg:
case FOURCC_JFIF:
i_cat = VIDEO_ES;
i_codec = CODEC_ID_MJPEG;
psz_name = "Motion JPEG";
break;
case FOURCC_mjpb:
i_cat = VIDEO_ES;
i_codec = CODEC_ID_MJPEGB;
psz_name = "Motion JPEG B";
break;
#if LIBAVCODEC_BUILD >= 4632
case FOURCC_WMA1:
case FOURCC_wma1:
......
......@@ -2,7 +2,7 @@
* ffmpeg_vdec.h: video decoder using ffmpeg library
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: ffmpeg.h,v 1.8 2002/11/05 10:07:56 gbazin Exp $
* $Id: ffmpeg.h,v 1.9 2002/11/27 12:41:45 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -37,7 +37,8 @@
\
/* Private stuff for frame gathering */ \
u8 *p_buffer; /* buffer for gather pes */ \
int i_buffer; /* size of allocated p_framedata */
int i_buffer_size; /* size of allocated p_buffer */ \
int i_buffer; /* bytes already present in p_buffer */
typedef struct generic_thread_s
......@@ -55,12 +56,15 @@ typedef struct generic_thread_s
#define FREE( p ) if( p ) free( p ); p = NULL
void E_( GetPESData )( u8 *p_buf, int i_max, pes_packet_t *p_pes );
int E_( GetPESData )( u8 *p_buf, int i_max, pes_packet_t *p_pes );
/*****************************************************************************
* Video codec fourcc
*****************************************************************************/
/* MPEG 1/2 video */
#define FOURCC_mpgv VLC_FOURCC('m','p','g','v')
/* MPEG4 video */
#define FOURCC_DIVX VLC_FOURCC('D','I','V','X')
#define FOURCC_divx VLC_FOURCC('d','i','v','x')
......@@ -118,6 +122,17 @@ void E_( GetPESData )( u8 *p_buf, int i_max, pes_packet_t *p_pes );
/* Sorenson v1 */
#define FOURCC_SVQ1 VLC_FOURCC( 'S', 'V', 'Q', '1' )
/* mjpeg */
#define FOURCC_MJPG VLC_FOURCC( 'M', 'J', 'P', 'G' )
#define FOURCC_mjpg VLC_FOURCC( 'm', 'j', 'p', 'g' )
/* for mov file */
#define FOURCC_mjpa VLC_FOURCC( 'm', 'j', 'p', 'a' )
/* for mov file XXX: untested */
#define FOURCC_mjpb VLC_FOURCC( 'm', 'j', 'p', 'b' )
#define FOURCC_jpeg VLC_FOURCC( 'j', 'p', 'e', 'g' )
#define FOURCC_JFIF VLC_FOURCC( 'J', 'F', 'I', 'F' )
/* wmv */
#define FOURCC_WMV1 VLC_FOURCC('W','M','V','1')
#define FOURCC_WMV2 VLC_FOURCC('W','M','V','2')
......
......@@ -2,7 +2,7 @@
* video.c: video decoder using ffmpeg library
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: video.c,v 1.5 2002/11/19 20:45:09 gbazin Exp $
* $Id: video.c,v 1.6 2002/11/27 12:41:45 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Gildas Bazin <gbazin@netcourrier.com>
......@@ -63,7 +63,7 @@ static int i_ffmpeg_PixFmtToChroma[] =
*/
0, VLC_FOURCC('I','4','2','0'),
VLC_FOURCC('I','4','2','0'), VLC_FOURCC('R','V','2','4'),
0, VLC_FOURCC('Y','4','2','2'),
0, VLC_FOURCC('I','4','2','2'),
VLC_FOURCC('I','4','4','4'), 0
};
......@@ -103,7 +103,6 @@ static inline int ffmpeg_FfAspect( int i_width, int i_height, int i_ffaspect )
static int ffmpeg_CheckVout( vout_thread_t *p_vout,
int i_width,
int i_height,
int i_aspect,
int i_chroma )
{
if( !p_vout )
......@@ -118,9 +117,7 @@ static int ffmpeg_CheckVout( vout_thread_t *p_vout,
if( ( p_vout->render.i_width != i_width )||
( p_vout->render.i_height != i_height )||
( p_vout->render.i_chroma != i_chroma )||
( p_vout->render.i_aspect !=
ffmpeg_FfAspect( i_width, i_height, i_aspect ) ) )
( p_vout->render.i_chroma != i_chroma ) )
{
return( 0 );
}
......@@ -131,15 +128,16 @@ static int ffmpeg_CheckVout( vout_thread_t *p_vout,
}
/* Return a Vout */
static vout_thread_t *ffmpeg_CreateVout( vdec_thread_t *p_vdec,
int i_width,
int i_height,
int i_aspect,
int i_chroma )
static vout_thread_t *ffmpeg_CreateVout( vdec_thread_t *p_vdec,
AVCodecContext *p_context )
{
vout_thread_t *p_vout;
int i_width = p_vdec->p_context->width;
int i_height = p_vdec->p_context->height;
uint32_t i_chroma = ffmpeg_PixFmtToChroma( p_vdec->p_context->pix_fmt );
int i_aspect;
if( (!i_width)||(!i_height) )
if( !i_width || !i_height )
{
return( NULL ); /* Can't create a new vout without display size */
}
......@@ -153,8 +151,28 @@ static vout_thread_t *ffmpeg_CreateVout( vdec_thread_t *p_vdec,
it's buggy and very slow */
}
i_aspect = ffmpeg_FfAspect( i_width, i_height, i_aspect );
#if LIBAVCODEC_BUILD >= 4640
i_aspect = (int) ( VOUT_ASPECT_FACTOR * p_vdec->p_context->aspect_ratio );
if( i_aspect == 0 )
{
i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height;
}
#else
switch( i_aspect )
{
case( FF_ASPECT_4_3_625 ):
case( FF_ASPECT_4_3_525 ):
i_aspect = VOUT_ASPECT_FACTOR * 4 / 3;
case( FF_ASPECT_16_9_625 ):
case( FF_ASPECT_16_9_525 ):
i_aspect = VOUT_ASPECT_FACTOR * 16 / 9 ;
case( FF_ASPECT_SQUARE ):
default:
i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height;
}
#endif
/* Spawn a video output if there is none. First we look for our children,
* then we look for any other vout that might be available. */
p_vout = vlc_object_find( p_vdec->p_fifo, VLC_OBJECT_VOUT,
......@@ -167,8 +185,7 @@ static vout_thread_t *ffmpeg_CreateVout( vdec_thread_t *p_vdec,
if( p_vout )
{
if( !ffmpeg_CheckVout( p_vout,
i_width, i_height, i_aspect,i_chroma ) )
if( !ffmpeg_CheckVout( p_vout, i_width, i_height, i_chroma ) )
{
/* We are not interested in this format, close this vout */
vlc_object_detach( p_vout );
......@@ -322,15 +339,18 @@ int E_( InitThread_Video )( vdec_thread_t *p_vdec )
if( p_vdec->p_fifo->p_demux_data )
{
p_vdec->p_format = (BITMAPINFOHEADER *)p_vdec->p_fifo->p_demux_data;
/* ***** Fill p_context with init values ***** */
p_vdec->p_context->width = p_vdec->p_format->biWidth;
p_vdec->p_context->height = p_vdec->p_format->biHeight;
}
else
{
msg_Warn( p_vdec->p_fifo, "display informations missing" );
p_vdec->p_format = NULL;
}
/* ***** Fill p_context with init values ***** */
p_vdec->p_context->width = p_vdec->p_format->biWidth;
p_vdec->p_context->height = p_vdec->p_format->biHeight;
/* ***** Get configuration of ffmpeg plugin ***** */
#if LIBAVCODEC_BUILD >= 4611
......@@ -365,6 +385,16 @@ int E_( InitThread_Video )( vdec_thread_t *p_vdec )
}
#endif
#if 0
/* check if codec support truncated frames */
// if( p_vdec->p_codec->capabilities & CODEC_FLAG_TRUNCATED )
if( p_vdec->i_codec_id == CODEC_ID_MPEG1VIDEO)
{
msg_Dbg( p_vdec->p_fifo, "CODEC_FLAG_TRUNCATED supported" );
p_vdec->p_context->flags |= CODEC_FLAG_TRUNCATED;
}
#endif
/* ***** Open the codec ***** */
if( avcodec_open(p_vdec->p_context, p_vdec->p_codec) < 0 )
{
......@@ -379,7 +409,8 @@ int E_( InitThread_Video )( vdec_thread_t *p_vdec )
}
/* ***** init this codec with special data ***** */
if( p_vdec->p_format->biSize > sizeof(BITMAPINFOHEADER) )
if( p_vdec->p_format &&
p_vdec->p_format->biSize > sizeof(BITMAPINFOHEADER) )
{
AVPicture avpicture;
int b_gotpicture;
......@@ -397,7 +428,12 @@ int E_( InitThread_Video )( vdec_thread_t *p_vdec )
if( p_vdec->p_fifo->i_fourcc == FOURCC_MP4S ||
p_vdec->p_fifo->i_fourcc == FOURCC_mp4s ||
p_vdec->p_fifo->i_fourcc == FOURCC_M4S2 ||
p_vdec->p_fifo->i_fourcc == FOURCC_m4s2 )
p_vdec->p_fifo->i_fourcc == FOURCC_m4s2 ||
p_vdec->p_fifo->i_fourcc == FOURCC_WMV2 ||
p_vdec->p_fifo->i_fourcc == FOURCC_MJPG ||
p_vdec->p_fifo->i_fourcc == FOURCC_mjpg ||
p_vdec->p_fifo->i_fourcc == FOURCC_mjpa ||
p_vdec->p_fifo->i_fourcc == FOURCC_mjpb )
{
p_vdec->p_context->extradata_size =
p_vdec->p_format->biSize - sizeof(BITMAPINFOHEADER);
......@@ -507,11 +543,12 @@ void E_( DecodeThread_Video )( vdec_thread_t *p_vdec )
{
pes_packet_t *p_pes;
int i_frame_size;
int i_status;
int i_used;
int b_drawpicture;
int b_gotpicture;
AVPicture avpicture; /* ffmpeg picture */
picture_t *p_pic; /* videolan picture */
mtime_t i_pts;
/* TODO implement it in a better way */
/* A good idea could be to decode all I pictures and see for the other */
......@@ -562,38 +599,109 @@ void E_( DecodeThread_Video )( vdec_thread_t *p_vdec )
p_vdec->p_fifo->b_error = 1;
return;
}
p_vdec->pts = p_pes->i_pts;
#if 0
if( p_vdec->i_codec_id == CODEC_ID_MPEG1VIDEO )
{
if( p_pes->i_dts )
{
p_vdec->pts = p_pes->i_dts;
p_vdec->i_frame_count = 0;
}
}
else
{
if( p_pes->i_pts )
{
p_vdec->pts = p_pes->i_pts;
p_vdec->i_frame_count = 0;
}
}
#endif
if( p_pes->i_pts )
{
p_vdec->pts = p_pes->i_pts;
p_vdec->i_frame_count = 0;
}
i_frame_size = p_pes->i_pes_size;
if( i_frame_size > 0 )
{
if( p_vdec->i_buffer < i_frame_size + 16 )
uint8_t *p_last;
int i_need;
/* XXX Don't forget that ffmpeg required a little more bytes
* that the real frame size */
i_need = i_frame_size + 16 + p_vdec->i_buffer;
if( p_vdec->i_buffer_size < i_need)
{
FREE( p_vdec->p_buffer );
p_vdec->p_buffer = malloc( i_frame_size + 16 );
p_vdec->i_buffer = i_frame_size + 16;
p_last = p_vdec->p_buffer;
p_vdec->p_buffer = malloc( i_need );
p_vdec->i_buffer_size = i_need;
if( p_vdec->i_buffer > 0 )
{
memcpy( p_vdec->p_buffer, p_last, p_vdec->i_buffer );
}
FREE( p_last );
}
E_( GetPESData )( p_vdec->p_buffer, p_vdec->i_buffer, p_pes );
}
i_frame_size =
E_( GetPESData )( p_vdec->p_buffer + p_vdec->i_buffer,
i_frame_size ,
p_pes );
memset( p_vdec->p_buffer + p_vdec->i_buffer + i_frame_size,
0,
16 );
}
input_DeletePES( p_vdec->p_fifo->p_packets_mgt, p_pes );
} while( i_frame_size <= 0 );
i_frame_size += p_vdec->i_buffer;
i_status = avcodec_decode_video( p_vdec->p_context,
&avpicture,
&b_gotpicture,
p_vdec->p_buffer,
i_frame_size );
usenextdata:
i_used = avcodec_decode_video( p_vdec->p_context,
&avpicture,
&b_gotpicture,
p_vdec->p_buffer,
i_frame_size );
if( i_status < 0 )
#if 0
msg_Dbg( p_vdec->p_fifo,
"used:%d framesize:%d (%s picture)",
i_used, i_frame_size, b_gotpicture ? "got":"no got" );
#endif
if( i_used < 0 )
{
msg_Warn( p_vdec->p_fifo, "cannot decode one frame (%d bytes)",
i_frame_size );
p_vdec->i_frame_error++;
p_vdec->i_buffer = 0;
return;
}
/* Update frame late count*/
else if( i_used < i_frame_size )
{
#if 0
msg_Dbg( p_vdec->p_fifo,
"didn't use all memory(%d < %d)", i_used, i_frame_size );
#endif
memmove( p_vdec->p_buffer,
p_vdec->p_buffer + i_used,
p_vdec->i_buffer_size - i_used );
p_vdec->i_buffer = i_frame_size - i_used;
}
else
{
p_vdec->i_buffer = 0;
}
if( b_gotpicture )
{
p_vdec->i_frame_count++;
}
/* consumed bytes */
i_frame_size -= i_used;
/* Update frame late count*/
/* I don't make statistic on decoding time */
if( p_vdec->pts <= mdate())
{
......@@ -612,17 +720,12 @@ void E_( DecodeThread_Video )( vdec_thread_t *p_vdec )
if( !p_vdec->b_direct_rendering )
{
/* Check our vout */
if( !ffmpeg_CheckVout( p_vdec->p_vout,
if( !ffmpeg_CheckVout( p_vdec->p_vout,
p_vdec->p_context->width,
p_vdec->p_context->height,
p_vdec->p_context->aspect_ratio_info,
ffmpeg_PixFmtToChroma(p_vdec->p_context->pix_fmt)) )
{
p_vdec->p_vout = ffmpeg_CreateVout( p_vdec,
p_vdec->p_context->width,
p_vdec->p_context->height,
p_vdec->p_context->aspect_ratio_info,
ffmpeg_PixFmtToChroma(p_vdec->p_context->pix_fmt) );
p_vdec->p_vout = ffmpeg_CreateVout( p_vdec, p_vdec->p_context );
if( !p_vdec->p_vout )
{
msg_Err( p_vdec->p_fifo, "cannot create vout" );
......@@ -654,13 +757,34 @@ void E_( DecodeThread_Video )( vdec_thread_t *p_vdec )
/* Do post-processing if requested */
ffmpeg_PostProcPicture( p_vdec, p_pic );
/* FIXME correct avi and use i_dts */
/* Send decoded frame to vout */
vout_DatePicture( p_vdec->p_vout, p_pic, p_vdec->pts);
if( p_vdec->pts > 0 )
{
i_pts = p_vdec->pts;
if( p_vdec->p_context->frame_rate > 0 )
{
i_pts += (uint64_t)1000000 *
( p_vdec->i_frame_count - 1) /
FRAME_RATE_BASE /
p_vdec->p_context->frame_rate;
}
}
else
{
i_pts = mdate() + DEFAULT_PTS_DELAY; // FIXME
}
vout_DatePicture( p_vdec->p_vout,
p_pic,
i_pts );
vout_DisplayPicture( p_vdec->p_vout, p_pic );
return;
if( i_frame_size > 0 )
{
goto usenextdata;
}
}
/*****************************************************************************
......@@ -780,14 +904,9 @@ static int ffmpeg_GetFrameBuf( struct AVCodecContext *avctx, int width,
if( !ffmpeg_CheckVout( p_vdec->p_vout,
p_vdec->p_context->width,
p_vdec->p_context->height,
p_vdec->p_context->aspect_ratio_info,
ffmpeg_PixFmtToChroma(p_vdec->p_context->pix_fmt)) )
{
p_vdec->p_vout = ffmpeg_CreateVout( p_vdec,
p_vdec->p_context->width,
p_vdec->p_context->height,
p_vdec->p_context->aspect_ratio_info,
ffmpeg_PixFmtToChroma(p_vdec->p_context->pix_fmt) );
p_vdec->p_vout = ffmpeg_CreateVout( p_vdec, p_vdec->p_context );
if( !p_vdec->p_vout )
{
msg_Err( p_vdec->p_fifo, "cannot create vout" );
......
......@@ -2,7 +2,7 @@
* video.h: video decoder using ffmpeg library
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: video.h,v 1.3 2002/11/06 21:48:24 gbazin Exp $
* $Id: video.h,v 1.4 2002/11/27 12:41:45 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -37,7 +37,9 @@ typedef struct vdec_thread_s
int b_hurry_up;
int i_frame_error;
int i_frame_skip;
int i_frame_late; /* how many decoded frames are late */
int i_frame_late; /* how many decoded frames are late */
int i_frame_count; /* to emulate pts */
/* for direct rendering */
int b_direct_rendering;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment