ffmpeg解码ps流部分代码以及demo

之前的设备研发算是告一段落了,最近一直在忙视频监控平台的架构以及实现,想把自己的设备接到自己的平台里,设备上的码流是ps流,要在平台里解码ps流->解码成h264->yuv->rgb最终显示。貌似现在用的最多的解码就是开源的ffmpeg,我也尝试着去研究ffmpeg,当然也只在网上搜搜资料看看如何调用这些,但好像都是些先探测流信息,然后再找解码器那些,但我并不想探测流,因为我已经知道流的格式了(这样也能节省探测时间),经过这段时间的不懈努力,终于搞出来了,现贴出部分代码以及demo

void PSDecode::startup()
{
    av_register_all();
}

bool PSDecode::open()
{
    m_pCodec = avcodec_find_decoder(CODEC_ID_H264);
    if (!m_pCodec)
    {
        return false;
    }

    m_pContext = avcodec_alloc_context3(m_pCodec);
    if (avcodec_open(m_pContext, m_pCodec) < 0)
    {
        av_free(m_pContext);
        m_pContext = NULL;
        m_pCodec = NULL;
    }

    m_pFrame = avcodec_alloc_frame();

    m_pPicture = new AVPicture();
    memset(m_pPicture, 0, sizeof(AVPicture));

    return true;
}

void PSDecode::close()
{
    if (!m_pContext)
    {
        return;
    }

    av_free(m_pFrame);
    m_pFrame = NULL;

    avpicture_free(m_pPicture);
    delete m_pPicture;
    m_pPicture = NULL;

    closeScaleContext();

    avcodec_close(m_pContext);

    av_free(m_pContext);
    m_pContext = NULL;

    m_pCodec = NULL;

}

bool PSDecode::inputData(const unsigned char* buffer, size_t length)
{
    AVPacket packet;
    av_init_packet(&packet);

    packet.data = (unsigned char*)buffer;
    packet.size = length;

    int got_picture = 0;
    int ret = avcodec_decode_video2(m_pContext, m_pFrame, &got_picture, &packet);
    if (got_picture)
    {
        updateResolution();

        drawFrame();

        m_frameCount ++;
    }
    return (ret >= 0);
}

bool PSDecode::snap(const char* filename)
{
    FILE* pFile = fopen(filename, "wb");
    if (!pFile)
    {
        return false;
    }

    int width = m_pContext->width;
    int height = m_pContext->height;
    
    AVPicture picture;
    memset(&picture, 0, sizeof(picture));
    avpicture_alloc(&picture, PIX_FMT_RGB32, width, height);

    SwsContext* pScaleContext = sws_getContext(width, height,
        m_pContext->pix_fmt,
        width, height, PIX_FMT_RGB32, SWS_BILINEAR, 0, 0, 0);

    sws_scale(pScaleContext, m_pFrame->data, m_pFrame->linesize, 0, height,
        picture.data, picture.linesize);

    sws_freeContext(pScaleContext);

    BITMAPINFO bmpInfo;
    memset(&bmpInfo, 0, sizeof(bmpInfo));
    bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmpInfo.bmiHeader.biWidth = width;
    bmpInfo.bmiHeader.biHeight = - height;
    bmpInfo.bmiHeader.biCompression = BI_RGB;
    bmpInfo.bmiHeader.biBitCount = 32;
    //bmpInfo.bmiHeader.biSizeImage = bmpInfo.bmiHeader.biWidth * bmpInfo.bmiHeader.biHeight * bmpInfo.bmiHeader.biBitCount /8;
    bmpInfo.bmiHeader.biPlanes = 1;
    bmpInfo.bmiHeader.biXPelsPerMeter = 0;
    bmpInfo.bmiHeader.biYPelsPerMeter = 0;
    bmpInfo.bmiHeader.biClrImportant = 0;
    bmpInfo.bmiHeader.biClrUsed = 0;

    int nColors = 0;
    BITMAPFILEHEADER hdr;
    hdr.bfType = ((WORD) ('M'<<8) |'B'); //is always "RM"
    hdr.bfSize = bmpInfo.bmiHeader.biSize + bmpInfo.bmiHeader.biSizeImage + sizeof(hdr);
    hdr.bfReserved1 = 0;		
    hdr.bfReserved2 = 0;
    hdr.bfOffBits=(DWORD) (sizeof(hdr) + bmpInfo.bmiHeader.biSize + nColors * sizeof(RGBQUAD));
    
    fwrite(&hdr,sizeof(hdr), 1, pFile);

    bmpInfo.bmiHeader.biHeight = bmpInfo.bmiHeader.biHeight>0?bmpInfo.bmiHeader.biHeight:-bmpInfo.bmiHeader.biHeight;
    fwrite(&bmpInfo.bmiHeader, bmpInfo.bmiHeader.biSize, 1, pFile);

    int nBytesPerLine = bmpInfo.bmiHeader.biBitCount/8*bmpInfo.bmiHeader.biWidth;
    char *pOffset = (char*)picture.data[0] + (bmpInfo.bmiHeader.biHeight-1)*nBytesPerLine;
    for (int i=0; i<bmpInfo.bmiHeader.biHeight; i++) 
    {
        fwrite(pOffset, nBytesPerLine, 1, pFile);
        pOffset -= nBytesPerLine;
    }

    fclose(pFile);

    avpicture_free(&picture);

    return true;
}

下载地址:https://download.csdn.net/download/u010868213/11847014

发布了12 篇原创文章 · 获赞 17 · 访问量 4445

猜你喜欢

转载自blog.csdn.net/u010868213/article/details/102484175