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
原创粉丝点击