zoukankan      html  css  js  c++  java
  • 实战小项目之基于嵌入式的图像采集压缩保存

    项目简介

      这是之前图像采集显示程序的升级版,首先基础部分的图像v4l2采集、framebuffer显示、IPU转码都进行了c++封装,之后加入了以下新功能:

    1. SDL1.2显示
    2. FFmpeg编码保存版本一(顺序执行)
    3. FFmpeg编码保存版本二(线程方式)  
    4. c++ pthread库简单封装

      这个小工程是一个附属产品,boss的项目中用到了图像编码保存,然后学了一段时间的多媒体技术(主要就是FFmpeg),后来就衍生出了这个版本的程序

      不多说,上代码

      首先是SDL显示部分

    /*
     * SDLDisp.cpp
     *
     *  Created on: Oct 11, 2016
     *      Author: tla001
     */
    
    #include "SDLDisp.h"
    /*
     * display different data
     * 1.framesize                 420p:screen_w*screen_h*3/2    422:screen_w*screen_h*2
     * 2.SDL_CreateYUVOverlay     420p:SDL_IYUV_OVERLAY        422:SDL_YUY2_OVERLAY
     * 3.dispfuction            420p:DisplayYUV420P            422:DisplayYUV422
     */
    
    SDLDisp::SDLDisp(int screen_w,int screen_h) {
        // TODO Auto-generated constructor stub
        this->screen_w=screen_w;
        this->screen_h=screen_h;
        this->framesize=screen_w*screen_h*3/2;
        this->buffer=NULL;
        this->sdl_running=1;
        this->thread_exit=0;
    }
    
    SDLDisp::~SDLDisp() {
        // TODO Auto-generated destructor stub
        this->sdl_running=0;
        closeSDL();
    }
    int SDLDisp::initSDL(char *winName)
    {
        buffer=(uint8_t*)malloc(sizeof(uint8_t)*framesize);
        SDL_Init(SDL_INIT_EVERYTHING);
        screen = SDL_SetVideoMode(screen_w, screen_h, 0, SDL_SWSURFACE|SDL_ANYFORMAT);
        if(!screen) {
            printf("SDL: could not set video mode - exiting:%s
    ",SDL_GetError());
            return -1;
        }
        /* Set the window name */
         SDL_WM_SetCaption(winName, NULL);
         //yuv420P    run with DisplayYUV420P
        // overlay = SDL_CreateYUVOverlay(screen_w, screen_h,SDL_IYUV_OVERLAY, screen);
         //yuv422 run with DisplayYUV422
         overlay = SDL_CreateYUVOverlay(screen_w, screen_h,SDL_IYUV_OVERLAY, screen);
    
        rect.x=0;
        rect.y = 0;
        rect.w = screen_w;
        rect.h = screen_h;
        //refresh_thread = SDL_CreateThread(sdlcontol,NULL);
        //pthread_create(&controlTid,NULL,sdlcontol, static_cast<void*>(this));
        //初始化读写所
    //    int ret=pthread_rwlock_init(&rwlock, NULL);
    //    if(ret<0){
    //        printf("init wrlock failed
    ");
    //        return -1;
    //    }
        //pthread_create(&dispTid,NULL,&sdlDisp,NULL);
    
        return 0;
    }
    int SDLDisp::closeSDL()
    {
        if(buffer!=NULL)
            free(buffer);
        thread_exit=1;
        SDL_FreeYUVOverlay(overlay);
        SDL_FreeSurface(screen);
        SDL_Quit();
        printf("sdl end
    ");
        return 0;
    }
    int SDLDisp::sdlDisp()
    {
        printf("sdl disp start
    ");
        while(sdl_running){
            SDL_WaitEvent(&event);
            if(event.type==REFRESH_EVENT){
                SDL_LockSurface(screen);
                pthread_rwlock_rdlock(&rwlock);
                DisplayYUV420P(buffer, screen_w, screen_h, overlay);
                pthread_rwlock_unlock(&rwlock);
                SDL_UnlockSurface(screen);
                SDL_DisplayYUVOverlay(overlay, &rect);
                //Update Screen
                SDL_Flip(screen);
            }else if(event.type==SDL_QUIT){
                thread_exit=1;
                sdl_running=0;
            }else if(event.type==BREAK_EVENT){
                break;
            }
        }
        thread_exit=1;
        printf("sdl disp end
    ");
        return 0;
    }
    int SDLDisp::refresh_video(void *opaque){
        thread_exit=0;
        while (thread_exit==0) {
            SDL_Event event;
            event.type = REFRESH_EVENT;
            SDL_PushEvent(&event);
            SDL_Delay(40);
        }
        thread_exit=0;
        //Break
        SDL_Event event;
        event.type = BREAK_EVENT;
        SDL_PushEvent(&event);
        return 0;
    }
    int SDLDisp::doSDLDisp(uint8_t *buf)
    {
        pthread_rwlock_wrlock(&rwlock);
        memcpy(buffer,buf,framesize);
        pthread_rwlock_unlock(&rwlock);
        return 0;
    }
    void SDLDisp::normalSDLDisp(uint8_t *buf)
    {
        memcpy(buffer,buf,framesize);
        SDL_LockSurface(screen);
        DisplayYUV420P(buffer, screen_w, screen_h, overlay);//420p
        //DisplayYUV422(buffer, screen_w, screen_h, overlay);//422
        SDL_UnlockSurface(screen);
        SDL_DisplayYUVOverlay(overlay, &rect);
        //Update Screen
        SDL_Flip(screen);
    }
    void SDLDisp::DisplayYUV420P(uint8_t *buf, uint32_t w, uint32_t h, SDL_Overlay *overlay)
    {
        /* Fill in video data */
        //uint32_t yuv_size = (w*h) * 3/2;
        uint8_t * y_video_data = (uint8_t*)buf;
        uint8_t * u_video_data = (uint8_t*)(buf + w * h);
        uint8_t * v_video_data = (uint8_t*)(u_video_data + (w * h / 4));
    
        /* Fill in pixel data - the pitches array contains the length of a line in each plane */
        SDL_LockYUVOverlay(overlay);
        memcpy(overlay->pixels[0], y_video_data, w * h);
        memcpy(overlay->pixels[1], u_video_data, w * h / 4);
        memcpy(overlay->pixels[2], v_video_data, w * h / 4);
    
        SDL_UnlockYUVOverlay(overlay);
    }
    void SDLDisp::DisplayYUV420(uint8_t *buf, uint32_t w, uint32_t h, SDL_Overlay *overlay)
    {
        /* Fill in video data */
        //uint32_t yuv_size = (w*h) * 3/2;
        uint8_t * y_video_data = (uint8_t*)buf;
        uint8_t * v_video_data = (uint8_t*)(buf + w * h);
        uint8_t * u_video_data = (uint8_t*)(v_video_data + (w * h / 4));
    
        /* Fill in pixel data - the pitches array contains the length of a line in each plane */
        SDL_LockYUVOverlay(overlay);
        memcpy(overlay->pixels[0], y_video_data, w * h);
        memcpy(overlay->pixels[1], u_video_data, w * h / 4);
        memcpy(overlay->pixels[2], v_video_data, w * h / 4);
    
        SDL_UnlockYUVOverlay(overlay);
    }
    void SDLDisp::DisplayYUV422(uint8_t *buf, uint32_t w, uint32_t h, SDL_Overlay *overlay)
    {
        /* Fill in pixel data - the pitches array contains the length of a line in each plane */
        SDL_LockYUVOverlay(overlay);
        memcpy(overlay->pixels[0], buf, w * h*2);
        SDL_UnlockYUVOverlay(overlay);
    }
    View Code

      然后是encodesaver1 

    /*
     * EncodeSaver.cpp
     *
     *  Created on: Oct 11, 2016
     *      Author: tla001
     */
    
    #include "EncodeSaver.h"
    
    EncodeSaver::EncodeSaver(int in_w,int in_h,int out_w,int out_h,char* out_file) {
        // TODO Auto-generated constructor stub
        this->in_w=in_w;
        this->in_h=in_h;
        this->out_w=out_w;
        this->out_h=out_h;
        this->framesize=0;
        this->out_file=out_file;
        this->basicsize=in_w*in_h;
        this->frameNum=0;
    }
    
    EncodeSaver::~EncodeSaver() {
        // TODO Auto-generated destructor stub
    }
    int EncodeSaver::initDevice()
    {
        av_register_all();
        //方法1.组合使用几个函数
        pFormatCtx = avformat_alloc_context();
        //猜格式
        fmt = av_guess_format(NULL, out_file, NULL);
        pFormatCtx->oformat = fmt;
        if (avio_open(&pFormatCtx->pb,out_file, AVIO_FLAG_READ_WRITE) < 0)
        {
            printf("输出文件打开失败");
            return -1;
        }
    
        video_st = av_new_stream(pFormatCtx, 0);
        if (video_st==NULL)
        {
            return -1;
        }
        pCodecCtx = video_st->codec;
        pCodecCtx->codec_id = fmt->video_codec;
        pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
        pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
        pCodecCtx->width = in_w;
        pCodecCtx->height = in_h;
        pCodecCtx->time_base.num = 1;
        pCodecCtx->time_base.den = 18;
        pCodecCtx->bit_rate = 400000;
        pCodecCtx->gop_size=250;
        //设置
        video_st->time_base.num=1;
        video_st->time_base.den=18;
        //H264
        pCodecCtx->me_range = 16;
        pCodecCtx->max_qdiff = 4;
        pCodecCtx->qmin = 10;
        pCodecCtx->qmax = 51;
        pCodecCtx->qcompress = 0.6;
        if (pCodecCtx->codec_id == CODEC_ID_MPEG2VIDEO)
        {
            pCodecCtx->max_b_frames = 2;
        }
        if (pCodecCtx->codec_id == CODEC_ID_MPEG1VIDEO)
        {
            pCodecCtx->mb_decision = 2;
        }
        if (!strcmp(pFormatCtx->oformat->name, "mp4") || !strcmp(pFormatCtx->oformat->name, "mov") || !strcmp(pFormatCtx->oformat->name, "3gp"))
        {
            pCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
        }
        //输出格式信息
        av_dump_format(pFormatCtx, 0, out_file, 1);
    
        pCodec = avcodec_find_encoder(pCodecCtx->codec_id);
        if (!pCodec)
        {
            printf("没有找到合适的编码器!
    ");
            return -1;
        }
        if (avcodec_open2(pCodecCtx, pCodec,NULL) < 0)
        {
            printf("编码器打开失败!
    ");
            return -1;
        }
        //输出420
    
        picture = avcodec_alloc_frame();
        framesize = avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
        picture_buf = (uint8_t *)av_malloc(framesize);
        avpicture_fill((AVPicture *)picture, picture_buf, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
        //输入422
        picture422 = avcodec_alloc_frame();
        framesize422 = avpicture_get_size(PIX_FMT_YUYV422, pCodecCtx->width, pCodecCtx->height);
        picture422_buf = (uint8_t *)av_malloc(framesize422);
        avpicture_fill((AVPicture *)picture422, picture422_buf, PIX_FMT_YUYV422, pCodecCtx->width, pCodecCtx->height);
        img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUYV422, pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
        //写文件头
        avformat_write_header(pFormatCtx,NULL);
        av_new_packet(&pkt,basicsize*3);
    }
    
    int EncodeSaver::closeDevice()
    {
        int ret = flush_encoder(pFormatCtx,0);
        if (ret < 0) {
            printf("Flushing encoder failed
    ");
            return -1;
        }
        //写文件尾
        av_write_trailer(pFormatCtx);
    
        //清理
        if (video_st)
        {
            avcodec_close(video_st->codec);
            av_free(picture);
            av_free(picture_buf);
            av_free(picture422);
            av_free(picture422_buf);
        }
        avio_close(pFormatCtx->pb);
        avformat_free_context(pFormatCtx);
        return 0;
    }
    int EncodeSaver::doEncode(unsigned char *buf)
    {
        int ret;
        //420P
        memcpy(picture_buf,buf,basicsize*3/2);
        picture->data[0] = picture_buf;  // 亮度Y
        picture->data[1] = picture_buf+ basicsize;  // U
        picture->data[2] = picture_buf+ basicsize*5/4; // V
    
    
        //PTS
        if (pFormatCtx->oformat->flags & AVFMT_RAWPICTURE)
        {
            AVPacket pkt;
            av_init_packet(&pkt);
            pkt.flags |= AV_PKT_FLAG_KEY;
            pkt.stream_index = video_st->index;
            pkt.data = (uint8_t*)picture;
            pkt.size = sizeof(AVPicture);
            ret = av_write_frame(pFormatCtx, &pkt);
        }
        else{
            int out_size = avcodec_encode_video(pCodecCtx, picture_buf, framesize, picture);
            if (out_size > 0)
            {
                AVPacket pkt;
                av_init_packet(&pkt);
                pkt.pts = av_rescale_q(pCodecCtx->coded_frame->pts, pCodecCtx->time_base, video_st->time_base);
                if (pCodecCtx->coded_frame->key_frame)
                {
                    pkt.flags |= AV_PKT_FLAG_KEY;
                    printf("here 1
    ");
                }
                pkt.stream_index = video_st->index;
                pkt.data = picture_buf;
                pkt.size = out_size;
                ret = av_write_frame(pFormatCtx, &pkt);
            }
        }
        return 0;
    }
    int EncodeSaver::doEncode2(unsigned char *buf)
    {
        int ret;
        //422
        memcpy(picture422_buf,buf,basicsize*2);
        picture422->data[0] = picture422_buf;
        sws_scale(img_convert_ctx, picture422->data, picture422->linesize, 0, pCodecCtx->height, picture->data, picture->linesize);
    
    
        //PTS
        if (pFormatCtx->oformat->flags & AVFMT_RAWPICTURE)
        {
            AVPacket pkt;
            av_init_packet(&pkt);
            pkt.flags |= AV_PKT_FLAG_KEY;
            pkt.stream_index = video_st->index;
            pkt.data = (uint8_t*)picture;
            pkt.size = sizeof(AVPicture);
            ret = av_write_frame(pFormatCtx, &pkt);
        }
        else{
            int out_size = avcodec_encode_video(pCodecCtx, picture_buf, framesize, picture);
            if (out_size > 0)
            {
                AVPacket pkt;
                av_init_packet(&pkt);
                pkt.pts = av_rescale_q(pCodecCtx->coded_frame->pts, pCodecCtx->time_base, video_st->time_base);
                if (pCodecCtx->coded_frame->key_frame)
                {
                    pkt.flags |= AV_PKT_FLAG_KEY;
                }
                pkt.stream_index = video_st->index;
                pkt.data = picture_buf;
                pkt.size = out_size;
                ret = av_write_frame(pFormatCtx, &pkt);
            }
        }
    
        return ret;
    }
    int EncodeSaver::flush_encoder(AVFormatContext *fmt_ctx,unsigned int stream_index)
    {
        int ret;
        int got_frame;
        AVPacket enc_pkt;
        if (!(fmt_ctx->streams[stream_index]->codec->codec->capabilities &
            CODEC_CAP_DELAY))
            return 0;
        while (1) {
            printf("Flushing stream #%u encoder
    ", stream_index);
            //ret = encode_write_frame(NULL, stream_index, &got_frame);
            enc_pkt.data = NULL;
            enc_pkt.size = 0;
            av_init_packet(&enc_pkt);
            ret = avcodec_encode_video2 (fmt_ctx->streams[stream_index]->codec, &enc_pkt,
                NULL, &got_frame);
            av_frame_free(NULL);
            if (ret < 0)
                break;
            if (!got_frame)
            {ret=0;break;}
            printf("successed frame!
    ");
            /* mux encoded frame */
            ret = av_write_frame(fmt_ctx, &enc_pkt);
            if (ret < 0)
                break;
        }
        return ret;
    }
    View Code

      接着是encodesaver2

    /*
     * EncodeSaver2.cpp
     *
     *  Created on: Oct 12, 2016
     *      Author: tla001
     */
    
    #include "EncodeSaver2.h"
    
    EncodeSaver2::EncodeSaver2(int in_w,int in_h,int out_w,int out_h,char* out_file) {
        // TODO Auto-generated constructor stub
        this->in_w=in_w;
        this->in_h=in_h;
        this->out_w=out_w;
        this->out_h=out_h;
        this->framesize=0;
        this->out_file=out_file;
        this->basicsize=in_w*in_h;
        this->frameNum=0;
        this->ready=0;
    }
    
    
    EncodeSaver2::~EncodeSaver2() {
        // TODO Auto-generated destructor stub
        closeDevice();
    }
    
    int EncodeSaver2::initDevice()
    {
        av_register_all();
        //方法1.组合使用几个函数
        pFormatCtx = avformat_alloc_context();
        //猜格式
        fmt = av_guess_format(NULL, out_file, NULL);
        pFormatCtx->oformat = fmt;
        if (avio_open(&pFormatCtx->pb,out_file, AVIO_FLAG_READ_WRITE) < 0)
        {
            printf("输出文件打开失败");
            return -1;
        }
    
        video_st = av_new_stream(pFormatCtx, 0);
        if (video_st==NULL)
        {
            return -1;
        }
        pCodecCtx = video_st->codec;
        pCodecCtx->codec_id = fmt->video_codec;
        pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
        pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
        pCodecCtx->width = in_w;
        pCodecCtx->height = in_h;
        pCodecCtx->time_base.num = 1;
        pCodecCtx->time_base.den = 25;
        pCodecCtx->bit_rate = 400000;
        pCodecCtx->gop_size=250;
        //设置
        video_st->time_base.num=1;
        video_st->time_base.den=25;
        //H264
        pCodecCtx->me_range = 16;
        pCodecCtx->max_qdiff = 4;
        pCodecCtx->qmin = 10;
        pCodecCtx->qmax = 51;
        pCodecCtx->qcompress = 0.6;
        if (pCodecCtx->codec_id == CODEC_ID_MPEG2VIDEO)
        {
            pCodecCtx->max_b_frames = 2;
        }
        if (pCodecCtx->codec_id == CODEC_ID_MPEG1VIDEO)
        {
            pCodecCtx->mb_decision = 2;
        }
        if (!strcmp(pFormatCtx->oformat->name, "mp4") || !strcmp(pFormatCtx->oformat->name, "mov") || !strcmp(pFormatCtx->oformat->name, "3gp"))
        {
            pCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
        }
        //输出格式信息
        av_dump_format(pFormatCtx, 0, out_file, 1);
    
        pCodec = avcodec_find_encoder(pCodecCtx->codec_id);
        if (!pCodec)
        {
            printf("没有找到合适的编码器!
    ");
            return -1;
        }
        if (avcodec_open2(pCodecCtx, pCodec,NULL) < 0)
        {
            printf("编码器打开失败!
    ");
            return -1;
        }
        //输出420
    
        picture = avcodec_alloc_frame();
        framesize = avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
        picture_buf = (uint8_t *)av_malloc(framesize);
        avpicture_fill((AVPicture *)picture, picture_buf, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
        //输入422
        picture422 = avcodec_alloc_frame();
        framesize422 = avpicture_get_size(PIX_FMT_YUYV422, pCodecCtx->width, pCodecCtx->height);
        picture422_buf = (uint8_t *)av_malloc(framesize422);
        avpicture_fill((AVPicture *)picture422, picture422_buf, PIX_FMT_YUYV422, pCodecCtx->width, pCodecCtx->height);
        img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUYV422, pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
        //写文件头
        avformat_write_header(pFormatCtx,NULL);
        av_new_packet(&pkt,basicsize*3);
    
        this->start();
        cout<<"thread start"<<endl;
    }
    int EncodeSaver2::closeDevice()
    {
        this->stop();
        int ret = flush_encoder(pFormatCtx,0);
        if (ret < 0) {
            printf("Flushing encoder failed
    ");
            return -1;
        }
    
        //写文件尾
        av_write_trailer(pFormatCtx);
    
        //清理
        if (video_st)
        {
            avcodec_close(video_st->codec);
            av_free(picture);
            av_free(picture_buf);
            av_free(picture422);
            av_free(picture422_buf);
        }
        avio_close(pFormatCtx->pb);
        avformat_free_context(pFormatCtx);
        return 0;
    }
    int EncodeSaver2::doEncode(unsigned char *buf)
    {
        int ret=0;
        //422
        memcpy(picture422_buft.a,buf,basicsize*2);
        //picture422_bufs.push(picture422_buft);
        this->ready=1;
        return ret;
    }
    int EncodeSaver2::isReady(){
        return ready;
    }
    void EncodeSaver2::run(){
        int ret;
        struct timeval temp;
        temp.tv_sec = 0;
        temp.tv_usec = 40000000;//40ms
        printf("thread is up!
    ");
        while(1){
        if(isStop())
            pthread_exit(0);
        if(isStart()&&isReady()){
    //        printf("here 1
    ");
    //        sleep(1);
    
            //select(0, NULL, NULL, NULL, &temp);
            //usleep(40000000);
            printf("**********time up********ttkf*** 
    ");
        //    if(picture422_bufs.empty()){
        //        cout<<" queue empty"<<endl;
        //        continue;
        //    }
    
            //picture422_buf=picture422_bufs.front().a;
            //picture422_bufs.pop();
            memcpy(picture422_buf,picture422_buft.a,basicsize*2);
            picture422->data[0] = picture422_buf;
            sws_scale(img_convert_ctx, picture422->data, picture422->linesize, 0, pCodecCtx->height, picture->data, picture->linesize);
                //PTS
            if (pFormatCtx->oformat->flags & AVFMT_RAWPICTURE)
            {
                AVPacket pkt;
                av_init_packet(&pkt);
                pkt.flags |= AV_PKT_FLAG_KEY;
                pkt.stream_index = video_st->index;
                pkt.data = (uint8_t*)picture;
                pkt.size = sizeof(AVPicture);
                ret = av_write_frame(pFormatCtx, &pkt);
            }
            else{
                int out_size = avcodec_encode_video(pCodecCtx, picture_buf, framesize, picture);
                if (out_size > 0)
                {
                    AVPacket pkt;
                    av_init_packet(&pkt);
                    pkt.pts = av_rescale_q(pCodecCtx->coded_frame->pts, pCodecCtx->time_base, video_st->time_base);
                    if (pCodecCtx->coded_frame->key_frame)
                    {
                        pkt.flags |= AV_PKT_FLAG_KEY;
                    }
                    pkt.stream_index = video_st->index;
                    pkt.data = picture_buf;
                    pkt.size = out_size;
                    ret = av_write_frame(pFormatCtx, &pkt);
                }
            }
        }else{
            printf("ready for data
    ");
            usleep(50000);//线程起来之后,由于参数没准备好,可能会空转
        }
    }
    }
    int EncodeSaver2::flush_encoder(AVFormatContext *fmt_ctx,unsigned int stream_index)
    {
        int ret;
        int got_frame;
        AVPacket enc_pkt;
        if (!(fmt_ctx->streams[stream_index]->codec->codec->capabilities &
            CODEC_CAP_DELAY))
            return 0;
        while (1) {
            printf("Flushing stream #%u encoder
    ", stream_index);
            //ret = encode_write_frame(NULL, stream_index, &got_frame);
            enc_pkt.data = NULL;
            enc_pkt.size = 0;
            av_init_packet(&enc_pkt);
            ret = avcodec_encode_video2 (fmt_ctx->streams[stream_index]->codec, &enc_pkt,
                NULL, &got_frame);
            av_frame_free(NULL);
            if (ret < 0)
                break;
            if (!got_frame)
            {ret=0;break;}
            printf("successed frame!
    ");
            /* mux encoded frame */
            ret = av_write_frame(fmt_ctx, &enc_pkt);
            if (ret < 0)
                break;
        }
        return ret;
    }
    View Code

    完整工程

    https://github.com/tla001/CapTransV2


    相关链接  

    ffmpeg移植

      http://www.cnblogs.com/tla001/p/5906220.html

    音视频处理(FFmpeg)基础

      http://blog.csdn.net/leixiaohua1020/article/details/15811977

      学习的资料,基本都是从雷神的博客中来的

    相关命令

    ffmpeg -f video4linux2 -i /dev/video0 -vcodec libx264 -s 320*240 -r 10 video0.mkv
    ffmpeg -f video4linux2 -s 640*480 -r 25 -i /dev/video0 test.avi
  • 相关阅读:
    网页图表Highcharts实践教程之外层图表区
    网页图表Highcharts实践教程之图表代码构成
    网页图表Highcharts实践教程之认识Highcharts
    Playmaker全面实践教程之Playmaker常用工具
    Playmaker全面实践教程之简单的使用Playmaker示例
    Playmaker全面实践教程之playMaker编辑器
    Playmaker Input篇教程之引入的核心概念
    Playmaker Input篇教程之PlayMaker菜单概述
    Playmaker Input篇教程之Playmaker购买下载和导入
    关于中值滤波算法,以及C语言实现(转)
  • 原文地址:https://www.cnblogs.com/tla001/p/6322926.html
Copyright © 2011-2022 走看看