Discuz! Board

 找回密码
 
搜索
查看: 11442|回复: 62

提问:关于ios版本ffmpeg解码h264文件花屏问题

[复制链接]

1

主题

15

帖子

51

积分

Rank: 2

积分
51
发表于 2013-1-31 11:38:19 | 显示全部楼层 |阅读模式
我的程序是通过socket和服务起建立的连接,服务器每次下发一帧数据,我进行解码,并用生成image。整个过程还是顺利的,但是解出来的图片经常的花屏(不是所有的都花屏,有时候不花的多,有时候花的多),我想问一下,这个问题应该如何解决。请大家多多指教。
以下是我的代码:
-(void)initFFMPEG
{

    av_register_all();
    av_init_packet(&packet);
    pCodec=avcodec_find_decoder(CODEC_ID_H264);
    if(pCodec==NULL)
        goto initError; // Codec not found
   
    pCodecCtx =  avcodec_alloc_context3(pCodec);
    // Open codec
    if(avcodec_open2(pCodecCtx, pCodec,NULL) < 0)
        goto initError; // Could not open codec

   
    pFrame=avcodec_alloc_frame();

    NSLog(@"init success");
    return;
   
initError:
    //error action
    NSLog(@"init failed");
    return ;
}

-(void)releaseFFMPEG
{
    // Free scaler
    sws_freeContext(img_convert_ctx);
   
    // Free RGB picture
    avpicture_free(&picture);
   
    // Free the YUV frame
    av_free(pFrame);
   
    // Close the codec
    if (pCodecCtx) avcodec_close(pCodecCtx);
}

-(void)dealloc {
    // Free scaler
    sws_freeContext(img_convert_ctx);
   
    // Free RGB picture
    avpicture_free(&picture);
   
    // Free the packet that was allocated by av_read_frame
    av_free_packet(&packet);
   
    // Free the YUV frame
    av_free(pFrame);
   
    // Close the codec
    if (pCodecCtx) avcodec_close(pCodecCtx);
   
    [super dealloc];
}

-(void)setupScaler {
   
    // Release old picture and scaler
    avpicture_free(&picture);
    sws_freeContext(img_convert_ctx);
   
    // Allocate RGB picture
    avpicture_alloc(&picture, PIX_FMT_RGB24,pCodecCtx->width,pCodecCtx->height);
   
    // Setup scaler
    static int sws_flags =  SWS_FAST_BILINEAR;
    img_convert_ctx = sws_getContext(pCodecCtx->width,
                                     pCodecCtx->height,
                                     pCodecCtx->pix_fmt,
                                     pCodecCtx->width,
                                     pCodecCtx->height,
                                     PIX_FMT_RGB24,
                                     sws_flags, NULL, NULL, NULL);
   

   
   
}

-(void)convertFrameToRGB
{
    [self setupScaler];
    sws_scale (img_convert_ctx,pFrame->data, pFrame->linesize,
               0, pCodecCtx->height,
               picture.data, picture.linesize);
}


-(void)decodeAndShow : (char*) buf lengthint)len andTimeStampunsigned long)ulTime
{
    if (m_bPlayStop == YES)
    {
        return;
    }

    //0407 add for ffmpeg decode
    packet.size = len;
    packet.data = (unsigned char *)buf;
    int got_picture_ptr=0;
    int nImageSize;
    nImageSize = avcodec_decode_video2(pCodecCtx,pFrame,&got_picture_ptr,&packet);
    NSLog(@"nImageSize:%d--got_picture_ptr:%d",nImageSize,got_picture_ptr);
   
   
    if (nImageSize > 0 )
    {
        
        if (pFrame->data[0])
        {

            [self convertFrameToRGB];
            nWidth = pCodecCtx->width;
            nHeight = pCodecCtx->height;
            CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
            CFDataRef data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, picture.data[0], nWidth*nHeight*3,kCFAllocatorNull);
            CGDataProviderRef provider = CGDataProviderCreateWithCFData(data);
            CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
            
            CGImageRef cgImage = CGImageCreate(nWidth,
                                               nHeight,
                                               8,
                                               24,
                                               nWidth*3,
                                               colorSpace,
                                               bitmapInfo,
                                               provider,
                                               NULL,
                                               YES,
                                               kCGRenderingIntentDefault);
            CGColorSpaceRelease(colorSpace);
            //UIImage *image = [UIImage imageWithCGImage:cgImage];
            UIImage* image = [[UIImage alloc]initWithCGImage:cgImage];   //crespo modify 20111020
            CGImageRelease(cgImage);
            CGDataProviderRelease(provider);
            CFRelease(data);
           // [self timeIntervalControl:ulTime]; //add 0228
            [self performSelectorOnMainThreadselector(showImage withObject:image waitUntilDone:YES];
            [image release];
        }
    }
    m_decodeFinish = YES;
    return;
}

