2014-03-19 10 views
0

파이프 또는 소켓에서 비디오를 디코딩 한 다음 이미지 세트를 변환하고 Qt (4.8.5 !!)로 그려야합니다. libAV의 기본 예제를 사용하여 필요한 항목을 추가하고 있습니다. 그것이 작동하지 않는 지금video from pipe-> YUV with libAV-> sws_scale-> Qt로 그리기

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); 

: 여기

내 코드입니다 "[swscaler @ 0xb0005460] 나쁜 DST 이미지 포인터"misstake하지만 질문은 다음과 같습니다 은 내가 globaly 잘못하고 있어요 어쩐 ?

- AVPicture가 필요합니까? here처럼?

-Is QImage - 프레임을 그릴 때 가장 좋은 방법은 무엇입니까?

- sws_scale()에 두 개의 다른 초기화 된 프레임을 제공하고 충돌이 발생합니다. 왜?

+0

조언대로 : avlog 출력을 어딘가에 유용하게 리디렉션하고 자세한 정보를 높게 설정하십시오. [여기] (http://blog.tomaka17.com/2012/03/libavcodeclibavformat-tutorial/#comment-72)를 읽어보십시오. – Jack

+0

"[swscaler @ 0398d060] 나쁜 dst 이미지 포인터"도 표시됩니다. 어떻게 해결할 수 있습니까? – Tariq

답변

1

내가 지금이 같은 것입니다 :

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을 다시 사용할 수 있습니다, 그냥 마지막에 삭제합니다.

+0

안녕하세요, 답변 해 주셔서 감사합니다. "image.copy();"를 사용 했습니까? "image = image.copy()"대신에? –

+0

아니요. image.copy()는 새 이미지를 반환하고 이미지를 수정하지 않으므로 일부 이미지를 저장해야합니다. – szatmary