ffmpeggrabber.cpp

来自「一个语言识别引擎」· C++ 代码 · 共 531 行 · 第 1/2 页

CPP
531
字号
                            AVFormatContext **ppFormatCtx) {

    AVFormatParameters formatParams;
    AVInputFormat *iformat;
	
	formatParams.device = strdup(config.check("v4ldevice",Value("/dev/video0")).asString().c_str());
    formatParams.channel = config.check("channel",Value(0)).asInt();
    formatParams.standard = strdup(config.check("standard",Value("ntsc")).asString().c_str());
    formatParams.width = config.check("width",Value(640)).asInt();
    formatParams.height = config.check("height",Value(480)).asInt();
    formatParams.time_base.den = config.check("time_base_den",
                                              Value(29)).asInt();
    formatParams.time_base.num = config.check("time_base_num",
                                              Value(1)).asInt();

    iformat = av_find_input_format("video4linux");

    return (av_open_input_file(ppFormatCtx,
                               "", iformat, 0, &formatParams)==0);

}



bool FfmpegGrabber::openFirewire(yarp::os::Searchable & config, 
                                 AVFormatContext **ppFormatCtx) {
    AVFormatParameters formatParams;
    AVInputFormat *iformat;
    ConstString devname = config.check("devname",Value("/dev/dv1394")).asString();
    formatParams.device = devname.c_str();
    iformat = av_find_input_format("dv1394");
    printf("Checking for digital video in %s\n", devname.c_str());
    return av_open_input_file(ppFormatCtx,
                              "", iformat, 0, &formatParams)==0;
}


bool FfmpegGrabber::openFile(AVFormatContext **ppFormatCtx,
                             const char *fname) {
    return av_open_input_file(ppFormatCtx, fname, NULL, 0, NULL)==0;
}


bool FfmpegGrabber::open(yarp::os::Searchable & config) {

    ConstString fname = 
        config.check("source",Value("default.avi")).asString();

    // Register all formats and codecs
    av_register_all();

    // Open video file
    if (config.check("v4l")) {
        needRateControl = false; // reading from live media
        if (!openV4L(config,&pFormatCtx)) {
            printf("Could not open Video4Linux input\n");
            return false;
        }
    } else if (config.check("ieee1394")) {
        needRateControl = false; // reading from live media
        if (!openFirewire(config,&pFormatCtx)) {
            printf("Could not open ieee1394 input\n");
            return false;
        }
    } else {
        needRateControl = true; // reading from recorded media
        if (!openFile(&pFormatCtx,fname.c_str())) {
            printf("Could not open avi file %s\n", fname.c_str());
            return false; // Couldn't open file
        }
    }
        
    // Retrieve stream information
    if(av_find_stream_info(pFormatCtx)<0) {
        printf("Could not find stream information in %s\n", fname.c_str());
        return false; // Couldn't find stream information
    }

    // Dump information about file onto standard error
    dump_format(pFormatCtx, 0, fname.c_str(), false);

    YARP_ASSERT(system_resource==NULL);
    system_resource = new FfmpegHelper;
    YARP_ASSERT(system_resource!=NULL);
    FfmpegHelper& helper = HELPER(system_resource);
    DecoderState& videoDecoder = helper.videoDecoder;
    DecoderState& audioDecoder = helper.audioDecoder;


    // Find the first video stream
    int videoStream = videoDecoder.getStream(pFormatCtx,CODEC_TYPE_VIDEO,
                                             "video");
    // Find the first audio stream
    int audioStream = audioDecoder.getStream(pFormatCtx,CODEC_TYPE_AUDIO,
                                             "audio");

    if (videoStream==-1&&audioStream==-1) {
        return false;
    }

    _hasVideo = (videoStream!=-1);
    _hasAudio = (audioStream!=-1);

    bool ok = true;
    if (_hasVideo) {
        ok = ok && videoDecoder.getCodec(pFormatCtx);
    }
    if (_hasAudio) {
        ok = ok && audioDecoder.getCodec(pFormatCtx);
    }
    if (!ok) return false;
    
    if (_hasVideo) {
        ok = ok && videoDecoder.allocateImage();
    }
    if (_hasAudio) {
        ok = ok && audioDecoder.allocateSound();
    }
    if (!ok) return false;

    if (_hasVideo) {
        m_w = videoDecoder.getWidth();
        m_h = videoDecoder.getHeight();
    }
    if (_hasAudio) {
        m_channels = audioDecoder.getChannels();
        m_rate = audioDecoder.getRate();
    }
    printf("  video size %dx%d, audio %dHz with %d channels\n", m_w, m_h,
           m_rate, m_channels);

    if (!(_hasVideo||_hasAudio)) {
        return false;
    }
    active = true;
    return true;
}
  