-(void)showImageUIImage *)img
{
    [self.delegate updateImage:img];
}


11.png
22.png
33.png
回复

使用道具 举报

1

主题

15

帖子

51

积分

Rank: 2

积分
51
 楼主| 发表于 2013-1-31 17:01:37 | 显示全部楼层
经反复实践得出,在高分辨率的情况下会花屏,低分辨率就不会,这为什么呢?
回复 支持 反对

使用道具 举报

676

主题

2229

帖子

3万

积分

吼山居士

Rank: 9Rank: 9Rank: 9

积分
34932
QQ
发表于 2013-2-4 13:31:47 | 显示全部楼层
花屏的原因事实上并不是跟分辨率的高低直接挂钩的,而是跟码率直接挂钩的,而导致花屏的直接原因是数据丢失(有可能是包丢失,也有可能是乱序未处理好从而导致丢失)。

若要改善花屏的现象,建议好好做一下这方面的功,如果时间紧的话,可以考虑先丢弃不完整的帧。
拒收论坛短消息,有问题请直接在论坛提问。

所有我的答复与微博同步,欢迎收听我的腾讯微博, 新浪微博,第一时间得到问题答复。

Item 1: Don't abuse your power        条款一:不要滥用权利
Item 2: Share expert knowledge        条款二:分享你的知识
Item 3: Respect other people's privacy        条款三:尊重他人的隐私
Item 4: Make yourself look good online        条款四:给自己网上留个好印象
Item 5: Help keep flame wars under control        条款五:平心静气地争论
Item 6: Respect other people's time and bandwidth        条款六:尊重别人的时间和带宽
回复 支持 反对

使用道具 举报

1

主题

15

帖子

51

积分

Rank: 2

积分
51
 楼主| 发表于 2013-2-17 10:03:46 | 显示全部楼层
jackyhwei 发表于 2013-2-4 13:31
花屏的原因事实上并不是跟分辨率的高低直接挂钩的,而是跟码率直接挂钩的,而导致花屏的直接原因是数据丢失 ...

谢谢您的回复,那您能告诉我以下“乱序未处理好”这个从什么地方找么,我有点没有头绪
回复 支持 反对

使用道具 举报

1

主题

15

帖子

51

积分

Rank: 2

积分
51
 楼主| 发表于 2013-2-17 12:30:03 | 显示全部楼层
一直报这个错误 No accelerated colorspace conversion found from yuv420p to rgb24.
回复 支持 反对

使用道具 举报

6

主题

36

帖子

190

积分

Rank: 2

积分
190
发表于 2013-2-17 12:44:31 | 显示全部楼层
本帖最后由 guo__qiu 于 2013-2-17 12:46 编辑
一直报这个错误 No accelerated colorspace conversion found from yuv420p to rgb24.

这个在arm的环境下遇到过,在pc下是不会有这个警告的,个人觉得不是这个问题,我在arm下转化图片时候是正常的(sws可能效率不高)。网上说这个问题能够通过安装x264的库解决。我自己没试过。建议lz检查一下帧率和帧大小及其完整性。
回复 支持 反对

使用道具 举报

1

主题

15

帖子

51

积分

Rank: 2

积分
51
 楼主| 发表于 2013-2-17 15:05:12 | 显示全部楼层
