demux.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:15k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * demux.c: demuxer using ffmpeg (libavformat).
  3.  *****************************************************************************
  4.  * Copyright (C) 2004 VideoLAN
  5.  * $Id: demux.c 9236 2004-11-07 20:20:35Z gbazin $
  6.  *
  7.  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  8.  *          Gildas Bazin <gbazin@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.  * Preamble
  26.  *****************************************************************************/
  27. #include <stdlib.h>                                      /* malloc(), free() */
  28. #include <vlc/vlc.h>
  29. #include <vlc/input.h>
  30. #include "vlc_meta.h"
  31. /* ffmpeg header */
  32. #ifdef HAVE_FFMPEG_AVCODEC_H
  33. #   include <ffmpeg/avformat.h>
  34. #else
  35. #   include <avformat.h>
  36. #endif
  37. #include "ffmpeg.h"
  38. //#define AVFORMAT_DEBUG 1
  39. /* Version checking */
  40. #if (LIBAVFORMAT_BUILD >= 4611) && defined(HAVE_LIBAVFORMAT)
  41. #if LIBAVFORMAT_BUILD < 4619
  42. #   define av_seek_frame(a,b,c,d) av_seek_frame(a,b,c)
  43. #endif
  44. /*****************************************************************************
  45.  * demux_sys_t: demux descriptor
  46.  *****************************************************************************/
  47. struct demux_sys_t
  48. {
  49.     ByteIOContext   io;
  50.     int             io_buffer_size;
  51.     uint8_t        *io_buffer;
  52.     AVInputFormat  *fmt;
  53.     AVFormatContext *ic;
  54.     URLContext     url;
  55.     URLProtocol    prot;
  56.     int             i_tk;
  57.     es_out_id_t     **tk;
  58.     int64_t     i_pcr;
  59.     int64_t     i_pcr_inc;
  60.     int         i_pcr_tk;
  61. };
  62. /*****************************************************************************
  63.  * Local prototypes
  64.  *****************************************************************************/
  65. static int Demux  ( demux_t *p_demux );
  66. static int Control( demux_t *p_demux, int i_query, va_list args );
  67. static int IORead( void *opaque, uint8_t *buf, int buf_size );
  68. static int IOSeek( void *opaque, offset_t offset, int whence );
  69. /*****************************************************************************
  70.  * Open
  71.  *****************************************************************************/
  72. int E_(OpenDemux)( vlc_object_t *p_this )
  73. {
  74.     demux_t       *p_demux = (demux_t*)p_this;
  75.     demux_sys_t   *p_sys;
  76.     AVProbeData   pd;
  77.     AVInputFormat *fmt;
  78.     int i;
  79.     /* Init Probe data */
  80.     pd.filename = p_demux->psz_path;
  81.     if( ( pd.buf_size = stream_Peek( p_demux->s, &pd.buf, 2048 ) ) <= 0 )
  82.     {
  83.         msg_Warn( p_demux, "cannot peek" );
  84.         return VLC_EGENERIC;
  85.     }
  86.     av_register_all(); /* Can be called several times */
  87.     /* Guess format */
  88.     if( !( fmt = av_probe_input_format( &pd, 1 ) ) )
  89.     {
  90.         msg_Dbg( p_demux, "couldn't guess format" );
  91.         return VLC_EGENERIC;
  92.     }
  93.     /* Don't try to handle MPEG unless forced */
  94.     if( !p_demux->b_force &&
  95.         ( !strcmp( fmt->name, "mpeg" ) ||
  96.           !strcmp( fmt->name, "vcd" ) ||
  97.           !strcmp( fmt->name, "vob" ) ||
  98.           !strcmp( fmt->name, "mpegts" ) ||
  99.           /* libavformat's redirector won't work */
  100.           !strcmp( fmt->name, "redir" ) ||
  101.           !strcmp( fmt->name, "sdp" ) ) )
  102.     {
  103.         return VLC_EGENERIC;
  104.     }
  105.     /* Don't trigger false alarms on bin files */
  106.     if( !p_demux->b_force && !strcmp( fmt->name, "psxstr" ) )
  107.     {
  108.         int i_len;
  109.         if( !p_demux->psz_path ) return VLC_EGENERIC;
  110.         i_len = strlen( p_demux->psz_path );
  111.         if( i_len < 4 ) return VLC_EGENERIC;
  112.         if( strcasecmp( &p_demux->psz_path[i_len - 4], ".str" ) &&
  113.             strcasecmp( &p_demux->psz_path[i_len - 4], ".xai" ) &&
  114.             strcasecmp( &p_demux->psz_path[i_len - 4], ".xa" ) )
  115.         {
  116.             return VLC_EGENERIC;
  117.         }
  118.     }
  119.     msg_Dbg( p_demux, "detected format: %s", fmt->name );
  120.     /* Fill p_demux fields */
  121.     p_demux->pf_demux = Demux;
  122.     p_demux->pf_control = Control;
  123.     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
  124.     p_sys->ic = 0;
  125.     p_sys->fmt = fmt;
  126.     p_sys->i_tk = 0;
  127.     p_sys->tk = NULL;
  128.     p_sys->i_pcr_tk = -1;
  129.     p_sys->i_pcr = -1;
  130.     /* Create I/O wrapper */
  131.     p_sys->io_buffer_size = 32768;  /* FIXME */
  132.     p_sys->io_buffer = malloc( p_sys->io_buffer_size );
  133.     p_sys->url.priv_data = p_demux;
  134.     p_sys->url.prot = &p_sys->prot;
  135.     p_sys->url.prot->name = "VLC I/O wrapper";
  136.     p_sys->url.prot->url_open = 0;
  137.     p_sys->url.prot->url_read =
  138.                     (int (*) (URLContext *, unsigned char *, int))IORead;
  139.     p_sys->url.prot->url_write = 0;
  140.     p_sys->url.prot->url_seek =
  141.                     (offset_t (*) (URLContext *, offset_t, int))IOSeek;
  142.     p_sys->url.prot->url_close = 0;
  143.     p_sys->url.prot->next = 0;
  144.     init_put_byte( &p_sys->io, p_sys->io_buffer, p_sys->io_buffer_size,
  145.                    0, &p_sys->url, IORead, NULL, IOSeek );
  146.     p_sys->fmt->flags |= AVFMT_NOFILE; /* libavformat must not fopen/fclose */
  147.     /* Open it */
  148.     if( av_open_input_stream( &p_sys->ic, &p_sys->io, p_demux->psz_path,
  149.                               p_sys->fmt, NULL ) )
  150.     {
  151.         msg_Err( p_demux, "av_open_input_stream failed" );
  152.         E_(CloseDemux)( p_this );
  153.         return VLC_EGENERIC;
  154.     }
  155.     if( av_find_stream_info( p_sys->ic ) )
  156.     {
  157.         msg_Err( p_demux, "av_find_stream_info failed" );
  158.         E_(CloseDemux)( p_this );
  159.         return VLC_EGENERIC;
  160.     }
  161.     for( i = 0; i < p_sys->ic->nb_streams; i++ )
  162.     {
  163.         AVCodecContext *cc = &p_sys->ic->streams[i]->codec;
  164.         es_out_id_t  *es;
  165.         es_format_t  fmt;
  166.         vlc_fourcc_t fcc;
  167.         if( !E_(GetVlcFourcc)( cc->codec_id, NULL, &fcc, NULL ) )
  168.             fcc = VLC_FOURCC( 'u', 'n', 'd', 'f' );
  169.         switch( cc->codec_type )
  170.         {
  171.         case CODEC_TYPE_AUDIO:
  172.             es_format_Init( &fmt, AUDIO_ES, fcc );
  173.             fmt.audio.i_channels = cc->channels;
  174.             fmt.audio.i_rate = cc->sample_rate;
  175.             fmt.audio.i_bitspersample = cc->bits_per_sample;
  176.             fmt.audio.i_blockalign = cc->block_align;
  177.             break;
  178.         case CODEC_TYPE_VIDEO:
  179.             es_format_Init( &fmt, VIDEO_ES, fcc );
  180.             fmt.video.i_width = cc->width;
  181.             fmt.video.i_height = cc->height;
  182.             if( cc->palctrl )
  183.             {
  184.                 fmt.video.p_palette = malloc( sizeof(video_palette_t) );
  185.                 *fmt.video.p_palette = *(video_palette_t *)cc->palctrl;
  186.             }
  187.             break;
  188.         default:
  189.             break;
  190.         }
  191.         fmt.i_extra = cc->extradata_size;
  192.         fmt.p_extra = cc->extradata;
  193.         es = es_out_Add( p_demux->out, &fmt );
  194.         msg_Dbg( p_demux, "adding es: %s codec = %4.4s",
  195.                  cc->codec_type == CODEC_TYPE_AUDIO ? "audio" : "video",
  196.                  (char*)&fcc );
  197.         TAB_APPEND( p_sys->i_tk, p_sys->tk, es );
  198.     }
  199.     msg_Dbg( p_demux, "AVFormat supported stream" );
  200.     msg_Dbg( p_demux, "    - format = %s (%s)",
  201.              p_sys->fmt->name, p_sys->fmt->long_name );
  202.     msg_Dbg( p_demux, "    - start time = "I64Fd,
  203.              ( p_sys->ic->start_time != AV_NOPTS_VALUE ) ?
  204.              p_sys->ic->start_time * 1000000 / AV_TIME_BASE : -1 );
  205.     msg_Dbg( p_demux, "    - duration = "I64Fd,
  206.              ( p_sys->ic->duration != AV_NOPTS_VALUE ) ?
  207.              p_sys->ic->duration * 1000000 / AV_TIME_BASE : -1 );
  208.     return VLC_SUCCESS;
  209. }
  210. /*****************************************************************************
  211.  * Close
  212.  *****************************************************************************/
  213. void E_(CloseDemux)( vlc_object_t *p_this )
  214. {
  215.     demux_t     *p_demux = (demux_t*)p_this;
  216.     demux_sys_t *p_sys = p_demux->p_sys;
  217.     if( p_sys->ic ) av_close_input_file( p_sys->ic );
  218.     if( p_sys->io_buffer ) free( p_sys->io_buffer );
  219.     free( p_sys );
  220. }
  221. /*****************************************************************************
  222.  * Demux:
  223.  *****************************************************************************/
  224. static int Demux( demux_t *p_demux )
  225. {
  226.     demux_sys_t *p_sys = p_demux->p_sys;
  227.     AVPacket    pkt;
  228.     block_t     *p_frame;
  229.     int64_t     i_start_time;
  230.     /* Read a frame */
  231.     if( av_read_frame( p_sys->ic, &pkt ) )
  232.     {
  233.         return 0;
  234.     }
  235.     if( pkt.stream_index < 0 || pkt.stream_index >= p_sys->i_tk )
  236.     {
  237.         av_free_packet( &pkt );
  238.         return 1;
  239.     }
  240.     if( ( p_frame = block_New( p_demux, pkt.size ) ) == NULL )
  241.     {
  242.         return 0;
  243.     }
  244.     memcpy( p_frame->p_buffer, pkt.data, pkt.size );
  245.     i_start_time = ( p_sys->ic->start_time != AV_NOPTS_VALUE ) ?
  246.         p_sys->ic->start_time : 0;
  247.     p_frame->i_dts = ( pkt.dts == AV_NOPTS_VALUE ) ?
  248.         0 : (pkt.dts - i_start_time) * 1000000 / AV_TIME_BASE;
  249.     p_frame->i_pts = ( pkt.pts == AV_NOPTS_VALUE ) ?
  250.         0 : (pkt.pts - i_start_time) * 1000000 / AV_TIME_BASE;
  251. #ifdef AVFORMAT_DEBUG
  252.     msg_Dbg( p_demux, "tk[%d] dts="I64Fd" pts="I64Fd,
  253.              pkt.stream_index, p_frame->i_dts, p_frame->i_pts );
  254. #endif
  255.     if( pkt.dts > 0  &&
  256.         ( pkt.stream_index == p_sys->i_pcr_tk || p_sys->i_pcr_tk < 0 ) )
  257.     {    
  258.         p_sys->i_pcr_tk = pkt.stream_index;
  259.         p_sys->i_pcr = pkt.dts - i_start_time;
  260.         es_out_Control( p_demux->out, ES_OUT_SET_PCR, (int64_t)p_sys->i_pcr );
  261.     }
  262.     es_out_Send( p_demux->out, p_sys->tk[pkt.stream_index], p_frame );
  263.     av_free_packet( &pkt );
  264.     return 1;
  265. }
  266. /*****************************************************************************
  267.  * Control:
  268.  *****************************************************************************/
  269. static int Control( demux_t *p_demux, int i_query, va_list args )
  270. {
  271.     demux_sys_t *p_sys = p_demux->p_sys;
  272.     double f, *pf;
  273.     int64_t i64, *pi64;
  274.     switch( i_query )
  275.     {
  276.         case DEMUX_GET_POSITION:
  277.             pf = (double*) va_arg( args, double* ); *pf = 0.0;
  278.             i64 = stream_Size( p_demux->s );
  279.             if( i64 > 0 )
  280.             {
  281.                 *pf = (double)stream_Tell( p_demux->s ) / (double)i64;
  282.             }
  283.             if( p_sys->ic->duration != AV_NOPTS_VALUE && p_sys->i_pcr > 0 )
  284.             {
  285.                 *pf = (double)p_sys->i_pcr / (double)p_sys->ic->duration;
  286.             }
  287.             return VLC_SUCCESS;
  288.         case DEMUX_SET_POSITION:
  289.             f = (double) va_arg( args, double );
  290.             i64 = stream_Tell( p_demux->s );
  291.             if( i64 && p_sys->i_pcr > 0 )
  292.             {
  293.                 int64_t i_size = stream_Size( p_demux->s );
  294.                 i64 = p_sys->i_pcr * i_size / i64 * f;
  295.                 if( p_sys->ic->start_time != AV_NOPTS_VALUE )
  296.                     i64 += p_sys->ic->start_time;
  297.                 if( p_sys->ic->duration != AV_NOPTS_VALUE )
  298.                     i64 = p_sys->ic->duration * f;
  299.                 msg_Warn( p_demux, "DEMUX_SET_POSITION: "I64Fd, i64 );
  300.                 if( av_seek_frame( p_sys->ic, -1, i64, 0 ) < 0 )
  301.                 {
  302.                     return VLC_EGENERIC;
  303.                 }
  304.                 es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
  305.                 p_sys->i_pcr = -1; /* Invalidate time display */
  306.             }
  307.             return VLC_SUCCESS;
  308.         case DEMUX_GET_LENGTH:
  309.             pi64 = (int64_t*)va_arg( args, int64_t * );
  310.             if( p_sys->ic->duration != AV_NOPTS_VALUE )
  311.             {
  312.                 *pi64 = p_sys->ic->duration;
  313.             }
  314.             else *pi64 = 0;
  315.             return VLC_SUCCESS;
  316.         case DEMUX_GET_TIME:
  317.             pi64 = (int64_t*)va_arg( args, int64_t * );
  318.             *pi64 = p_sys->i_pcr;
  319.             return VLC_SUCCESS;
  320.         case DEMUX_SET_TIME:
  321.             i64 = (int64_t)va_arg( args, int64_t );
  322.             if( p_sys->ic->start_time != AV_NOPTS_VALUE )
  323.                 i64 += p_sys->ic->start_time;
  324.             msg_Warn( p_demux, "DEMUX_SET_TIME: "I64Fd, i64 );
  325.             if( av_seek_frame( p_sys->ic, -1, i64, 0 ) < 0 )
  326.             {
  327.                 return VLC_EGENERIC;
  328.             }
  329.             es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
  330.             p_sys->i_pcr = -1; /* Invalidate time display */
  331.             return VLC_SUCCESS;
  332.         case DEMUX_GET_META:
  333.         {
  334.             vlc_meta_t **pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** );
  335.             vlc_meta_t *meta;
  336.             if( !p_sys->ic->title[0] || !p_sys->ic->author[0] ||
  337.                 !p_sys->ic->copyright[0] || !p_sys->ic->comment[0] ||
  338.                 /*!p_sys->ic->album[0] ||*/ !p_sys->ic->genre[0] )
  339.             {
  340.                 return VLC_EGENERIC;
  341.             }
  342.             *pp_meta = meta = vlc_meta_New();
  343.             if( p_sys->ic->title[0] )
  344.                 vlc_meta_Add( meta, VLC_META_TITLE, p_sys->ic->title );
  345.             if( p_sys->ic->author[0] )
  346.                 vlc_meta_Add( meta, VLC_META_AUTHOR, p_sys->ic->author );
  347.             if( p_sys->ic->copyright[0] )
  348.                 vlc_meta_Add( meta, VLC_META_COPYRIGHT, p_sys->ic->copyright );
  349.             if( p_sys->ic->comment[0] )
  350.                 vlc_meta_Add( meta, VLC_META_DESCRIPTION, p_sys->ic->comment );
  351.             if( p_sys->ic->genre[0] )
  352.                 vlc_meta_Add( meta, VLC_META_GENRE, p_sys->ic->genre );
  353.             return VLC_SUCCESS;
  354.         }
  355.         default:
  356.             return VLC_EGENERIC;
  357.     }
  358. }
  359. /*****************************************************************************
  360.  * I/O wrappers for libavformat
  361.  *****************************************************************************/
  362. static int IORead( void *opaque, uint8_t *buf, int buf_size )
  363. {
  364.     URLContext *p_url = opaque;
  365.     demux_t *p_demux = p_url->priv_data;
  366.     int i_ret = stream_Read( p_demux->s, buf, buf_size );
  367.     return i_ret ? i_ret : -1;
  368. }
  369. static int IOSeek( void *opaque, offset_t offset, int whence )
  370. {
  371.     URLContext *p_url = opaque;
  372.     demux_t *p_demux = p_url->priv_data;
  373.     int64_t i_absolute;
  374. #ifdef AVFORMAT_DEBUG
  375.     msg_Warn( p_demux, "IOSeek offset: "I64Fd", whence: %i", offset, whence );
  376. #endif
  377.     switch( whence )
  378.     {
  379.         case SEEK_SET:
  380.             i_absolute = offset;
  381.             break;
  382.         case SEEK_CUR:
  383.             i_absolute = stream_Tell( p_demux->s ) + offset;
  384.             break;
  385.         case SEEK_END:
  386.             i_absolute = stream_Size( p_demux->s ) - offset;
  387.             break;
  388.         default:
  389.             return -1;
  390.     }
  391.     if( stream_Seek( p_demux->s, i_absolute ) )
  392.     {
  393.         return -1;
  394.     }
  395.     return 0;
  396. }
  397. #else /* LIBAVFORMAT_BUILD >= 4611 */
  398. int E_(OpenDemux)( vlc_object_t *p_this )
  399. {
  400.     return VLC_EGENERIC;
  401. }
  402. void E_(CloseDemux)( vlc_object_t *p_this )
  403. {
  404. }
  405. #endif /* LIBAVFORMAT_BUILD >= 4611 */