demux_lavf.c

来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 714 行 · 第 1/2 页

C
714
字号
/*    Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at>    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA*/// #include <mplaylib.h>#include <mplaylib.h>// #include <mplaylib.h>#include "config.h"#include "mp_msg.h"#include "help_mp.h"#include "stream/stream.h"#include "demuxer.h"#include "stheader.h"#include "m_option.h"#include "libvo/sub.h"#ifdef USE_LIBAVFORMAT_SO#include <ffmpeg/avformat.h>#include <ffmpeg/avutil.h>#include <ffmpeg/opt.h>#else#include "avformat.h"#include "avutil.h"#include "avi.h"#include "opt.h"#endif#include "riff.h"#undef memcpy#define memcpy uc_memcpy#define PROBE_BUF_SIZE 2048extern char *audio_lang;static unsigned int opt_probesize = 0;static unsigned int opt_analyzeduration = 0;static char *opt_format;m_option_t lavfdopts_conf[] = {	{"probesize", &(opt_probesize), CONF_TYPE_INT, CONF_RANGE, 32, INT_MAX, NULL},	{"format",    &(opt_format),    CONF_TYPE_STRING,       0,  0,       0, NULL},	{"analyzeduration",    &(opt_analyzeduration),    CONF_TYPE_INT,       CONF_RANGE,  0,       INT_MAX, NULL},	{NULL, NULL, 0, 0, 0, 0, NULL}};typedef struct lavf_priv_t{    AVInputFormat *avif;    AVFormatContext *avfc;    ByteIOContext pb;    int audio_streams;    int video_streams;    int sub_streams;    int64_t last_pts;    int astreams[MAX_A_STREAMS];    int vstreams[MAX_V_STREAMS];    int sstreams[MAX_S_STREAMS];}lavf_priv_t;extern void print_wave_header(WAVEFORMATEX *h, int verbose_level);extern void print_video_header(BITMAPINFOHEADER *h, int verbose_level);static const AVCodecTag mp_wav_tags[] = {    { CODEC_ID_ADPCM_4XM,         MKTAG('4', 'X', 'M', 'A')},    { CODEC_ID_ADPCM_EA,          MKTAG('A', 'D', 'E', 'A')},    { CODEC_ID_ADPCM_IMA_WS,      MKTAG('A', 'I', 'W', 'S')},    { CODEC_ID_ADPCM_THP,         MKTAG('T', 'H', 'P', 'A')},    { CODEC_ID_AMR_NB,            MKTAG('n', 'b',   0,   0)},    { CODEC_ID_COOK,              MKTAG('c', 'o', 'o', 'k')},    { CODEC_ID_DSICINAUDIO,       MKTAG('D', 'C', 'I', 'A')},    { CODEC_ID_INTERPLAY_DPCM,    MKTAG('I', 'N', 'P', 'A')},    { CODEC_ID_MUSEPACK7,         MKTAG('M', 'P', 'C', ' ')},    { CODEC_ID_PCM_S24BE,         MKTAG('i', 'n', '2', '4')},    { CODEC_ID_PCM_S16BE,         MKTAG('t', 'w', 'o', 's')},    { CODEC_ID_PCM_S8,            MKTAG('t', 'w', 'o', 's')},    { CODEC_ID_ROQ_DPCM,          MKTAG('R', 'o', 'Q', 'A')},    { CODEC_ID_SHORTEN,           MKTAG('s', 'h', 'r', 'n')},    { CODEC_ID_TTA,               MKTAG('T', 'T', 'A', '1')},    { CODEC_ID_WAVPACK,           MKTAG('W', 'V', 'P', 'K')},    { CODEC_ID_WESTWOOD_SND1,     MKTAG('S', 'N', 'D', '1')},    { CODEC_ID_XAN_DPCM,          MKTAG('A', 'x', 'a', 'n')},    { 0, 0 },};const struct AVCodecTag *mp_wav_taglists[] = {codec_wav_tags, mp_wav_tags, 0};static const AVCodecTag mp_bmp_tags[] = {    { CODEC_ID_AMV,               MKTAG('A', 'M', 'V', 'V')},    { CODEC_ID_BETHSOFTVID,       MKTAG('B', 'E', 'T', 'H')},    { CODEC_ID_C93,               MKTAG('C', '9', '3', 'V')},    { CODEC_ID_DSICINVIDEO,       MKTAG('D', 'C', 'I', 'V')},    { CODEC_ID_DXA,               MKTAG('D', 'X', 'A', '1')},        { CODEC_ID_FLIC,              MKTAG('F', 'L', 'I', 'C')},    { CODEC_ID_IDCIN,             MKTAG('I', 'D', 'C', 'I')},    { CODEC_ID_INTERPLAY_VIDEO,   MKTAG('I', 'N', 'P', 'V')},    { CODEC_ID_ROQ,               MKTAG('R', 'o', 'Q', 'V')},    { CODEC_ID_THP,               MKTAG('T', 'H', 'P', 'V')},    { CODEC_ID_TIERTEXSEQVIDEO,   MKTAG('T', 'S', 'E', 'Q')},    { CODEC_ID_TXD,               MKTAG('T', 'X', 'D', 'V')},    { CODEC_ID_VMDVIDEO,          MKTAG('V', 'M', 'D', 'V')},    { CODEC_ID_WS_VQA,            MKTAG('V', 'Q', 'A', 'V')},    { CODEC_ID_XAN_WC3,           MKTAG('W', 'C', '3', 'V')},    { CODEC_ID_NUV,               MKTAG('N', 'U', 'V', '1')},    { 0, 0 },};const struct AVCodecTag *mp_bmp_taglists[] = {codec_bmp_tags, mp_bmp_tags, 0};static int mp_open(URLContext *h, const char *filename, int flags){    return 0;}static int mp_read(URLContext *h, unsigned char *buf, int size){    stream_t *stream = (stream_t*)h->priv_data;    int ret;    if(stream_eof(stream)) //needed?        return -1;    ret=stream_read(stream, buf, size);    mp_msg(MSGT_HEADER,MSGL_DBG2,"%d=mp_read(%p, %p, %d), eof:%d\n", ret, h, buf, size, stream->eof);    return ret;}static int mp_write(URLContext *h, unsigned char *buf, int size){    return -1;}static offset_t mp_seek(URLContext *h, offset_t pos, int whence){    stream_t *stream = (stream_t*)h->priv_data;        mp_msg(MSGT_HEADER,MSGL_DBG2,"mp_seek(%p, %d, %d)\n", h, (int)pos, whence);    if(whence == SEEK_CUR)        pos +=stream_tell(stream);    else if(whence == SEEK_END && stream->end_pos > 0)        pos += stream->end_pos;    else if(whence == SEEK_SET)        pos += stream->start_pos;    else if(whence == AVSEEK_SIZE && stream->end_pos > 0)        return stream->end_pos - stream->start_pos;    else        return -1;    if(pos<0)        return -1;    if(pos<stream->end_pos && stream->eof)        stream_reset(stream);    if(stream_seek(stream, pos)==0)        return -1;    return pos - stream->start_pos;}static int mp_close(URLContext *h){    return 0;}static URLProtocol mp_protocol = {    "mp",    mp_open,    mp_read,    mp_write,    mp_seek,    mp_close,};static void list_formats(void) {    AVInputFormat *fmt;    mp_msg(MSGT_DEMUX, MSGL_INFO, "Available lavf input formats:\n");    for (fmt = first_iformat; fmt; fmt = fmt->next)        mp_msg(MSGT_DEMUX, MSGL_INFO, "%15s : %s\n", fmt->name, fmt->long_name);}static int lavf_check_file(demuxer_t *demuxer){    AVProbeData avpd;    uint8_t buf[PROBE_BUF_SIZE];    lavf_priv_t *priv;    F("1\n");    if(!demuxer->priv)         demuxer->priv=calloc(sizeof(lavf_priv_t),1);    F("2\n");    priv= demuxer->priv;    av_register_all();		F("3\n");    if(stream_read(demuxer->stream, buf, PROBE_BUF_SIZE)!=PROBE_BUF_SIZE)        return 0;    F("4\n");    avpd.filename= demuxer->stream->url;    avpd.buf= buf;    avpd.buf_size= PROBE_BUF_SIZE;		F("5\n");    if (opt_format) {        if (strcmp(opt_format, "help") == 0) {           list_formats();           return 0;        }        priv->avif= av_find_input_format(opt_format);        if (!priv->avif) {            mp_msg(MSGT_DEMUX,MSGL_FATAL,"Unknown lavf format %s\n", opt_format);            return 0;        }        mp_msg(MSGT_DEMUX,MSGL_INFO,"Forced lavf %s demuxer\n", priv->avif->long_name);        return DEMUXER_TYPE_LAVF;    }    F("6\n");    priv->avif= av_probe_input_format(&avpd, 1);    F("7\n");        if(!priv->avif){        mp_msg(MSGT_HEADER,MSGL_V,"LAVF_check: no clue about this gibberish!\n");        return 0;    }else        mp_msg(MSGT_HEADER,MSGL_V,"LAVF_check: %s\n", priv->avif->long_name);		return DEMUXER_TYPE_LAVF;}static const char *preferred_list[] = {    "dxa",    "wv",    "nuv",    "nut",    "gxf",    "mxf",    "flv",    "swf",    NULL};static int lavf_check_preferred_file(demuxer_t *demuxer){    if (lavf_check_file(demuxer)) {        char **p = preferred_list;        lavf_priv_t *priv = demuxer->priv;        while (*p) {            if (strcmp(*p, priv->avif->name) == 0)                return DEMUXER_TYPE_LAVF_PREFERRED;            p++;        }    }    return 0;}    static demuxer_t* demux_open_lavf(demuxer_t *demuxer){    AVFormatContext *avfc;    AVFormatParameters ap;    const AVOption *opt;    lavf_priv_t *priv= demuxer->priv;    int i,g;    char mp_filename[256]="mp:";    memset(&ap, 0, sizeof(AVFormatParameters));    stream_seek(demuxer->stream, 0);    register_protocol(&mp_protocol);    avfc = av_alloc_format_context();    if (correct_pts)        avfc->flags |= AVFMT_FLAG_GENPTS;    if (index_mode == 0)        avfc->flags |= AVFMT_FLAG_IGNIDX;    ap.prealloced_context = 1;    if(opt_probesize) {        opt = av_set_int(avfc, "probesize", opt_probesize);        if(!opt) mp_msg(MSGT_HEADER,MSGL_ERR, "demux_lavf, couldn't set option probesize to %u\n", opt_probesize);    }    if(opt_analyzeduration) {        opt = av_set_int(avfc, "analyzeduration", opt_analyzeduration * AV_TIME_BASE);        if(!opt) mp_msg(MSGT_HEADER,MSGL_ERR, "demux_lavf, couldn't set option analyzeduration to %u\n", opt_analyzeduration);    }    if(demuxer->stream->url)        strncpy(mp_filename + 3, demuxer->stream->url, sizeof(mp_filename)-3);    else        strncpy(mp_filename + 3, "foobar.dummy", sizeof(mp_filename)-3);        url_fopen(&priv->pb, mp_filename, URL_RDONLY);        ((URLContext*)(priv->pb.opaque))->priv_data= demuxer->stream;            if(av_open_input_stream(&avfc, &priv->pb, mp_filename, priv->avif, &ap)<0){        mp_msg(MSGT_HEADER,MSGL_ERR,"LAVF_header: av_open_input_stream() failed\n");        return NULL;    }    priv->avfc= avfc;    if(av_find_stream_info(avfc) < 0){        mp_msg(MSGT_HEADER,MSGL_ERR,"LAVF_header: av_find_stream_info() failed\n");        return NULL;    }    if(avfc->title    [0]) demux_info_add(demuxer, "name"     , avfc->title    );    if(avfc->author   [0]) demux_info_add(demuxer, "author"   , avfc->author   );    if(avfc->copyright[0]) demux_info_add(demuxer, "copyright", avfc->copyright);    if(avfc->comment  [0]) demux_info_add(demuxer, "comments" , avfc->comment  );    if(avfc->album    [0]) demux_info_add(demuxer, "album"    , avfc->album    );//    if(avfc->year        ) demux_info_add(demuxer, "year"     , avfc->year     );//    if(avfc->track       ) demux_info_add(demuxer, "track"    , avfc->track    );    if(avfc->genre    [0]) demux_info_add(demuxer, "genre"    , avfc->genre    );    for(i=0; i<avfc->nb_streams; i++){        AVStream *st= avfc->streams[i];        AVCodecContext *codec= st->codec;        switch(codec->codec_type){        case CODEC_TYPE_AUDIO:{            WAVEFORMATEX *wf= calloc(sizeof(WAVEFORMATEX) + codec->extradata_size, 1);            sh_audio_t* sh_audio;            if(priv->audio_streams >= MAX_A_STREAMS)                break;            sh_audio=new_sh_audio(demuxer, i);            mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_AudioID, "lavf", i);            if(!sh_audio)                break;            priv->astreams[priv->audio_streams] = i;            priv->audio_streams++;            // mp4a tag is used for all mp4 files no matter what they actually contain            if(codec->codec_tag == MKTAG('m', 'p', '4', 'a'))                codec->codec_tag= 0;            if(codec->codec_id == CODEC_ID_ADPCM_IMA_AMV)                codec->codec_tag= MKTAG('A','M','V','A');            if(!codec->codec_tag)                codec->codec_tag= av_codec_get_tag(mp_wav_taglists, codec->codec_id);            wf->wFormatTag= codec->codec_tag;            wf->nChannels= codec->channels;            wf->nSamplesPerSec= codec->sample_rate;            wf->nAvgBytesPerSec= codec->bit_rate/8;            wf->nBlockAlign= codec->block_align ? codec->block_align : 1;            wf->wBitsPerSample= codec->bits_per_sample;            wf->cbSize= codec->extradata_size;            if(codec->extradata_size){                memcpy(                    wf + 1,                     codec->extradata,                    codec->extradata_size);            }            sh_audio->wf= wf;            sh_audio->audio.dwSampleSize= codec->block_align;            if(codec->frame_size && codec->sample_rate){

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?