Wons' Blog

个人博客

Android程序猿


回首向来萧瑟处,也无风雨也无晴

ffmpeg解码视频流并转YUV为RGB

FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec里很多codec都是从头开发的。

以下代码在Qt环境下用ffmpeg解码视频流并将YUV转换为RGB格式。

int MapThread::decode_write_frame(AVCodecContext *avctx, AVFrame *frame, AVPacket *pkt)
{
    int len, got_frame;
    len = avcodec_decode_video2(avctx, frame, &got_frame, pkt);

    if (got_frame)
    {

        if(image == 0)
            image = new QImage(img_buf, avctx->width, avctx->height, QImage::Format_RGB888);

        received_frame_width = avctx->width;
        received_frame_height = avctx->height;

        for(int h = 0; h < avctx->height; h++)
        {
            for(int w = 0; w < avctx->width; w ++)
            {
                int hh = h >> 1;
                int ww = w >> 1;
                int Y = frame->data[0][h * frame->linesize[0] + w];
                int U = frame->data[1][hh * (frame->linesize[1]) + ww];
                int V = frame->data[2][hh * (frame->linesize[2]) + ww];

                int C = Y - 16;
                int D = U - 128;
                int E = V - 128;

                int r = 298 * C           + 409 * E + 128;
                int g = 298 * C - 100 * D - 208 * E + 128;
                int b = 298 * C + 516 * D           + 128;

                r = qBound(0, r >> 8, 255);
                g = qBound(0, g >> 8, 255);
                b = qBound(0, b >> 8, 255);

                QRgb rgb = qRgb(r, g, b);
                image->setPixel(QPoint(w, h), rgb);
            }
        }
        emit frameGot(image);
    }
    if (pkt->data) {
        pkt->size -= len;
        pkt->data += len;
    }

    return 0;
}

void MapThread::newData()
{
    if(!inited)
    {
        avcodec_register_all();

        pkt = new AVPacket;
        av_init_packet(pkt);

        memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE);

        codec = avcodec_find_decoder(AV_CODEC_ID_MPEG1VIDEO);
        if (!codec)
        {
            exit(1);
        }
        c = avcodec_alloc_context3(codec);

        if (!c) {
            exit(1);
        }

        av_opt_set(c->priv_data, "preset", "superfast", 0);
        av_opt_set(c->priv_data, "tune", "zerolatency", 0);

        c->delay = 0;

        if(codec->capabilities&CODEC_CAP_TRUNCATED)
            c->flags|= CODEC_FLAG_TRUNCATED;
        if (avcodec_open2(c, codec, NULL) < 0) {
            exit(1);
        }

        frame = av_frame_alloc();
        if (!frame) {
            exit(1);
        }

        inited = true;
    }
    while(true)
    {
        int nread = mapSocket->read((char*)inbuf, INBUF_SIZE);

        if(nread <= 0)
            break;

        av_init_packet(pkt);
        pkt->size = nread;
        pkt->data = inbuf;
        while (pkt->size > 0)
        {
            if (decode_write_frame(c, frame, pkt) < 0)
                exit(1);
        }
        av_free_packet(pkt);
    }
}
最近的文章

YV12转RGB

YUV,是一种颜色编码方法,是编译true-color颜色空间(color space)的种类,Y’UV, YUV, YCbCr,YPbPr等专有名词都可以称为YUV,彼此有重叠。“Y”表示明亮度(Luminance、Luma),“U”和“V”则是色度、浓度(Chrominance、Chroma),Y’UV, YUV, YCbCr, YPbPr常常有些混用的情况,其中YUV和Y’UV通常用来描述模拟信号,而相反的YCbCr与YPbPr则是用来描述数位的影像信号,例如在一些压缩格式内MPEG...…

YUVopencv继续阅读
更早的文章

关于我

Android程序猿教育 东华大学, 本科, 计算机 复旦大学, 硕士, 计算机技术 Android ★★★★☆ Java ★★★★☆ Python ★★★☆☆ C++ ★★★☆☆ Shell ★★★☆☆就业经历 百度 爱奇艺社区 GitHub liuwons的GitHub CSDN liuwons的CSDN博客…

me继续阅读