加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

ffmpeg读取内存rgb数据初始化流程

(2012-09-17 17:23:27)
标签:

ffmpeg

压缩传输

流媒体

it

分类: ffmpeg
//1.function


void COsgVideo::init()
{
     av_register_all();                                            //注册编辑码器;
     if ( NULL == m_pOutputFormat)                                //初始化输出流;
         m_pOutputFormat = av_guess_format("AVI", NULL, NULL);
     m_pFormatCtx = avformat_alloc_context();                 //为AVFormatContext分配空间及初始化;
     if (!m_pFormatCtx)
     {
         wprintf(L"不能使用的输出文件扩展: 使用 MPEG 格式代替;\n");
         return;
     }
     m_pFormatCtx->oformat = m_pOutputFormat;
     if (m_pOutputFormat->video_codec != CODEC_ID_NONE)
     {
         m_pVideoStream = addVideoStream(m_pFormatCtx, m_pOutputFormat->video_codec, m_width, m_height);
       
     if (m_pVideoStream)  // 现在所有的参数设置完毕, 我们可以打开视频编解码器,初始化必要的缓冲区;
     {
         openVideo(m_pFormatCtx, m_pVideoStream);
     }
     m_yuvFrame->pts = 0;
}

//2.function



AVStream* COsgVideo::addVideoStream(AVFormatContext *pFormatCtx, CodecID codec_id, int width, int height)
{
    AVStream* stream = avformat_new_stream(pFormatCtx, NULL);
    if (!stream)
    {
        wprintf(L"初始化视频流失败;\n");
        return NULL;
    }
    AVCodecContext* pCodecCtx = stream->codec;
    AVCodec* pCodec = avcodec_find_encoder(codec_id);    // 寻找视频编解码器 ;
    if (!pCodec)
    {
        wprintf(L"未能找到视频编解码器;\n");
        return NULL;
    }
    avcodec_get_context_defaults3(pCodecCtx, pCodec);

    pCodecCtx->codec_id = codec_id;
    pCodecCtx->bit_rate = 400000;                        // 设置样本参数比特率;
    pCodecCtx->width = width;                            // 设置分辨率;
    pCodecCtx->height = height;
    pCodecCtx->time_base.den = m_frameRate;                //帧率;
    pCodecCtx->time_base.num = 1;
    pCodecCtx->gop_size = 12;                            //每发送12帧有一个关键帧;
    pCodecCtx->pix_fmt = m_pixFmt;
   
    if (pFormatCtx->oformat->flags & AVFMT_GLOBALHEADER)// 一些格式需要视频流的头被分开;
        pCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;

    return stream;
}

//3.function


bool COsgVideo::openVideo(AVFormatContext *pFormatCtx, AVStream *stream)
{
    AVCodecContext* pCodecCtx = stream->codec;
    AVCodec* pCodec = avcodec_find_encoder(pCodecCtx->codec_id);    // 寻找编解码器;
    if (!pCodec)
    {
        wprintf(L"未能找到编解码器;\n");
        return false;
     
    if (avcodec_open(pCodecCtx, pCodec) < 0)                        //打开编码器;
    {
        wprintf(L"打开编解码器失败;\n");
        return false;
    }
    if (!(pFormatCtx->oformat->flags & AVFMT_RAWPICTURE))
    {
        m_videoOutbufSize = LineWidthBytes(WIDTH,24)*HEIGHT*3;
        m_videoOutbuf = (uint8_t *)av_malloc(m_videoOutbufSize);
    }
    // 初始化编码帧,分配内存空间;
    m_rgbFrame = allocFrame(PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);
    m_yuvFrame = allocFrame(m_pixFmt, pCodecCtx->width, pCodecCtx->height);
    if (!m_yuvFrame)
    {
        wprintf(L"初始化编码帧失败;\n");
        return false;
    }
    return true;
}

//4.function


AVFrame* COsgVideo::allocFrame(PixelFormat pix_fmt, int width, int height)
{
    AVFrame *picture;
    picture = avcodec_alloc_frame();
    if (!picture)
        return NULL;
    int size = avpicture_get_size(pix_fmt, width, height);
    uint8_t *picture_buf = (uint8_t *)av_malloc(size);
    if (!picture_buf)
    {
        av_free(picture);
        return NULL;
    }
    avpicture_fill((AVPicture *)picture, picture_buf, pix_fmt, width, height);
    return picture;
}

//5.run函数调用来发送数据。

void COsgVideo::run()
{
    while(1)
    {
        transformRGB2YUV(m_data,m_width,m_height,24,m_yuvFrame);
        //2.YUV 生成AVPacket;
        AVPacket pkt;
        av_init_packet(&pkt);
        packYUVData2AVPacket(m_pVideoStream,m_yuvFrame,&pkt);
        //3.AVPacket打包发送;
        sendAVPacketData(&pkt);
        av_free_packet(&pkt);
        m_yuvFrame->pts++;
        Sleep(50);
    }
}

//6.function

void COsgVideo::transformRGB2YUV(unsigned char *rgbSrcData, int srcWidth, int srcHeight, int pixelBits,AVFrame *yuvDstPic)
{
    static int index = 0;
    OpenThreads::ScopedLock mutex(m_mutex);
    if(!rgbSrcData)
        return;
    int linesize = srcWidth * 3;
    for (int i = srcHeight; i > 0; i--)
    {
        memcpy(&m_rgbFrame->data[0][(srcHeight - i)*linesize], &(rgbSrcData[(i-1)*linesize]), linesize);
    }
    SwsContext * scxt = sws_getContext(srcWidth,srcHeight,PIX_FMT_RGB24,srcWidth,srcHeight,m_pixFmt,SWS_POINT,NULL,NULL,NULL);
    sws_scale(scxt,m_rgbFrame->data,m_rgbFrame->linesize,0,srcHeight,yuvDstPic->data,yuvDstPic->linesize);
}

//7.function


void COsgVideo::packYUVData2AVPacket(AVStream *pStream, AVFrame *yuvSrcData, AVPacket *dstPacket)
{
    AVCodecContext *pCodecCtx = pStream->codec;
    if(pCodecCtx == NULL)
        return;
    int got_packt;           
    dstPacket->data = (unsigned char*)m_videoOutbuf;
    dstPacket->size = m_videoOutbufSize;
    int out_size = avcodec_encode_video2(pCodecCtx, dstPacket, yuvSrcData, &got_packt);//got_pack = 1  if the output packet is non-empty, and got_pack = 0 if it is empty;
    if (out_size >= 0)
    {
        if (pCodecCtx->coded_frame->pts != AV_NOPTS_VALUE)
            dstPacket->pts= av_rescale_q(pCodecCtx->coded_frame->pts, pCodecCtx->time_base, pStream->time_base);
        if(pCodecCtx->coded_frame->key_frame)
            dstPacket->flags |= AV_PKT_FLAG_KEY;
        dstPacket->stream_index = pStream->index;
    }
}

//8.function



void COsgVideo::sendAVPacketData(AVPacket *pPacket)
{
    //接收到客户端,识别client地址;
    sockaddr_in remoteAddr;
    int nAddrLen = sizeof(sockaddr);
    char buf[20] = {0};
    //m_connected = false;
    recvfrom(sListen,buf,21,0,(sockaddr*)&remoteAddr,&nAddrLen);
    m_connected = true;

    //分包发送;
    Video_Packet my_packet;
    int packetNum = 0;
    if (pPacket->size % VIDEO_SIZE == 0)
    {
        packetNum = pPacket->size/VIDEO_SIZE;
        my_packet.int_flag = 1;
    }
    else
    {
        packetNum = pPacket->size/VIDEO_SIZE + 1;
        my_packet.int_flag = 0;
    }
    my_packet.packet_cnt = packetNum;
    my_packet.Frame_seq = m_frameCount;
    my_packet.video_total_size = pPacket->size;
    for (int i = 0; i < my_packet.packet_cnt; i++)
    {
        if (i+1 == my_packet.packet_cnt)
        {
            if (my_packet.int_flag == 0)
            {
                my_packet.video_size = my_packet.video_total_size%VIDEO_SIZE;
            }
            else
            {
                my_packet.video_size = VIDEO_SIZE;
            }
            my_packet.more_flag = 0;
        }
        else
        {
            my_packet.video_size = VIDEO_SIZE;
            my_packet.more_flag = 1;
        }
        my_packet.packet_idx = i + 1;
        memcpy(my_packet.data, pPacket->data + (my_packet.packet_idx - 1)*VIDEO_SIZE, my_packet.video_size);

        sendto(sListen,(const char*)&my_packet, sizeof(Video_Packet), 0,(sockaddr*)&remoteAddr,nAddrLen);
    }
}

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有