FFmpeg总结(八)windows下用ffmpeg获取视频缩略图
来源:互联网 发布:java 版本 编辑:程序博客网 时间:2024/06/06 00:43
环境:VS 2015
运行程序,生成RGB图像数据:
将RGB图像数据转换成yuv格式,通过ffmpeg命令,如下:
验证画面完整性,需要用YUVplayer来打开yuv文件:如下:
完整代码:
#include "stdafx.h"extern "C"{#include "libavformat\avformat.h"#include "libswscale\swscale.h"}#define DEBUG_SPEND_TIME 1#ifdef DEBUG_SPEND_TIME#ifdef _WIN32#include "windows.h"#include "mmsystem.h"#pragma comment(lib, "winmm.lib")#else#include <sys/time.h>#endif#endifAVFormatContext* m_pFormatContext = NULL;AVCodecContext* m_pCodecContext = NULL;int m_nStreamIndex[AVMEDIA_TYPE_NB] = { -1 };AVCodec* m_pVideoCodec = NULL;AVFrame* m_pAVFrame = NULL;AVFrame* m_pThumbFrame = NULL;const char* strInputFileName[] = { "C:\\oppo.mp4",};const char strThumbFileName[] = "D:\\thumb.rgb";#define THUMB_WIDTH 640#define THUMB_HEIGHT 480#define BRIGHTNESS_VALUE 0xF0#define DARKNESS_VALUE 0x30int initFFmpegContext(){ avcodec_register_all(); av_register_all(); return 0;}int setDataSource(const char* url){ int ret = -1; if (m_pFormatContext) { avformat_free_context(m_pFormatContext); m_pFormatContext = NULL; } m_pFormatContext = avformat_alloc_context(); if (!m_pFormatContext) { return -1; } ret = avformat_open_input(&m_pFormatContext, url, NULL, NULL); if (ret != 0) { delete m_pFormatContext; return ret; } ret = avformat_find_stream_info(m_pFormatContext, NULL); if (ret != 0) { delete m_pFormatContext; return ret; } m_nStreamIndex[AVMEDIA_TYPE_VIDEO] = av_find_best_stream(m_pFormatContext, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0); m_nStreamIndex[AVMEDIA_TYPE_AUDIO] = av_find_best_stream(m_pFormatContext, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0); return ret;}int openDecoder(){ int ret = -1; m_pCodecContext = m_pFormatContext->streams[m_nStreamIndex[AVMEDIA_TYPE_VIDEO]]->codec; if (m_pCodecContext) { m_pVideoCodec = avcodec_find_decoder(m_pCodecContext->codec_id); ret = avcodec_open2(m_pCodecContext, m_pVideoCodec, NULL); if (ret != 0) { return ret; } avcodec_flush_buffers(m_pCodecContext); } return ret;}void closeDecoder(){ if (m_pVideoCodec) { avcodec_close(m_pCodecContext); m_pCodecContext = NULL; }}int decodeOneFrame(AVFrame* pFrame){ int ret = 0; bool frame_found = false; int decoded_frame_count = 0; AVPacket pkt; do { int got_frame = 0; ret = av_read_frame(m_pFormatContext, &pkt); if (ret < 0) { break; } if (pkt.flags != AV_PKT_FLAG_KEY) { av_free_packet(&pkt); continue; } if (pkt.stream_index == m_nStreamIndex[AVMEDIA_TYPE_VIDEO]) { ret = avcodec_decode_video2(m_pCodecContext, pFrame, &got_frame, &pkt); if (got_frame && ret >=0) { if (pFrame->width != m_pCodecContext->width || pFrame->height != m_pCodecContext->height) { m_pCodecContext->width = pFrame->width; m_pCodecContext->height = pFrame->height; decoded_frame_count++; av_free_packet(&pkt); continue; } decoded_frame_count++; //skip black and white pitures 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", decoded_frame_count, y_half, y_value); continue; } if (y_value < BRIGHTNESS_VALUE && y_value > DARKNESS_VALUE) { frame_found = true; printf("frame_found = true -----------------------decoded frame count = %d\n", decoded_frame_count); } }#ifdef SAVE_YUV_FRAME char szName[128]; sprintf(szName, "D:\\test_%d.yuv", frame_count); // save the yuv FILE *pFile = fopen(szName, "ab"); if (pFile) { fwrite(pFrame->data[0], 1, pFrame->width * pFrame->height, pFile); fwrite(pFrame->data[1], 1, pFrame->width * pFrame->height * 1 / 4, pFile); fwrite(pFrame->data[2], 1, pFrame->width * pFrame->height * 1 / 4, pFile); fclose(pFile); }#endif } av_free_packet(&pkt); } while ((!frame_found) && (ret >= 0)); av_free_packet(&pkt); return ret;}int getThumbnail(AVFrame* pInputFrame, AVFrame* pOutputFrame, int desW, int desH){ if (pInputFrame == NULL || pOutputFrame == NULL) { return -1; } SwsContext* pSwsContext = NULL; pSwsContext = sws_getCachedContext(pSwsContext, pInputFrame->width, pInputFrame->height, (AVPixelFormat)pInputFrame->format, desW, desH, AV_PIX_FMT_RGB565, SWS_BICUBIC, NULL, NULL, NULL); if (pSwsContext == NULL) { return -1; } m_pThumbFrame->width = desW; m_pThumbFrame->height = desH; m_pThumbFrame->format = AV_PIX_FMT_RGB565; av_frame_get_buffer(m_pThumbFrame, 16); sws_scale(pSwsContext, pInputFrame->data, pInputFrame->linesize, 0, pInputFrame->height, m_pThumbFrame->data, m_pThumbFrame->linesize); sws_freeContext(pSwsContext); return 0;}int getFrameAt(int64_t timeUs, int width, int height){ int ret = -1; AVFrame* pFrame = NULL; ret = avformat_seek_file(m_pFormatContext, -1, INT16_MIN, timeUs, INT16_MAX, 0); pFrame = av_frame_alloc(); m_pThumbFrame = av_frame_alloc(); ret = openDecoder(); if (ret != 0) { av_frame_free(&pFrame); av_frame_free(&m_pThumbFrame); return ret; }#ifdef DEBUG_SPEND_TIME#ifdef _WIN32 DWORD start_time = timeGetTime();#else struct timeval start, end; gettimeofday(&start, NULL);#endif#endif ret = decodeOneFrame(pFrame); if (ret < 0) { av_frame_free(&pFrame); av_frame_free(&m_pThumbFrame); return ret; }#ifdef DEBUG_SPEND_TIME#ifdef _WIN32 DWORD end_time = timeGetTime(); printf("decodeOneFrame spend time = %d ms\n", end_time - start_time);#else gettimeofday(&end, NULL); int spend_time = (end.tv_sec - start.tv_sec) * 1000 + (end.tv_usec - start.tv_usec) / 1000; printf("spend_time = %d ms\n", spend_time);#endif#endif ret = getThumbnail(pFrame, m_pThumbFrame, width, height); if (ret < 0) { av_frame_free(&pFrame); av_frame_free(&m_pThumbFrame); return ret; } // save the rgb565 FILE *pFile = fopen(strThumbFileName, "ab"); if (pFile) { fwrite(m_pThumbFrame->data[0], 1, m_pThumbFrame->width * m_pThumbFrame->height * 2, pFile); fclose(pFile); } av_frame_free(&pFrame); av_frame_free(&m_pThumbFrame); closeDecoder(); return ret;}int _tmain(int argc, _TCHAR* argv[]){ int ret = -1; initFFmpegContext(); int file_count = sizeof(strInputFileName) / sizeof(strInputFileName[0]); for (int i = 0; i < file_count; i++) { const char* pFileName = strInputFileName[i]; ret = setDataSource(pFileName); getFrameAt(-1, THUMB_WIDTH, THUMB_HEIGHT); } //pause printf("finished, pause ....\n"); getchar(); return 0;}
0 0
- FFmpeg总结(八)windows下用ffmpeg获取视频缩略图
- 在windows使用FFmpeg获取视频缩略图的工具类
- Windows下使用ffmpeg与java实现截取视频缩略图
- android 获取视频缩略图终极解决方案(ffmpeg)
- PHP之使用FFMPEG获取视频缩略图
- FFMPEG抽取视频缩略图
- windows环境下FFmpeg配置—— php生成视频缩略图,转换视频函数
- FFmpeg在Linux下的简单安装并与Java结合获取视频缩略图功能实现
- FFmpeg在Linux下的简单安装并与Java结合获取视频缩略图功能实现
- Java 生成视频缩略图(ffmpeg)
- PHP FFMPEG 生成视频缩略图
- FFmpeg获得视频的缩略图
- Java 生成视频缩略图(ffmpeg)
- Java 生成视频缩略图(ffmpeg)
- Java 生成视频缩略图(ffmpeg)
- FFmpeg获得视频的缩略图
- [FFmpeg] Windows下使用ffmpeg为视频添加字幕
- windows下用ffmpeg采集摄像头的视频
- Xcode运行工程报错-Reason: image not found
- 获取Android “/asset”目录数据
- 搭建yum私有仓库
- js_JavaScript中有六种值为“假”
- Linux命令行与shell脚本(9)--函数参数
- FFmpeg总结(八)windows下用ffmpeg获取视频缩略图
- Android实现类似execel的表格 能回显并能修改表格内容
- Fildder增加响应时间功能
- Autumn中文文档4:响应客户端结果
- 前端技术学习指南
- JetBrains全系列破解
- 地理空间距离计算优化-美团智能排序
- Java多线程同步问题探讨
- This license CNEKJPQZEX has been cancelled pycharm 注册码实效for mac