#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;
}