guo__qiu 发表于 2013-2-17 12:44
这个在arm的环境下遇到过,在pc下是不会有这个警告的,个人觉得不是这个问题,我在arm下转化图片时候是正 ...

能提供一下你arm下正常展示的代码吗?
回复 支持 反对

使用道具 举报

1

主题

15

帖子

51

积分

Rank: 2

积分
51
 楼主| 发表于 2013-2-19 16:07:40 | 显示全部楼层
我把
-(void)decodeAndShow : (char*) buf lengthint)len andTimeStampunsigned long)ulTime
{
    if (m_bPlayStop == YES)
    {
        return;
    }

    //0407 add for ffmpeg decode
    packet.size = len;
    packet.data = (unsigned char *)buf;
    int got_picture_ptr=0;
    int nImageSize;
    nImageSize = avcodec_decode_video2(pCodecCtx,pFrame,&got_picture_ptr,&packet);
    NSLog(@"nImageSize:%d--got_picture_ptr:%d",nImageSize,got_picture_ptr);
   
   
    if (nImageSize > 0 )
    {
        
        if (pFrame->data[0])
        {

          sleep(1);//这里就是延时一秒,解析一桢。舍弃了一秒钟内的其他所有侦,花屏的情况就基本没有了,但问题依旧存在的是,这样视频就不是连贯的,跳着走了。
            [self convertFrameToRGB];
            nWidth = pCodecCtx->width;
            nHeight = pCodecCtx->height;
            CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
            CFDataRef data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, picture.data[0], nWidth*nHeight*3,kCFAllocatorNull);
            CGDataProviderRef provider = CGDataProviderCreateWithCFData(data);
            CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
            
            CGImageRef cgImage = CGImageCreate(nWidth,
                                               nHeight,
                                               8,
                                               24,
                                               nWidth*3,
                                               colorSpace,
                                               bitmapInfo,
                                               provider,
                                               NULL,
                                               YES,
                                               kCGRenderingIntentDefault);
            CGColorSpaceRelease(colorSpace);
            //UIImage *image = [UIImage imageWithCGImage:cgImage];
            UIImage* image = [[UIImage alloc]initWithCGImage:cgImage];   //crespo modify 20111020
            CGImageRelease(cgImage);
            CGDataProviderRelease(provider);
            CFRelease(data);
           // [self timeIntervalControl:ulTime]; //add 0228
            [self performSelectorOnMainThreadselector(showImage withObject:image waitUntilDone:YES];
            [image release];
        }
    }
    m_decodeFinish = YES;
    return;
}
回复 支持 反对

使用道具 举报

1

主题

15

帖子

51

积分

Rank: 2

积分
51
 楼主| 发表于 2013-2-19 18:05:17 | 显示全部楼层
真机的时候还是不行,还是花屏,而且会有整个图片都是灰色的效果
回复 支持 反对

使用道具 举报

6

主题

36

帖子

190

积分

Rank: 2

积分
190
发表于 2013-2-21 23:45:08 | 显示全部楼层
本帖最后由 guo__qiu 于 2013-2-21 23:46 编辑

我在linux下用的jpeg的库转化的在qt下显示,看LZ的代码  
nImageSize = avcodec_decode_video2(pCodecCtx,pFrame,&got_picture_ptr,&packet);
这里解码完成后,可以用:
        img_convert_ctx2 = sws_getContext(         avCodecCtx->width, avCodecCtx->height,
                                            PIX_FMT_YUV420P,
                                            avCodecCtx->width,
                                            avCodecCtx->height,
                                            PIX_FMT_RGB24,
                                            SWS_FAST_BILINEAR, NULL, NULL, NULL);
将数据转化成rgb24的(我的视频数据在编码的时候是用的420p)。然后就可以了。你下边的代码我就看不明白了。呵呵
回复 支持 反对

使用道具 举报

高级模式
B Color Image Link Quote Code Smilies

本版积分规则

Archiver||С|Comsenz Inc.  

GMT+8, 2018-10-17 12:11 , Processed in 0.025684 second(s), 26 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表