Ejemplo n.º 1
0
std::string MovieDecoder::createScaleString(int size, bool maintainAspectRatio)
{
    std::stringstream scale;

    if (!maintainAspectRatio)
    {
        scale << "w=" << size << ":h=" << size;
    }
    else
    {
        auto width      = GetVideoWidth();
        auto height     = GetVideoHeight();

        AVRational par = av_guess_sample_aspect_ratio(m_pFormatContext, m_pVideoStream, m_pFrame);
        // if the pixel aspect ratio is defined and is not 1, we have an anamorphic stream
        bool anamorphic = par.num != 0 && par.num != par.den;

        if (anamorphic)
        {
            width = width * par.num / par.den;
        }

        if (height > width)
        {
            scale << "w=-1:h=" << (size == 0 ? height : size);
        }
        else
        {
            scale << "h=-1:w=" << (size == 0 ? width : size);
        }
    }

    return scale.str();
}
Ejemplo n.º 2
0
bool    Identify::identify(const QString &file, LightBird::IIdentify::Information &information)
{
    QVariantMap     &data = information.data;
    AVFormatContext *format = NULL;
    AVStream        *audioStream = NULL;
    AVStream        *videoStream = NULL;
    AVCodecContext  *audio = NULL;
    AVCodecContext  *video = NULL;
    AVRational      sar;
    AVRational      dar;
    int             code;
    bool            result = true;

    try
    {
        // Opens the input file
        if ((code = avformat_open_input(&format, file.toUtf8().data(), NULL, NULL)) < 0)
        {
            LOG_TRACE("Could not open source file", Properties("file", file).add("error", this->_errorToString(code)).toMap(), "Identify", "identify");
            throw false;
        }
        if ((code = avformat_find_stream_info(format, NULL)) < 0)
        {
            LOG_TRACE("Could not find stream information", Properties("file", file).add("error", this->_errorToString(code)).toMap(), "Identify", "identify");
            throw false;
        }
        // The file should be a document
        if (format->iformat->name == QString("tty"))
        {
            information.type = LightBird::IIdentify::DOCUMENT;
            throw true;
        }
        audioStream = this->_openStream(format, audio, AVMEDIA_TYPE_AUDIO);
        videoStream = this->_openStream(format, video, AVMEDIA_TYPE_VIDEO);
        // No audio or video stream detected
        if (!audioStream && !videoStream)
            throw false;
        // Identify the format
        {
            data.insert("format", format->iformat->name);
            data.insert("format name", format->iformat->long_name);
            if (format->duration)
                data.insert("duration", format->duration * (1.0 / (double)AV_TIME_BASE));
            if (format->bit_rate)
                data.insert("bit rate", format->bit_rate);
            data.insert("streams", format->nb_streams);
            this->_addMetadata(format->metadata, data);
        }
        // Identify the audio stream
        if (audioStream)
        {
            information.type = LightBird::IIdentify::AUDIO;
            data.insert("audio codec", audio->codec->name);
            data.insert("audio codec name", audio->codec->long_name);
            if (audioStream->duration)
                data.insert("audio duration", audioStream->duration * av_q2d(audio->time_base));
            data.insert("channels", audio->channels);
            data.insert("sample rate", audio->sample_rate);
            if (audioStream->nb_frames)
                data.insert("audio frames", (qint64)audioStream->nb_frames);
            data.insert("audio time base", QString("%1/%2").arg(QString::number(audioStream->time_base.num), QString::number(audioStream->time_base.den)));
            data.insert("sample format", av_get_sample_fmt_name(audio->sample_fmt));
            this->_addMetadata(audioStream->metadata, data);
        }
        // Identify the video stream
        if (videoStream && !this->_isImage(videoStream))
        {
            information.type = LightBird::IIdentify::VIDEO;
            data.insert("video codec", video->codec->name);
            data.insert("video codec name", video->codec->long_name);
            data.insert("width", video->width);
            data.insert("height", video->height);
            if (videoStream->duration)
                data.insert("video duration", videoStream->duration * av_q2d(video->time_base));
            data.insert("frame rate", QString("%1/%2").arg(QString::number(videoStream->r_frame_rate.num), QString::number(videoStream->r_frame_rate.den)));
            data.insert("pixel format", av_get_pix_fmt_name(video->pix_fmt));
            if (videoStream->nb_frames)
                data.insert("video frames", (qint64)videoStream->nb_frames);
            if (video->has_b_frames)
                data.insert("has b frames", "true");
            data.insert("video time base", QString("%1/%2").arg(QString::number(videoStream->time_base.num), QString::number(videoStream->time_base.den)));
            sar = av_guess_sample_aspect_ratio(format, videoStream, NULL);
            if (sar.den)
            {
                av_reduce(&dar.num, &dar.den, video->width * sar.num, video->height * sar.den, 1024 * 1024);
                data.insert("aspect ratio", QString("%1/%2").arg(QString::number(dar.num), QString::number(dar.den)));
            }
            this->_addMetadata(videoStream->metadata, data);
        }
    }
    catch (bool exception)
    {
        result = exception;
    }
    if (audio)
        avcodec_close(audio);
    if (video)
        avcodec_close(video);
    if (format)
        avformat_close_input(&format);
    return (result);
}
Ejemplo n.º 3
0
Archivo: demux.c Proyecto: mstorsjo/vlc
int avformat_OpenDemux( vlc_object_t *p_this )
{
    demux_t       *p_demux = (demux_t*)p_this;
    demux_sys_t   *p_sys;
    AVInputFormat *fmt = NULL;
    vlc_tick_t    i_start_time = VLC_TICK_INVALID;
    bool          b_can_seek;
    const char    *psz_url;
    int           error;

    if( p_demux->psz_filepath )
        psz_url = p_demux->psz_filepath;
    else
        psz_url = p_demux->psz_url;

    if( avformat_ProbeDemux( p_this, &fmt, psz_url ) != VLC_SUCCESS )
        return VLC_EGENERIC;

    vlc_stream_Control( p_demux->s, STREAM_CAN_SEEK, &b_can_seek );

    /* Fill p_demux fields */
    p_demux->pf_demux = Demux;
    p_demux->pf_control = Control;
    p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
    if( !p_sys )
        return VLC_ENOMEM;

    p_sys->ic = 0;
    p_sys->fmt = fmt;
    p_sys->tracks = NULL;
    p_sys->i_ssa_order = 0;
    TAB_INIT( p_sys->i_attachments, p_sys->attachments);
    p_sys->p_title = NULL;
    p_sys->i_seekpoint = 0;
    p_sys->i_update = 0;

    /* Create I/O wrapper */
    unsigned char * p_io_buffer = av_malloc( AVFORMAT_IOBUFFER_SIZE );
    if( !p_io_buffer )
    {
        avformat_CloseDemux( p_this );
        return VLC_ENOMEM;
    }

    p_sys->ic = avformat_alloc_context();
    if( !p_sys->ic )
    {
        av_free( p_io_buffer );
        avformat_CloseDemux( p_this );
        return VLC_ENOMEM;
    }

    AVIOContext *pb = p_sys->ic->pb = avio_alloc_context( p_io_buffer,
        AVFORMAT_IOBUFFER_SIZE, 0, p_demux, IORead, NULL, IOSeek );
    if( !pb )
    {
        av_free( p_io_buffer );
        avformat_CloseDemux( p_this );
        return VLC_ENOMEM;
    }

    p_sys->ic->pb->seekable = b_can_seek ? AVIO_SEEKABLE_NORMAL : 0;
    error = avformat_open_input(&p_sys->ic, psz_url, p_sys->fmt, NULL);

    if( error < 0 )
    {
        msg_Err( p_demux, "Could not open %s: %s", psz_url,
                 vlc_strerror_c(AVUNERROR(error)) );
        av_free( pb->buffer );
        av_free( pb );
        p_sys->ic = NULL;
        avformat_CloseDemux( p_this );
        return VLC_EGENERIC;
    }

    char *psz_opts = var_InheritString( p_demux, "avformat-options" );
    unsigned nb_streams = p_sys->ic->nb_streams;

    AVDictionary *options[nb_streams ? nb_streams : 1];
    options[0] = NULL;
    for (unsigned i = 1; i < nb_streams; i++)
        options[i] = NULL;
    if (psz_opts) {
        vlc_av_get_options(psz_opts, &options[0]);
        for (unsigned i = 1; i < nb_streams; i++) {
            av_dict_copy(&options[i], options[0], 0);
        }
        free(psz_opts);
    }
    vlc_avcodec_lock(); /* avformat calls avcodec behind our back!!! */
    error = avformat_find_stream_info( p_sys->ic, options );
    vlc_avcodec_unlock();
    AVDictionaryEntry *t = NULL;
    while ((t = av_dict_get(options[0], "", t, AV_DICT_IGNORE_SUFFIX))) {
        msg_Err( p_demux, "Unknown option \"%s\"", t->key );
    }
    av_dict_free(&options[0]);
    for (unsigned i = 1; i < nb_streams; i++) {
        av_dict_free(&options[i]);
    }

    nb_streams = p_sys->ic->nb_streams; /* it may have changed */
    if( !nb_streams )
    {
        msg_Err( p_demux, "No streams found");
        avformat_CloseDemux( p_this );
        return VLC_EGENERIC;
    }
    p_sys->tracks = calloc( nb_streams, sizeof(*p_sys->tracks) );
    if( !p_sys->tracks )
    {
        avformat_CloseDemux( p_this );
        return VLC_ENOMEM;
    }
    p_sys->i_tracks = nb_streams;

    if( error < 0 )
    {
        msg_Warn( p_demux, "Could not find stream info: %s",
                  vlc_strerror_c(AVUNERROR(error)) );
    }

    for( unsigned i = 0; i < nb_streams; i++ )
    {
        struct avformat_track_s *p_track = &p_sys->tracks[i];
        AVStream *s = p_sys->ic->streams[i];
        const AVCodecParameters *cp = s->codecpar;
        es_format_t es_fmt;
        const char *psz_type = "unknown";

        /* Do not use the cover art as a stream */
        if( s->disposition == AV_DISPOSITION_ATTACHED_PIC )
            continue;

        vlc_fourcc_t fcc = GetVlcFourcc( cp->codec_id );
        switch( cp->codec_type )
        {
        case AVMEDIA_TYPE_AUDIO:
            es_format_Init( &es_fmt, AUDIO_ES, fcc );
            es_fmt.i_original_fourcc = CodecTagToFourcc( cp->codec_tag );
            es_fmt.i_bitrate = cp->bit_rate;
            es_fmt.audio.i_channels = cp->channels;
            es_fmt.audio.i_rate = cp->sample_rate;
            es_fmt.audio.i_bitspersample = cp->bits_per_coded_sample;
            es_fmt.audio.i_blockalign = cp->block_align;
            psz_type = "audio";

            if(cp->codec_id == AV_CODEC_ID_AAC_LATM)
            {
                es_fmt.i_original_fourcc = VLC_FOURCC('L','A','T','M');
                es_fmt.b_packetized = false;
            }
            else if(cp->codec_id == AV_CODEC_ID_AAC && p_sys->fmt->long_name &&
                    strstr(p_sys->fmt->long_name, "raw ADTS AAC"))
            {
                es_fmt.i_original_fourcc = VLC_FOURCC('A','D','T','S');
                es_fmt.b_packetized = false;
            }
            break;

        case AVMEDIA_TYPE_VIDEO:
            es_format_Init( &es_fmt, VIDEO_ES, fcc );
            es_fmt.i_original_fourcc = CodecTagToFourcc( cp->codec_tag );

            es_fmt.video.i_bits_per_pixel = cp->bits_per_coded_sample;
            /* Special case for raw video data */
            if( cp->codec_id == AV_CODEC_ID_RAWVIDEO )
            {
                msg_Dbg( p_demux, "raw video, pixel format: %i", cp->format );
                if( GetVlcChroma( &es_fmt.video, cp->format ) != VLC_SUCCESS)
                {
                    msg_Err( p_demux, "was unable to find a FourCC match for raw video" );
                }
                else
                    es_fmt.i_codec = es_fmt.video.i_chroma;
            }
            /* We need this for the h264 packetizer */
            else if( cp->codec_id == AV_CODEC_ID_H264 && ( p_sys->fmt == av_find_input_format("flv") ||
                p_sys->fmt == av_find_input_format("matroska") || p_sys->fmt == av_find_input_format("mp4") ) )
                es_fmt.i_original_fourcc = VLC_FOURCC( 'a', 'v', 'c', '1' );

            es_fmt.video.i_width = cp->width;
            es_fmt.video.i_height = cp->height;
            es_fmt.video.i_visible_width = es_fmt.video.i_width;
            es_fmt.video.i_visible_height = es_fmt.video.i_height;

            get_rotation(&es_fmt, s);

# warning FIXME: implement palette transmission
            psz_type = "video";

            AVRational rate;
#if (LIBAVUTIL_VERSION_MICRO < 100) /* libav */
# if (LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(55, 20, 0))
            rate.num = s->time_base.num;
            rate.den = s->time_base.den;
# else
            rate.num = s->codec->time_base.num;
            rate.den = s->codec->time_base.den;
# endif
            rate.den *= __MAX( s->codec->ticks_per_frame, 1 );
#else /* ffmpeg */
            rate = av_guess_frame_rate( p_sys->ic, s, NULL );
#endif
            if( rate.den && rate.num )
            {
                es_fmt.video.i_frame_rate = rate.num;
                es_fmt.video.i_frame_rate_base = rate.den;
            }

            AVRational ar;
#if (LIBAVUTIL_VERSION_MICRO < 100) /* libav */
            ar.num = s->sample_aspect_ratio.num;
            ar.den = s->sample_aspect_ratio.den;
#else
            ar = av_guess_sample_aspect_ratio( p_sys->ic, s, NULL );
#endif
            if( ar.num && ar.den )
            {
                es_fmt.video.i_sar_den = ar.den;
                es_fmt.video.i_sar_num = ar.num;
            }
            break;

        case AVMEDIA_TYPE_SUBTITLE:
            es_format_Init( &es_fmt, SPU_ES, fcc );
            es_fmt.i_original_fourcc = CodecTagToFourcc( cp->codec_tag );
            if( strncmp( p_sys->ic->iformat->name, "matroska", 8 ) == 0 &&
                cp->codec_id == AV_CODEC_ID_DVD_SUBTITLE &&
                cp->extradata != NULL &&
                cp->extradata_size > 0 )
            {
                char *psz_start;
                char *psz_buf = malloc( cp->extradata_size + 1);
                if( psz_buf != NULL )
                {
                    memcpy( psz_buf, cp->extradata , cp->extradata_size );
                    psz_buf[cp->extradata_size] = '\0';

                    psz_start = strstr( psz_buf, "size:" );
                    if( psz_start &&
                        vobsub_size_parse( psz_start,
                                           &es_fmt.subs.spu.i_original_frame_width,
                                           &es_fmt.subs.spu.i_original_frame_height ) == VLC_SUCCESS )
                    {
                        msg_Dbg( p_demux, "original frame size: %dx%d",
                                 es_fmt.subs.spu.i_original_frame_width,
                                 es_fmt.subs.spu.i_original_frame_height );
                    }
                    else
                    {
                        msg_Warn( p_demux, "reading original frame size failed" );
                    }

                    psz_start = strstr( psz_buf, "palette:" );
                    if( psz_start &&
                        vobsub_palette_parse( psz_start, &es_fmt.subs.spu.palette[1] ) == VLC_SUCCESS )
                    {
                        es_fmt.subs.spu.palette[0] = SPU_PALETTE_DEFINED;
                        msg_Dbg( p_demux, "vobsub palette read" );
                    }
                    else
                    {
                        msg_Warn( p_demux, "reading original palette failed" );
                    }
                    free( psz_buf );
                }
            }
            else if( cp->codec_id == AV_CODEC_ID_DVB_SUBTITLE &&
                     cp->extradata_size > 3 )
            {
                es_fmt.subs.dvb.i_id = GetWBE( cp->extradata ) |
                                      (GetWBE( cp->extradata + 2 ) << 16);
            }
            else if( cp->codec_id == AV_CODEC_ID_MOV_TEXT )
            {
                if( cp->extradata_size && (es_fmt.p_extra = malloc(cp->extradata_size)) )
                {
                    memcpy( es_fmt.p_extra, cp->extradata, cp->extradata_size );
                    es_fmt.i_extra = cp->extradata_size;
                }
            }
            psz_type = "subtitle";
            break;

        default:
            es_format_Init( &es_fmt, UNKNOWN_ES, 0 );
            es_fmt.i_original_fourcc = CodecTagToFourcc( cp->codec_tag );
#ifdef HAVE_AVUTIL_CODEC_ATTACHMENT
            if( cp->codec_type == AVMEDIA_TYPE_ATTACHMENT )
            {
                input_attachment_t *p_attachment;

                psz_type = "attachment";
                if( cp->codec_id == AV_CODEC_ID_TTF )
                {
                    AVDictionaryEntry *filename = av_dict_get( s->metadata, "filename", NULL, 0 );
                    if( filename && filename->value )
                    {
                        p_attachment = vlc_input_attachment_New(
                                filename->value, "application/x-truetype-font",
                                NULL, cp->extradata, (int)cp->extradata_size );
                        if( p_attachment )
                            TAB_APPEND( p_sys->i_attachments, p_sys->attachments,
                                        p_attachment );
                    }
                }
                else msg_Warn( p_demux, "unsupported attachment type (%u) in avformat demux", cp->codec_id );
            }
            else
#endif
            {
                if( cp->codec_type == AVMEDIA_TYPE_DATA )
                    psz_type = "data";

                msg_Warn( p_demux, "unsupported track type (%u:%u) in avformat demux", cp->codec_type, cp->codec_id );
            }
            break;
        }

        AVDictionaryEntry *language = av_dict_get( s->metadata, "language", NULL, 0 );
        if ( language && language->value )
            es_fmt.psz_language = strdup( language->value );

        if( s->disposition & AV_DISPOSITION_DEFAULT )
            es_fmt.i_priority = ES_PRIORITY_SELECTABLE_MIN + 1000;

#ifdef HAVE_AVUTIL_CODEC_ATTACHMENT
        if( cp->codec_type != AVMEDIA_TYPE_ATTACHMENT )
#endif
        if( cp->codec_type != AVMEDIA_TYPE_DATA )
        {
            const bool    b_ogg = !strcmp( p_sys->fmt->name, "ogg" );
            const uint8_t *p_extra = cp->extradata;
            unsigned      i_extra  = cp->extradata_size;

            if( cp->codec_id == AV_CODEC_ID_THEORA && b_ogg )
            {
                unsigned pi_size[3];
                const void *pp_data[3];
                unsigned i_count;
                for( i_count = 0; i_count < 3; i_count++ )
                {
                    if( i_extra < 2 )
                        break;
                    pi_size[i_count] = GetWBE( p_extra );
                    pp_data[i_count] = &p_extra[2];
                    if( i_extra < pi_size[i_count] + 2 )
                        break;

                    p_extra += 2 + pi_size[i_count];
                    i_extra -= 2 + pi_size[i_count];
                }
                if( i_count > 0 && xiph_PackHeaders( &es_fmt.i_extra, &es_fmt.p_extra,
                                                     pi_size, pp_data, i_count ) )
                {
                    es_fmt.i_extra = 0;
                    es_fmt.p_extra = NULL;
                }
            }
            else if( cp->codec_id == AV_CODEC_ID_SPEEX && b_ogg )
            {
                const uint8_t p_dummy_comment[] = {
                    0, 0, 0, 0,
                    0, 0, 0, 0,
                };
                unsigned pi_size[2];
                const void *pp_data[2];

                pi_size[0] = i_extra;
                pp_data[0] = p_extra;

                pi_size[1] = sizeof(p_dummy_comment);
                pp_data[1] = p_dummy_comment;

                if( pi_size[0] > 0 && xiph_PackHeaders( &es_fmt.i_extra, &es_fmt.p_extra,
                                                        pi_size, pp_data, 2 ) )
                {
                    es_fmt.i_extra = 0;
                    es_fmt.p_extra = NULL;
                }
            }
            else if( cp->codec_id == AV_CODEC_ID_OPUS )
            {
                const uint8_t p_dummy_comment[] = {
                    'O', 'p', 'u', 's',
                    'T', 'a', 'g', 's',
                    0, 0, 0, 0, /* Vendor String length */
                                /* Vendor String */
                    0, 0, 0, 0, /* User Comment List Length */

                };
                unsigned pi_size[2];
                const void *pp_data[2];

                pi_size[0] = i_extra;
                pp_data[0] = p_extra;

                pi_size[1] = sizeof(p_dummy_comment);
                pp_data[1] = p_dummy_comment;

                if( pi_size[0] > 0 && xiph_PackHeaders( &es_fmt.i_extra, &es_fmt.p_extra,
                                                        pi_size, pp_data, 2 ) )
                {
                    es_fmt.i_extra = 0;
                    es_fmt.p_extra = NULL;
                }
            }
            else if( cp->extradata_size > 0 && !es_fmt.i_extra )
            {
                es_fmt.p_extra = malloc( i_extra );
                if( es_fmt.p_extra )
                {
                    es_fmt.i_extra = i_extra;
                    memcpy( es_fmt.p_extra, p_extra, i_extra );
                }
            }

            p_track->p_es = es_out_Add( p_demux->out, &es_fmt );
            if( p_track->p_es && (s->disposition & AV_DISPOSITION_DEFAULT) )
                es_out_Control( p_demux->out, ES_OUT_SET_ES_DEFAULT, p_track->p_es );

            msg_Dbg( p_demux, "adding es: %s codec = %4.4s (%d)",
                     psz_type, (char*)&fcc, cp->codec_id  );
        }
        es_format_Clean( &es_fmt );
    }

    if( p_sys->ic->start_time != (int64_t)AV_NOPTS_VALUE )
        i_start_time = FROM_AV_TS(p_sys->ic->start_time);

    msg_Dbg( p_demux, "AVFormat(%s %s) supported stream", AVPROVIDER(LIBAVFORMAT), LIBAVFORMAT_IDENT );
    msg_Dbg( p_demux, "    - format = %s (%s)",
             p_sys->fmt->name, p_sys->fmt->long_name );
    msg_Dbg( p_demux, "    - start time = %"PRId64, i_start_time );
    msg_Dbg( p_demux, "    - duration = %"PRId64,
             ( p_sys->ic->duration != (int64_t)AV_NOPTS_VALUE ) ?
             FROM_AV_TS(p_sys->ic->duration) : -1 );

    if( p_sys->ic->nb_chapters > 0 )
    {
        p_sys->p_title = vlc_input_title_New();
        p_sys->p_title->i_length = FROM_AV_TS(p_sys->ic->duration);
    }

    for( unsigned i = 0; i < p_sys->ic->nb_chapters; i++ )
    {
        seekpoint_t *s = vlc_seekpoint_New();

        AVDictionaryEntry *title = av_dict_get( p_sys->ic->metadata, "title", NULL, 0);
        if( title && title->value )
        {
            s->psz_name = strdup( title->value );
            EnsureUTF8( s->psz_name );
            msg_Dbg( p_demux, "    - chapter %d: %s", i, s->psz_name );
        }
        s->i_time_offset = vlc_tick_from_samples( p_sys->ic->chapters[i]->start *
            p_sys->ic->chapters[i]->time_base.num,
            p_sys->ic->chapters[i]->time_base.den ) -
            (i_start_time != VLC_TICK_INVALID ? i_start_time : 0 );
        TAB_APPEND( p_sys->p_title->i_seekpoint, p_sys->p_title->seekpoint, s );
    }

    ResetTime( p_demux, 0 );
    return VLC_SUCCESS;
}
Ejemplo n.º 4
0
void cVideo::run(void)
{
	lt_info("====================== start decoder thread ================================\n");
	AVCodec *codec;
	AVCodecContext *c= NULL;
	AVFormatContext *avfc = NULL;
	AVInputFormat *inp;
	AVFrame *frame, *rgbframe;
	uint8_t *inbuf = (uint8_t *)av_malloc(INBUF_SIZE);
	AVPacket avpkt;
	struct SwsContext *convert = NULL;

	time_t warn_r = 0; /* last read error */
	time_t warn_d = 0; /* last decode error */

	bufpos = 0;
	buf_num = 0;
	buf_in = 0;
	buf_out = 0;
	dec_r = 0;

	av_init_packet(&avpkt);
	inp = av_find_input_format("mpegts");
	AVIOContext *pIOCtx = avio_alloc_context(inbuf, INBUF_SIZE, // internal Buffer and its size
			0,		// bWriteable (1=true,0=false)
			NULL,		// user data; will be passed to our callback functions
			my_read,	// read callback
			NULL,		// write callback
			NULL);		// seek callback
	avfc = avformat_alloc_context();
	avfc->pb = pIOCtx;
	avfc->iformat = inp;
	avfc->probesize = 188*5;

	thread_running = true;
	if (avformat_open_input(&avfc, NULL, inp, NULL) < 0) {
		lt_info("%s: Could not open input\n", __func__);
		goto out;
	}
	while (avfc->nb_streams < 1)
	{
		lt_info("%s: nb_streams %d, should be 1 => retry\n", __func__, avfc->nb_streams);
		if (av_read_frame(avfc, &avpkt) < 0)
			lt_info("%s: av_read_frame < 0\n", __func__);
		av_free_packet(&avpkt);
		if (! thread_running)
			goto out;
	}

	if (avfc->streams[0]->codec->codec_type != AVMEDIA_TYPE_VIDEO)
		lt_info("%s: no video codec? 0x%x\n", __func__, avfc->streams[0]->codec->codec_type);

	c = avfc->streams[0]->codec;
	codec = avcodec_find_decoder(c->codec_id);
	if (!codec) {
		lt_info("%s: Codec for %s not found\n", __func__, avcodec_get_name(c->codec_id));
		goto out;
	}
	if (avcodec_open2(c, codec, NULL) < 0) {
		lt_info("%s: Could not open codec\n", __func__);
		goto out;
	}
	frame = av_frame_alloc();
	rgbframe = av_frame_alloc();
	if (!frame || !rgbframe) {
		lt_info("%s: Could not allocate video frame\n", __func__);
		goto out2;
	}
	lt_info("decoding %s\n", avcodec_get_name(c->codec_id));
	while (thread_running) {
		if (av_read_frame(avfc, &avpkt) < 0) {
			if (warn_r - time(NULL) > 4) {
				lt_info("%s: av_read_frame < 0\n", __func__);
				warn_r = time(NULL);
			}
			usleep(10000);
			continue;
		}
		int got_frame = 0;
		int len = avcodec_decode_video2(c, frame, &got_frame, &avpkt);
		if (len < 0) {
			if (warn_d - time(NULL) > 4) {
				lt_info("%s: avcodec_decode_video2 %d\n", __func__, len);
				warn_d = time(NULL);
			}
			av_free_packet(&avpkt);
			continue;
		}
		if (avpkt.size > len)
			lt_info("%s: WARN: pkt->size %d != len %d\n", __func__, avpkt.size, len);
		if (got_frame) {
			unsigned int need = avpicture_get_size(PIX_FMT_RGB32, c->width, c->height);
			convert = sws_getCachedContext(convert,
						       c->width, c->height, c->pix_fmt,
						       c->width, c->height, PIX_FMT_RGB32,
						       SWS_BICUBIC, 0, 0, 0);
			if (!convert)
				lt_info("%s: ERROR setting up SWS context\n", __func__);
			else {
				buf_m.lock();
				SWFramebuffer *f = &buffers[buf_in];
				if (f->size() < need)
					f->resize(need);
				avpicture_fill((AVPicture *)rgbframe, &(*f)[0], PIX_FMT_RGB32,
						c->width, c->height);
				sws_scale(convert, frame->data, frame->linesize, 0, c->height,
						rgbframe->data, rgbframe->linesize);
				if (dec_w != c->width || dec_h != c->height) {
					lt_info("%s: pic changed %dx%d -> %dx%d\n", __func__,
							dec_w, dec_h, c->width, c->height);
					dec_w = c->width;
					dec_h = c->height;
					w_h_changed = true;
				}
				f->width(c->width);
				f->height(c->height);
				int64_t vpts = av_frame_get_best_effort_timestamp(frame);
				if (v_format == VIDEO_FORMAT_MPEG2)
					vpts += 90000*3/10; /* 300ms */
				f->pts(vpts);
				AVRational a = av_guess_sample_aspect_ratio(avfc, avfc->streams[0], frame);
				f->AR(a);
				buf_in++;
				buf_in %= VDEC_MAXBUFS;
				buf_num++;
				if (buf_num > (VDEC_MAXBUFS - 1)) {
					lt_info("%s: buf_num overflow\n", __func__);
					buf_out++;
					buf_out %= VDEC_MAXBUFS;
					buf_num--;
				}
				dec_r = c->time_base.den/(c->time_base.num * c->ticks_per_frame);
				buf_m.unlock();
			}
			lt_debug("%s: time_base: %d/%d, ticks: %d rate: %d pts 0x%" PRIx64 "\n", __func__,
					c->time_base.num, c->time_base.den, c->ticks_per_frame, dec_r,
					av_frame_get_best_effort_timestamp(frame));
		}
		av_free_packet(&avpkt);
	}
	sws_freeContext(convert);
 out2:
	avcodec_close(c);
	av_frame_free(&frame);
	av_frame_free(&rgbframe);
 out:
	avformat_close_input(&avfc);
	av_free(pIOCtx->buffer);
	av_free(pIOCtx);
	/* reset output buffers */
	bufpos = 0;
	buf_num = 0;
	buf_in = 0;
	buf_out = 0;
	lt_info("======================== end decoder thread ================================\n");
}
Ejemplo n.º 5
0
void cVideo::ShowPicture(const char *fname, const char *)
{
	lt_info("%s(%s)\n", __func__, fname);
	if (access(fname, R_OK))
		return;

	unsigned int i;
	int stream_id = -1;
	int got_frame = 0;
	int len;
	AVFormatContext *avfc = NULL;
	AVCodecContext *c = NULL;
	AVCodec *codec;
	AVFrame *frame, *rgbframe;
	AVPacket avpkt;

	if (avformat_open_input(&avfc, fname, NULL, NULL) < 0) {
		lt_info("%s: Could not open file %s\n", __func__, fname);
		return;
	}

	if (avformat_find_stream_info(avfc, NULL) < 0) {
		lt_info("%s: Could not find file info %s\n", __func__, fname);
		goto out_close;
	}
	for (i = 0; i < avfc->nb_streams; i++) {
		if (avfc->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
			stream_id = i;
			break;
		}
	}
	if (stream_id < 0)
		goto out_close;
	c = avfc->streams[stream_id]->codec;
	codec = avcodec_find_decoder(c->codec_id);
	if (!avcodec_open2(c, codec, NULL) < 0) {
		lt_info("%s: Could not find/open the codec, id 0x%x\n", __func__, c->codec_id);
		goto out_close;
	}
	frame = av_frame_alloc();
	rgbframe = av_frame_alloc();
	if (!frame || !rgbframe) {
		lt_info("%s: Could not allocate video frame\n", __func__);
		goto out_free;
	}
	av_init_packet(&avpkt);
	if (av_read_frame(avfc, &avpkt) < 0) {
		lt_info("%s: av_read_frame < 0\n", __func__);
		goto out_free;
	}
	len = avcodec_decode_video2(c, frame, &got_frame, &avpkt);
	if (len < 0) {
		lt_info("%s: avcodec_decode_video2 %d\n", __func__, len);
		av_free_packet(&avpkt);
		goto out_free;
	}
	if (avpkt.size > len)
		lt_info("%s: WARN: pkt->size %d != len %d\n", __func__, avpkt.size, len);
	if (got_frame) {
		unsigned int need = avpicture_get_size(PIX_FMT_RGB32, c->width, c->height);
		struct SwsContext *convert = sws_getContext(c->width, c->height, c->pix_fmt,
							    c->width, c->height, PIX_FMT_RGB32,
							    SWS_BICUBIC, 0, 0, 0);
		if (!convert)
			lt_info("%s: ERROR setting up SWS context\n", __func__);
		else {
			buf_m.lock();
			SWFramebuffer *f = &buffers[buf_in];
			if (f->size() < need)
				f->resize(need);
			avpicture_fill((AVPicture *)rgbframe, &(*f)[0], PIX_FMT_RGB32,
					c->width, c->height);
			sws_scale(convert, frame->data, frame->linesize, 0, c->height,
					rgbframe->data, rgbframe->linesize);
			sws_freeContext(convert);
			f->width(c->width);
			f->height(c->height);
			f->pts(AV_NOPTS_VALUE);
			AVRational a = av_guess_sample_aspect_ratio(avfc, avfc->streams[stream_id], frame);
			f->AR(a);
			buf_in++;
			buf_in %= VDEC_MAXBUFS;
			buf_num++;
			if (buf_num > (VDEC_MAXBUFS - 1)) {
				lt_debug("%s: buf_num overflow\n", __func__);
				buf_out++;
				buf_out %= VDEC_MAXBUFS;
				buf_num--;
			}
			buf_m.unlock();
		}
	}
	av_free_packet(&avpkt);
 out_free:
	avcodec_close(c);
	av_frame_free(&frame);
	av_frame_free(&rgbframe);
 out_close:
	avformat_close_input(&avfc);
	lt_debug("%s(%s) end\n", __func__, fname);
}
Ejemplo n.º 6
0
void QFFmpegPlayer::run()
{


    int err, i, ret;
    int st_index[AVMEDIA_TYPE_NB];
    AVPacket pkt1, *pkt = &pkt1;
    int64_t stream_start_time;
    int pkt_in_play_range = 0;
    AVDictionaryEntry *t;
    AVDictionary **opts;
    int orig_nb_streams;
    QMutex *wait_mutex = new QMutex();
    int scan_all_pmts_set = 0;
    int64_t pkt_ts;
    float max_frame_duration;
    int realtime;

    AVFormatContext *formatCtx=avformat_alloc_context();
    AVFrame *frame=av_frame_alloc();


    int video_stream = -1;
    int audio_stream = -1;
    int subtitle_stream = -1;
    int eof = 0;



    formatCtx->interrupt_callback.callback = DecodeInterruptCallback;
    formatCtx->interrupt_callback.opaque = this;

    memset(st_index, -1, sizeof(st_index));
    ret = avformat_open_input(&formatCtx, "D:/Music/mww.mp4",NULL, NULL);
    if (ret < 0) {
        qDebug("avformat_open_input fail!");
        return;
    }

    // av_dump_format(formatCtx, 0, 0, 0);

    av_format_inject_global_side_data(formatCtx);


    orig_nb_streams = formatCtx->nb_streams;


    if (formatCtx->pb)
        formatCtx->pb->eof_reached = 0;


    max_frame_duration = (formatCtx->iformat->flags & AVFMT_TS_DISCONT) ? 10.0 : 3600.0;



    realtime = is_realtime(formatCtx);




    for (i = 0; i < formatCtx->nb_streams; i++) {
        AVStream *st = formatCtx->streams[i];
        AVMediaType type = st->codec->codec_type;
        //st->discard = AVDISCARD_ALL;
        if (st_index[type] == -1)
            st_index[type] = i;
    }

    for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
        if (st_index[i] == -1) {
            st_index[i] = INT_MAX;
        }
    }


    st_index[AVMEDIA_TYPE_VIDEO] =
        av_find_best_stream(formatCtx, AVMEDIA_TYPE_VIDEO,
                            st_index[AVMEDIA_TYPE_VIDEO], -1, NULL, 0);

    st_index[AVMEDIA_TYPE_AUDIO] =
        av_find_best_stream(formatCtx, AVMEDIA_TYPE_AUDIO,
                            st_index[AVMEDIA_TYPE_AUDIO],
                            st_index[AVMEDIA_TYPE_VIDEO],
                            NULL, 0);

    st_index[AVMEDIA_TYPE_SUBTITLE] =
        av_find_best_stream(formatCtx, AVMEDIA_TYPE_SUBTITLE,
                            st_index[AVMEDIA_TYPE_SUBTITLE],
                            (st_index[AVMEDIA_TYPE_AUDIO] >= 0 ?
                             st_index[AVMEDIA_TYPE_AUDIO] :
                             st_index[AVMEDIA_TYPE_VIDEO]),
                            NULL, 0);
    video_stream=st_index[AVMEDIA_TYPE_VIDEO];
    audio_stream=st_index[AVMEDIA_TYPE_AUDIO];

    qDebug("video:%d audio:%d subtitle:%d",st_index[AVMEDIA_TYPE_VIDEO],st_index[AVMEDIA_TYPE_AUDIO],st_index[AVMEDIA_TYPE_SUBTITLE]);


    if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
        AVStream *st = formatCtx->streams[st_index[AVMEDIA_TYPE_VIDEO]];
        AVCodecContext *avctx = st->codec;
        AVRational sar = av_guess_sample_aspect_ratio(formatCtx, st, NULL);
        if (avctx->width)
        {
            qDebug("window size:%d*%d SAR:%d/%d",avctx->width,avctx->height,sar.num,sar.den);
        }

    }


    if (st_index[AVMEDIA_TYPE_AUDIO] >= 0) {
        AVCodecContext *mAudioCtx = formatCtx->streams[st_index[AVMEDIA_TYPE_AUDIO]]->codec;

        AVCodec *mAudioCodec = avcodec_find_decoder(mAudioCtx->codec_id);
        if(mAudioCodec->capabilities & CODEC_CAP_DR1)
            mAudioCtx->flags |= CODEC_FLAG_EMU_EDGE;

        ret = avcodec_open2(mAudioCtx, mAudioCodec, NULL);
        if(ret<0)
            return;

        formatCtx->streams[st_index[AVMEDIA_TYPE_AUDIO]]->discard = AVDISCARD_DEFAULT;

        //sample_rate    = mAudioCtx->sample_rate;
        //nb_channels    = mAudioCtx->channels;
        //channel_layout = mAudioCtx->channel_layout;

        //开启音频解码
        mAudioDecoder->setCodecCtx(mAudioCtx);
        mAudioDecoder->setStream(formatCtx->streams[st_index[AVMEDIA_TYPE_AUDIO]]);
        mAudioDecoder->start();
    }


    if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
        AVCodecContext *mVideoCtx = formatCtx->streams[st_index[AVMEDIA_TYPE_VIDEO]]->codec;

        AVCodec *mVideoCodec = avcodec_find_decoder(mVideoCtx->codec_id);
        //if(mVideoCodec->capabilities & CODEC_CAP_DR1)
        //    mVideoCodec->flags |= CODEC_FLAG_EMU_EDGE;

        ret = avcodec_open2(mVideoCtx, mVideoCodec, NULL);
        if(ret<0)
            return;
        mVideoDecoder->setFormatCtx(formatCtx);
        mVideoDecoder->setCodecCtx(mVideoCtx);
        mVideoDecoder->setStream(formatCtx->streams[st_index[AVMEDIA_TYPE_VIDEO]]);
        mVideoDecoder->start();

    }


    if (st_index[AVMEDIA_TYPE_SUBTITLE] >= 0) {


    }


    while(true)
    {


        if(abort)
        {
            qDebug("++++++++++");
            //this->deleteLater();

            return;
        }

        if(mAudioDecoder->getQueueLength() >10 && mVideoDecoder->getQueueLength() >10)
        {
            QThread::msleep(20);
            continue;
        }


        ret = av_read_frame(formatCtx, pkt);
        //qDebug("av_read_frame:%d",pkt->stream_index);



        if (ret < 0)
        {
            if ((ret == AVERROR_EOF || avio_feof(formatCtx->pb)) && !eof)
            {
                /*if (mVideoState->video_stream >= 0)
                mVideoState->videoq.packet_queue_put_nullpacket(mVideoState->video_stream);
                if (mVideoState->audio_stream >= 0)
                mVideoState->audioq.packet_queue_put_nullpacket(mVideoState->audio_stream);
                if (mVideoState->subtitle_stream >= 0)
                mVideoState->subtitleq.packet_queue_put_nullpacket(mVideoState->subtitle_stream);*/
                eof = 1;
            }
            if (formatCtx->pb && formatCtx->pb->error)
                return;

        }
        else
        {

            eof = 0;

            int64_t stream_start_time = formatCtx->streams[pkt->stream_index]->start_time;
            pkt_ts = pkt->pts == AV_NOPTS_VALUE ? pkt->dts : pkt->pts;
            //qDebug(".............:%d",pkt->stream_index);

            if (pkt->stream_index == audio_stream )
            {
                mAudioDecoder->addPacket(*pkt);
            }
            else if (pkt->stream_index == video_stream)
                //&& !(formatCtx->streams[pkt->stream_index]->disposition & AV_DISPOSITION_ATTACHED_PIC))
            {
                mVideoDecoder->addPacket(*pkt);


            }
            else if (pkt->stream_index == subtitle_stream)
            {
                av_free_packet(pkt);
            }
            else
            {
                av_free_packet(pkt);
            }

            //qDebug("else end");
        }

    }

}