来自管道的视频->;YUV带libAV->;带有sws_刻度的RGB->;用Qt绘图

来自管道的视频->;YUV带libAV->;带有sws_刻度的RGB->;用Qt绘图,qt,rgb,yuv,libav,Qt,Rgb,Yuv,Libav,我需要从管道或插座解码视频,然后将其转换为一组图像,并用Qt(4.8.5!!)绘制。 我正在使用libAV的默认示例,并添加了我需要的内容 这是我的密码: AVCodec *codec; AVCodecContext *codecContext= NULL; int frameNumber, got_picture, len; FILE *f; AVFrame *avFrame, *avFrameYUV, *avFrameRGB; uint8_t

我需要从管道或插座解码视频,然后将其转换为一组图像,并用Qt(4.8.5!!)绘制。 我正在使用libAV的默认示例,并添加了我需要的内容

这是我的密码:

    AVCodec *codec;
    AVCodecContext *codecContext= NULL;
    int frameNumber, got_picture, len;
    FILE *f;
    AVFrame *avFrame, *avFrameYUV, *avFrameRGB;
    uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
    AVPacket avpkt;

    av_init_packet(&avpkt);

    f = fopen("/tmp/test.mpg", "rb");
     if (!f) {
         fprintf(stderr, "could not open /tmp/test.mpg\n");
         exit(1);
     }

     /* set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) */
     memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE);

     /* decode until eof */
     avpkt.data = inbuf;
     avpkt.size = fread(inbuf, 1, INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE, f);

    /* find the mpeg1 video decoder */
    codec = avcodec_find_decoder(AV_CODEC_ID_MPEG1VIDEO);
    if (!codec) {
        fprintf(stderr, "codec not found\n");
        exit(1);
    }

    codecContext = avcodec_alloc_context3(codec);
    codecContext->get_format = &my_get_format;
    avFrameYUV = avcodec_alloc_frame();
    avFrameRGB = avcodec_alloc_frame();

    if(codec->capabilities&CODEC_CAP_TRUNCATED)
        codecContext->flags|= CODEC_FLAG_TRUNCATED; /* we do not send complete frames */

    /* For some codecs, such as msmpeg4 and mpeg4, width and height
       MUST be initialized there because this information is not
       available in the bitstream. */

    /* open it */
    if (avcodec_open2(codecContext, codec, NULL) < 0) {
        fprintf(stderr, "could not open codec\n");
        exit(1);
    }

    /* the codec gives us the frame size, in samples */

    int srcX = 352;  //Size of output picture in example
    int srcY = 288;
    struct SwsContext *swsContext = sws_getContext(srcX, srcY, AV_PIX_FMT_YUV420P,
                                                srcX, srcY, PIX_FMT_RGB32, SWS_BICUBIC, NULL, NULL, NULL);
    frameNumber = 0;
    for(;;) {
        if (avpkt.size == 0)
            break;
        avpkt.data = inbuf;
        while (avpkt.size > 0) {
            len = avcodec_decode_video2(codecContext, avFrameYUV, &got_picture, &avpkt);
            if (len < 0) {
                fprintf(stderr, "Error while decoding frame %d\n", frameNumber);
                exit(1);
            }
            if (got_picture) {
                printf("saving frame %3d\n", frameNumber);
                fflush(stdout);

                sws_scale(swsContext, avFrameYUV->data, avFrameYUV->linesize, 0, dstY, avFrameRGB->data, avFrameRGB->linesize);

                myImage = new QImage(avFrameRGB->data[0], srcX, srcY, QImage::Format_RGB32);

                emit update(myImage); // Here i draw it to the screen
                usleep(50000);
                frameNumber++;
            }
            avpkt.size -= len;
            avpkt.data += len;
        }
    }

    avpkt.data = NULL;
    avpkt.size = 0;
    len = avcodec_decode_video2(codecContext, avFrameYUV, &got_picture, &avpkt);
    if (got_picture) {
        printf("saving last frame %3d\n", frameNumber);
        fflush(stdout);
        frameNumber++;
    }

    avcodec_close(codecContext);
    av_free(codecContext);
    avcodec_free_frame(&avFrameRGB);
    avcodec_free_frame(&avFrameYUV);