bool FfmpegGrabber::close() {
    if (!active) {
        return false;
    }
    
    // Close the video file
    if (pFormatCtx!=NULL) {
        av_close_input_file(pFormatCtx);
    }
    if (system_resource!=NULL) {
        delete &HELPER(system_resource);
        system_resource = NULL;
    }

    active = false;
    return true;
}
  
bool FfmpegGrabber::getImage(yarp::sig::ImageOf<yarp::sig::PixelRgb> & image) {
    if (!_hasVideo) {
        return false;
    }
    Sound sound;
    return getAudioVisual(image,sound);
}


bool FfmpegGrabber::getSound(yarp::sig::Sound& sound) {
    if (!_hasAudio) {
        return false;
    }
    ImageOf<PixelRgb> image;
    return getAudioVisual(image,sound);
}

  
bool FfmpegGrabber::getAudioVisual(yarp::sig::ImageOf<yarp::sig::PixelRgb>& image,
                                   yarp::sig::Sound& sound) {

    FfmpegHelper& helper = HELPER(system_resource);
    DecoderState& videoDecoder = helper.videoDecoder;
    DecoderState& audioDecoder = helper.audioDecoder;

    bool tryAgain = false;
    bool triedAgain = false;
    
    do {
    
        bool gotAudio = false;
        bool gotVideo = false;
        if (startTime<0.5) {
            startTime = Time::now();
        }
        double time_target = 0;
        while(av_read_frame(pFormatCtx, &packet)>=0) {
            // Is this a packet from the video stream?
            DBG printf("frame ");
            bool done = false;
            if (packet.stream_index==videoDecoder.getIndex()) {
                DBG printf("video ");
                done = videoDecoder.getVideo(packet);
                image.resize(1,1);
                if (done) {
                    //printf("got a video frame\n");
                    gotVideo = true;
                }
            } if (packet.stream_index==audioDecoder.getIndex()) {
                DBG printf("audio ");
                done = audioDecoder.getAudio(packet,sound);
                if (done) {
                    //printf("got an audio frame\n");
                    gotAudio = true;
                }
            } else {
                DBG printf("other ");
            }
            AVRational& time_base = pFormatCtx->streams[packet.stream_index]->time_base;
            double rbase = av_q2d(time_base);
            
            DBG printf(" time=%g ", packet.pts*rbase);
            time_target = packet.pts*rbase;
            
            av_free_packet(&packet);
            DBG printf(" %d\n", done);
            if ((videoDecoder.haveFrame()||!_hasVideo)&&
                (gotAudio||!_hasAudio)) {
                if (_hasVideo) {
                    videoDecoder.getVideo(image);
                } else {
                    image.resize(0,0);
                }
                if (needRateControl) {
                    double now = Time::now()-startTime;
                    double delay = time_target-now;
                    if (delay>0) {
                        DBG printf("DELAY %g ", delay);
                        Time::delay(delay);
                    } else {
                        DBG printf("NODELAY %g ", delay);
                    }
                }
                DBG printf("IMAGE size %dx%d  ", image.width(), image.height());
                DBG printf("SOUND size %d\n", sound.getSamples());
                if (!_hasAudio) {
                    sound.resize(0,0);
                }
                return true;
            }
        }

        tryAgain = !triedAgain;
   
        if (tryAgain) {
#if LIBAVFORMAT_BUILD > 4616
            av_seek_frame(pFormatCtx,-1,0,AVSEEK_FLAG_BACKWARD);
#else
            av_seek_frame(pFormatCtx,-1,0);
#endif
            startTime = Time::now();
        }
    } while (tryAgain);

    return false;
}


⌨️ 快捷键说明

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