ios/mac 将 nv12 或 i420 数据输出到文件,通过 ffplay 播放

ffplay 播放 yuv 命令

ffplay -f rawvideo -video_size 1280x720 -pixel_format nv12 xxx.yuv
ffplay -f rawvideo -video_size 1280x720 -pixel_format yuv420p xxx.yuv

将 yuv 数据写入文件

Objective-C 写法,将 nv12 写入文件

void writeNV12(uint8_t *src_y, int src_stride_y,
               uint8_t *src_uv, int src_stride_uv,
               int width, int height)
{
    
    NSMutableData *dat = [[NSMutableData alloc] init];
    if (src_stride_y == width && src_stride_uv == width) {
        //没有padding
        [dat appendData:[NSData dataWithBytes:src_y length:width*height]];
        [dat appendData:[NSData dataWithBytes:src_uv length:width*height/2]];
    } else {
        //write y, 需要去除 padding
        for (int i = 0; i< height; ++i) {
            [dat appendData:[NSData dataWithBytes:src_y length:width]];
            src_y += src_stride_y;
        }
        //write uv, 需要去除 padding
        for (int i = 0; i< height/2; ++i) {
            [dat appendData:[NSData dataWithBytes:src_uv length:width]];
            src_uv += src_stride_uv;
        }
    }
    
    //save to file
    NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
    path = [path stringByAppendingPathComponent:@"nv12.yuv"];
    
    NSLog(@"file path = %@ ============",path);
    if (![[NSFileManager defaultManager] fileExistsAtPath:path]) {
        [[NSFileManager defaultManager] createFileAtPath:path contents:nil attributes:nil];
    }
    NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:path];
    [fileHandle seekToEndOfFile];
    [fileHandle writeData:dat];
    [fileHandle closeFile];
}

C++ 写法,将 I420 写入文件

void writeI420(uint8_t *src_y, int src_stride_y,
               uint8_t *src_u, int src_stride_u,
               uint8_t *src_v, int src_stride_v,
               int width, int height)
{
    static FILE* m_pOutFile = nullptr;
    if (!m_pOutFile) {
        std::string home{std::getenv("HOME")};
        std::string path = home + "/i420.yuv";
        m_pOutFile = fopen(path.c_str(), "a+");
        printf("======== i420 file path = %s
",path.c_str());
    }
    
    if (width == src_stride_y && width / 2 == src_stride_u && width / 2 == src_stride_v) {
        //write y
        fwrite(src_y, 1, height * src_stride_y, m_pOutFile);
        //write u
        fwrite(src_u, 1, height / 2 * src_stride_u, m_pOutFile);
        //write v
        fwrite(src_v, 1, height / 2 * src_stride_v, m_pOutFile);
    } else {
        //存在 padding 的情况
        for (int i = 0; i < height; ++i) {
            //write y
            fwrite(src_y, 1, width * i, m_pOutFile);
            src_y += src_stride_y;
        }
        for (int i = 0; i < height/2; ++i) {
            //write u
            fwrite(src_u, 1, width/2 * i, m_pOutFile);
            src_u += src_stride_u;
        }
        for (int i = 0; i < height/2; ++i) {
            //write v
            fwrite(src_v, 1, width/2 * i, m_pOutFile);
            src_v += src_stride_v;
        }
    }
}

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容