doorxp-blog

doorxp.com

ffmpeg 获得视频截屏

#import <libavformat/avformat.h>

#import <libswscale/swscale.h>


#define BRIGHTNESS_VALUE 0xF0

#define DARKNESS_VALUE   0x30


+ (UIImage *)thumbnailForVideo:(NSString *)path {

    

    

    UIImage *image = nil;

    

    AVFormatContext *pFormatCtx = NULL;

    AVCodec *pCodec = NULL;

    AVCodecContext *pCodecCtx = NULL;

    

    AVFrame *pFrame = NULL;

    AVFrame *pOutFrame = NULL;

    

    struct SwsContext *pSwsCtx = NULL;

    

    const int whs = 200;

    

    int videoStream = -1;

    

    do {

        

        pFormatCtx = avformat_alloc_context();

        

        if (!pFormatCtx) {

            break;

        }

        

        if (avformat_open_input(&pFormatCtx, path.UTF8String, NULL, NULL) < 0) {

            break;

        }

        

        if (avformat_find_stream_info(pFormatCtx, NULL)<0) {

            break;

        }

        

        videoStream = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, &pCodec, 0);

        

        if (videoStream < 0) {

            break;

        }

        

        if (avformat_seek_file(pFormatCtx, videoStream, INT16_MIN, 0, INT16_MAX, 0) < 0) {

            break;

        }

        

        AVStream *stream = pFormatCtx->streams[videoStream];

        

        enum AVCodecID codecId = stream->codecpar->codec_id;

        

        pCodec = avcodec_find_decoder(codecId);

        

        if (!pCodec) {

            break;

        }

        

        pCodecCtx = avcodec_alloc_context3(pCodec);

        

        if (!pCodecCtx) {

            break;

        }

        

        avcodec_parameters_to_context(pCodecCtx, stream->codecpar);

        av_codec_set_pkt_timebase(pCodecCtx, stream->time_base);


        if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {

            break;

        }

        

        avcodec_flush_buffers(pCodecCtx);

        

        

        

        bool frameFound = false;

        int ret = 0;

        int decodedFrameCount = 0;

        AVPacket pkt;

        

        pFrame = av_frame_alloc();

        

        do {

            ret = av_read_frame(pFormatCtx, &pkt);

            if (ret<0) {

                break;

            }

            

            if (pkt.stream_index == videoStream) {

                if(avcodec_send_packet(pCodecCtx, &pkt) < 0) {

                    break;

                }

                if(avcodec_receive_frame(pCodecCtx, pFrame)<0) {

                    break;

                }

                

                decodedFrameCount ++;

                

                uint32_t y_value = 0;

                uint32_t y_half = 0;

                uint32_t y_count = 0;

                int pixel_count = pFrame->width * pFrame->height;

                bool bHalf = false;

                for (int i = 0; i < pixel_count; i+=3)

                {

                    uint8_t y_temp = (uint8_t)(*(uint8_t*)((uint8_t*)(pFrame->data[0]) + i));

                    y_value += y_temp;

                    y_count++;

                    

                    

                    if (!bHalf && i > pixel_count / 6)

                    {

                        y_half = y_value / y_count;

                        bHalf = true;

                    }

                }

                

                

                y_value /= y_count;

                if (y_half == y_value)

                {

                    printf("decoded frame count = %d y_half=%d == y_value=%d, skip this frame!\n", decodedFrameCount, y_half, y_value);

                    continue;

                }

                if (y_value < BRIGHTNESS_VALUE && y_value > DARKNESS_VALUE)

                {

                    frameFound = true;

                    printf("frameFound = true -----------------------decoded frame count = %d\n", decodedFrameCount);

                }

            }

            

            av_packet_unref(&pkt);

            

        }while (!frameFound && ret>=0);

        

        if (!frameFound) {

            break;

        }

        

        int x = 0;

        int y = 0;

        

        int s = pFrame->width;

        if (s>pFrame->height) {

            s = pFrame->height;

        }

        

        x = (pFrame->width-s)/2;

        y = (pFrame->height-s)/2;

        

        av_picture_crop((AVPicture *)pFrame,

                        (AVPicture *)pFrame,

                        pFrame->format,

                        y, x);

        

        pFrame->width = s;

        pFrame->height = s;

        

        pSwsCtx =

        sws_getCachedContext(pSwsCtx,

                             pFrame->width, pFrame->height, pCodecCtx->pix_fmt,

                             whs, whs, AV_PIX_FMT_RGB24,

                             SWS_FAST_BILINEAR,

                             NULL,

                             NULL,

                             NULL);

        

        if (!pSwsCtx) {

            break;

        }

        

        pOutFrame = av_frame_alloc();

        

        if (!pOutFrame) {

            break;

        }

        

        pOutFrame->format = AV_PIX_FMT_RGB24;

        pOutFrame->width = whs;

        pOutFrame->height = whs;

        

        if(av_frame_get_buffer(pOutFrame, 16) < 0) {

            break;

        }

        

        if(sws_scale(pSwsCtx,

                     (const uint8_t *const *)pFrame->data,

                     pFrame->linesize,

                     0,

                     pFrame->height,

                     pOutFrame->data,

                     pOutFrame->linesize) < 0) {

            break;

        }

        

    }while (0);

    

    if (pCodecCtx) {

        avcodec_close(pCodecCtx);

        pCodecCtx = NULL;

    }

    

    

    if (pSwsCtx) {

        sws_freeContext(pSwsCtx);

        pSwsCtx = NULL;

    }

    

    if (pFrame) {

        av_frame_free(&pFrame);

        pFrame = NULL;

    }

    

    if (pFormatCtx) {

        avformat_close_input(&pFormatCtx);

        pFormatCtx = NULL;

    }

    

    

    if(!!pOutFrame) {

        

        CGBitmapInfo binfo = kCGBitmapByteOrderDefault;

        

        const CFDataRef data =

        CFDataCreate(kCFAllocatorDefault,

                     pOutFrame->data[0],

                     pOutFrame->linesize[0]

                     * pOutFrame->height);

        

        CGDataProviderRef provider = CGDataProviderCreateWithCFData(data);

        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

        CGImageRef cgImage = CGImageCreate(whs,

                                           whs,

                                           8,

                                           24,

                                           pOutFrame->linesize[0],

                                           colorSpace,

                                           binfo,

                                           provider,

                                           NULL,

                                           NO,

                                           kCGRenderingIntentDefault);

        

        image = [UIImage imageWithCGImage:cgImage];

        

        CGImageRelease(cgImage);

        CGDataProviderRelease(provider);

        CGColorSpaceRelease(colorSpace);

        

        CFRelease(data);

    }


    if (pOutFrame) {

        av_frame_free(&pOutFrame);

        pOutFrame = NULL;

    }


   

    if (image == nil) {

        image = [UIImage imageNamed:@"default_music_cover"];

    }

    

    return image;

    

}


发表评论:

Powered By Z-BlogPHP 1.5.1 Zero

Copyright doorxp.com Rights Reserved.