ffmpeg解碼ps流部分代碼以及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;
}

下載地址(僅是個demo,不含源碼):https://download.csdn.net/download/u010868213/11847014

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章