您当前的位置: 首页 >  windows

暂无认证

  • 3浏览

    0关注

    95907博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

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

发布时间:2017-04-25 11:03:29 ,浏览量:3

环境: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  #endif #endif AVFormatContext* 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   0x30 int 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;
}
关注
打赏
1655516835
查看更多评论
立即登录/注册

微信扫码登录

0.2446s