环境: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 pituresuint32_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 yuvFILE *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 _WIN32DWORD start_time = timeGetTime();
#elsestruct timeval start, end;gettimeofday(&start, NULL);
#endif
#endifret = decodeOneFrame(pFrame);if (ret < 0){av_frame_free(&pFrame);av_frame_free(&m_pThumbFrame);return ret;}
#ifdef DEBUG_SPEND_TIME
#ifdef _WIN32DWORD end_time = timeGetTime();printf("decodeOneFrame spend time = %d ms\n", end_time - start_time);
#elsegettimeofday(&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
#endifret = getThumbnail(pFrame, m_pThumbFrame, width, height);if (ret < 0){av_frame_free(&pFrame);av_frame_free(&m_pThumbFrame);return ret;}// save the rgb565FILE *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);}//pauseprintf("finished, pause ....\n");getchar();return 0;
}

FFmpeg总结(八)windows下用ffmpeg获取视频缩略图相关推荐

  1. 【FFMPEG系列】windows下编译FFMPEG篇----之一(MingW)

    目录描述 序 1.环境准备 1.1 c99toc89安装 1.2 c99头文件inttypes.h和stdint.h安装 1.3 修改link文件 1.4 修改configure 2.编译 2.1 编 ...

  2. 【FFMPEG系列】windows下编译ffmpeg且加入libx264

    目录结构 1. 源码包下载 1.1. Ffmpeg 1.2. x264 2. 编译工具 2.1. mingw 2.2. yasm 2.3. nasm 2.4. pkg-config 3. mingw/ ...

  3. Linux下通过v4l2获取视频设备名、支持的编解码及视频size列表实现

    早些时候给出了在Windows下通过dshow获取视频设备信息的实现,包括获取视频设备名.获取每种视频设备支持的编解码格式列表.每种编解码格式支持的video size列表,见:https://blo ...

  4. 在Windows下编译FFmpeg详细说明

    在Windows下编译FFmpeg详细说明 MinGW:一个可自由使用和自由发布的Windows特定头文件和使用GNC工具集导入库的集合,允许你生成本地的Windows程序而不需要第三方C运行时 Mi ...

  5. 【FFMPEG系列】之windows下编译FFMPEG篇----之三(MingW64)

    目录结构 序 1 .安装mingw64 1.1 mingw64的安装 1.2 msys的安装 2.编译ffmpeg 2.1 编译 序 前文"windows下编译FFMPEG篇----之一(M ...

  6. WINDOWS 下编译 ffmpeg 源码总结

    WINDOWS 下编译 ffmpeg 源码,有两种方式:VC.GCC 1.VC 编译:   https://github.com/ShiftMediaProject/FFVS-Project-Gene ...

  7. windows下配置ffmpeg环境变量

    1.下载ffmpeg 官方下载链接,根据自己电脑系统选择32位或者64位下载. 2.下载后解压到D盘根目录 3.在桌面上右键点击"此电脑",左键点击"属性",在 ...

  8. android 获取视频缩略图终极解决方案(ffmpeg)

    android 获取视频缩略图终极解决方案(ffmpeg) 参考文章: (1)android 获取视频缩略图终极解决方案(ffmpeg) (2)https://www.cnblogs.com/juka ...

  9. Windows下C/C++获取当前系统时间

    Windows下CC获取当前系统时间 方案一localtime 优点仅使用C标准库缺点只能精确到秒级 方案二GetLocalTime sys   优点能精确到毫秒级缺点使用了windows API 方 ...

  10. Windows下用Python获取电脑显示器物理尺寸和PPI

    Windows下用Python获取电脑显示器物理尺寸和PPI 背景 PPI 和 DPI Python获取PPI 方法一(WMI) 方法二(WINREG) 方法三(WMI+WINREG) 总结 背景 最 ...

最新文章

  1. 采用TurboGate邮件网关防止企业邮箱被盗用
  2. cocos2dx 2.2.5 hitWidget-onTouchEnded(pTouch, pEvent); 异常
  3. linux下java写ftp服务器端,在Linux下部署网站(java环境部署)第五章 FTP服务器搭建...
  4. ie8下ewebeditor无效的解决办法
  5. linux怎么取消挂在u盘,linux下如何挂载U盘
  6. python access_Python3 os.access() 方法
  7. mysql实习报告总结_MySQL上机实习报告(一)
  8. c语言投票程序设计报告书,C语言程序设计报告书
  9. 基于OSSIM平台的信息系统安全风险评估实施指南
  10. 微信小程序开发:绑定手机号获取验证码功能
  11. 什么是前端总线,后端总线,内部总线、系统总线,外部总线,地址总线,数据总线,控制总线
  12. Unity 简单TCP通信实现
  13. 【工具】一键制作纯净ROM去除推广APP,支持线刷包卡刷包
  14. 特斯拉和拼多多,到底在「较真儿」什么?
  15. python斗地主出牌算法_斗地主之用蚁群算法整理牌型:如何进行牌力估计
  16. 样式的层级关系,选择器优先级,样式冲突,以及抽离样式模块怎么写,说出思路,有无实践经验
  17. 动态范围测试—imatest
  18. WWW 2022 | 量化交易相关论文(附论文链接)
  19. 3.Sunday算法的一个小优化
  20. 操作系统期末复习重点

热门文章

  1. Openlayer:学习笔记之View
  2. 2019最新论文阅读-BlazeFace:面向移动设备的实时人脸检测
  3. TensorFlow中数据的feed与fetch
  4. 深度学习中的 Attention 机制总结与代码实现(2017-2021年)
  5. (2)[wp7数据存储] WP7 IsolatedStorage系列篇——获取存储的文件或文件夹 [复制链接]...
  6. Sequence operation3397
  7. mapabc全国兴趣点、商户数据、poi数据,一共1490多万条,包含地址、电话、经纬度、类别...
  8. Lambda 表达式(C# 编程指南)
  9. 白盒测试之基本路径测试法[3]
  10. GARFIELD@10-21-2004