AVCodec*编解码器;
AVCodecContext*codecContext=NULL;
int frameNumber,获得图片,len;
文件*f;
AVFrame*AVFrame,*avFrameYUV,*avFrameRGB;
uint8_t inbuf[inbuf_SIZE+FF_INPUT_BUFFER_PADDING_SIZE];
avpkt;
av_init_数据包(&avpkt);
f=fopen(“/tmp/test.mpg”,“rb”);
如果(!f){
fprintf(stderr,“无法打开/tmp/test.mpg\n”);
出口(1);
}
/*将缓冲区结束设置为0(这可确保损坏的mpeg流不会发生过读)*/
memset(inbuf+inbuf_大小,0,FF_输入_缓冲区_填充_大小);
/*解码到eof*/
avpkt.data=inbuf;
avpkt.size=fread(inbuf,1,inbuf_size+FF_输入_缓冲区_填充_大小,f);
/*查找mpeg1视频解码器*/
codec=avcodec\u find\u解码器(AV\u codec\u ID\u mpeg1视频);
如果(!编解码器){
fprintf(stderr,“找不到编解码器”);
出口(1);
}
codecContext=avcodec\u alloc\u context3(编解码器);
codecContext->get\u format=&my\u get\u format;
avFrameYUV=avcodec_alloc_frame();
avFrameRGB=avcodec_alloc_frame();
if(编解码器->功能和编解码器\u CAP\u截断)
编解码器上下文->标志|=编解码器标志被截断;/*我们不发送完整的帧*/
/*对于某些编解码器,如msmpeg4和mpeg4,宽度和高度
必须在那里初始化,因为此信息不可用
在比特流中可用*/
/*打开它*/
if(avcodec_open2(codecContext,codec,NULL)<0){
fprintf(stderr,“无法打开编解码器”\n);
出口(1);
}
/*编解码器以示例的形式给出了帧大小*/
int srcX=352//示例中输出图片的大小
int srcY=288;
结构SwsContext*SwsContext=sws_getContext(srcX,srcY,AV_PIX_FMT_YUV420P,
srcX,srcY,PIX_FMT_RGB32,SWS_双三次,NULL,NULL,NULL);
frameNumber=0;
对于(;;){
如果(avpkt.size==0)
打破
avpkt.data=inbuf;
而(avpkt.size>0){
len=avcodec\u decode\u video2(codecContext、avFrameYUV、got\u picture和avpkt);
if(len<0){
fprintf(stderr,“解码帧%d时出错”,帧号);
出口(1);
}
如果(得到图片){
printf(“保存帧%3d\n”,帧编号);
fflush(stdout);
sws_比例(swsContext,avFrameYUV->data,avFrameYUV->linesize,0,dstY,avFrameRGB->data,avFrameRGB->linesize);
myImage=newqimage(avFrameRGB->data[0],srcX,srcY,QImage::Format_RGB32);
emit update(myImage);//这里我把它画到屏幕上
美国LEEP(50000);
frameNumber++;
}
avpkt.size-=len;
avpkt.data+=len;
}
}
avpkt.data=NULL;
avpkt.size=0;
len=avcodec\u decode\u video2(codecContext、avFrameYUV、got\u picture和avpkt);
如果(得到图片){
printf(“保存最后一帧%3d\n”,帧号);
fflush(stdout);
frameNumber++;
}
avcodec_close(编解码器上下文);
av_免费(编解码器上下文);
avcodec_free_帧(&avFrameRGB);
avcodec_free_帧(&avFrameYUV);
现在它不起作用了:“[swscaler@0xb0005460]错误的dst图像指针”错误,但问题是: -我到底做错了什么

-我需要一张照片吗?比如说

-QImage是画框最好的材料吗


-我给sws_scale()两个不同的初始化帧,它崩溃了。为什么?

我想这样说:

AVPicture m_Rgb;
int srcX = codecContext->width;
int srcY = codecContext->height;
struct SwsContext *swsContext = sws_getContext(srcX, srcY, codecContext->pix_fmt, srcX, srcY, PIX_FMT_RGB32, SWS_BICUBIC, NULL, NULL, NULL);
m_Rgb.linesize[0] = srcX * 4;
m_Rgb.data[0]     = (uint8_t*)malloc( m_Rgb.linesize[0] * srcY );
sws_scale(swsContext, avFrameYUV->data, avFrameYUV->linesize, 0, srcY, m_Rgb.data, m_Rgb.linesize );

QImage image( m_Rgb.data[0], srcX, srcY, QImage::Format_RGB32 );
image = image.copy(); // This makes a deep copy of the pixels. Currently image just has a copy of the m_Rgb.data[0] pointer

您可以反复使用m_Rgb,并在最后删除它。

嘿,谢谢您的回答。你的意思是“image.copy();”而不是“image=image.copy()”?否。image.copy()返回一个新图像,它不会在适当的位置修改图像,因此必须将其存储在某个位置。建议:将avlog输出重定向到有用的位置,并将详细度设置为高。阅读更多。我还收到了“[swscaler@0398d060]错误的dst图像指针”。我如何解决它?