首页 > 程序开发 > 移动开发 > 其他 > 正文
使用VideoToolBox硬解码MJPEG编码格式视频
2017-05-19 09:59:00       个评论    来源:weili905906480123的博客  
收藏    我要投稿

Motion JPEG(MJPEG,Motion Joint Photographic Experts Group,FourCC:MJPG)是一种视频压缩格式,其中每一帧图像都分别使用JPEG编码。一般我们使用看到的使用VideoToolBox处理的都是H.264压缩格式的视频,这里我介绍一个使用VideoToolBox解码MJPEG视频编码格式的视频的方法,我们同样使用ffmpeg读取一个MJPEG编码格式的网络视频流。

1.同样的我们需要先创建 VTDecompressionSessionRef

 //根据视频信息创建视频解码的session
    if (videoFormatDescr == NULL){
        // 获取视频的宽高
        int videoWidth = pCodecCtx->width;
        int videoHeight = pCodecCtx->height;
        //创建视频描叙信息,包括视频的宽,高和编码信息,这里我们使用MJPEG对应的编码类型kCMVideoCodecType_JPEG
        CMVideoFormatDescriptionCreate(kCFAllocatorDefault, kCMVideoCodecType_JPEG, videoWidth, videoHeight, NULL, &videoFormatDescr);
        //创建解码回调函数
        VTDecompressionOutputCallbackRecord callback;
        callback.decompressionOutputCallback = didDecompress;
        callback.decompressionOutputRefCon = (bridge void )self;
        //定义解码得到的图片像素格式
        NSDictionary destinationImageBufferAttributes =[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO],(id)kCVPixelBufferOpenGLESCompatibilityKey,[NSNumber numberWithInt:kCVPixelFormatType_32BGRA],(id)kCVPixelBufferPixelFormatTypeKey,nil];
        //创建session
        status = VTDecompressionSessionCreate(kCFAllocatorDefault, videoFormatDescr, NULL, (bridge CFDictionaryRef)destinationImageBufferAttributes, &callback, &session);
        if (status != noErr){
            NSLog(@"Init decoder session failed status= %d", (int)status);
        }
    }

2.开始解码

    //创建BlockBuffer,这里的数据我们直接使用AVPacket中的数据去填充
    CMBlockBufferRef videoBlock = NULL;
    status = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault, packet.data, packet.size, kCFAllocatorNull, NULL, 0, packet.size, 0, &videoBlock);
    if (status != noErr){
        NSLog(@"CMBlockBufferRef failed status=%d", (int)status);
    }
    //创建sampleBuffer
    CMSampleBufferRef sampleBuffer = NULL;
    const size_t sampleSizeArray[] = {packet.size};
    status = CMSampleBufferCreate(kCFAllocatorDefault, videoBlock, true, NULL, NULL, videoFormatDescr, 1, 0, NULL, 1, sampleSizeArray, &sampleBuffer);
    if (status != noErr){
        NSLog(@"CMSampleBufferRef failed status=%d", (int)status);
    }
    //开始解码
    VTDecodeFrameFlags flags = kVTDecodeFrame_EnableAsynchronousDecompression;
    VTDecodeInfoFlags flagOut;
    status = VTDecompressionSessionDecodeFrame(session, sampleBuffer, flags, &sampleBuffer, &flagOut);
    if (status != noErr) {
        NSLog(@"Decode falied status = %d",(int)status);
    }
    //释放内存
    CFRelease(videoBlock);
    CFRelease(sampleBuffer);

3.解码之后得到的回调结果数据

void didDecompress( void decompressionOutputRefCon, void sourceFrameRefCon, OSStatus status, VTDecodeInfoFlags infoFlags, CVImageBufferRef imageBuffer, CMTime presentationTimeStamp, CMTime presentationDuration )
{
    if (status != noErr || !imageBuffer) {
        NSLog(@"Error decompresssing frame at time: %.3f error: %d infoFlags: %u", (float)presentationTimeStamp.value/presentationTimeStamp.timescale, (int)status, (unsigned int)infoFlags);
        return;
    }
}
点击复制链接 与好友分享!回本站首页
上一篇:object-c 和 java 可以通用的DES散列加密
下一篇:多段视频合并核心代码
相关文章
图文推荐
文章
推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训
版权所有: 红黑联盟--致力于做实用的IT技术学习网站