如何用C++封装视频文件的H.264码流

2024-01-12

我正在尝试转换视频文件(.mp4) 到 Dicom 文件。
我通过在 Dicom 中存储单个图像(视频的每帧一个图像)成功地做到了这一点,
但结果是文件太大,这对我来说不好。
相反,我想将存储在视频文件中的 H.264 比特流封装到 Dicom 文件中。
我尝试按如下方式获取文件的字节:

std::ifstream inFile(file_name, std::ifstream::binary);

inFile.seekg(0, inFile.end);
std::streampos length = inFile.tellg();
inFile.seekg(0, inFile.beg);

std::vector<unsigned char> bytes(length);

inFile.read((char*)&bytes[0], length);

但我认为我错过了诸如封装读取字节之类的事情,因为结果 Dicom 文件是黑色图像。

在 python 中,我将使用 pydicom.encaps.encapsulate 函数来实现此目的:
https://pydicom.github.io/pydicom/dev/reference/ generated/pydicom.encaps.encapsulate.html https://pydicom.github.io/pydicom/dev/reference/generated/pydicom.encaps.encapsulate.html

with open(videofile, 'rb') as f:
    dataset.PixelData = encapsulate([f.read()])

C++ 中是否有相当于encapsulate功能?
或者任何不同的方式来获取一个流中视频的封装像素数据而不是逐帧获取?

这是初始化的代码Dcmdataset, 使用bytes提取:

VideoFileStream* vfs = new VideoFileStream();
vfs->setFilename(file_name);
if (!vfs->open())
    return false;

DcmDataset* dataset = new DcmDataset();
dataset->putAndInsertOFStringArray(DCM_SeriesInstanceUID, dcmGenerateUniqueIdentifier(new char[100], SITE_SERIES_UID_ROOT));
dataset->putAndInsertOFStringArray(DCM_SOPInstanceUID, dcmGenerateUniqueIdentifier(new char[100], SITE_INSTANCE_UID_ROOT));
dataset->putAndInsertOFStringArray(DCM_StudyInstanceUID, dcmGenerateUniqueIdentifier(new char[100], SITE_STUDY_UID_ROOT));
dataset->putAndInsertOFStringArray(DCM_MediaStorageSOPInstanceUID, dcmGenerateUniqueIdentifier(new char[100], SITE_UID_ROOT));
dataset->putAndInsertString(DCM_MediaStorageSOPClassUID, UID_VideoPhotographicImageStorage);
dataset->putAndInsertString(DCM_SOPClassUID, UID_VideoPhotographicImageStorage);
dataset->putAndInsertOFStringArray(DCM_TransferSyntaxUID, UID_MPEG4HighProfileLevel4_1TransferSyntax);
dataset->putAndInsertOFStringArray(DCM_PatientID, "987655");
dataset->putAndInsertOFStringArray(DCM_StudyDate, "20050509");
dataset->putAndInsertOFStringArray(DCM_Modality, "ES");
dataset->putAndInsertOFStringArray(DCM_PhotometricInterpretation, "YBR_PARTIAL_420");
dataset->putAndInsertUint16(DCM_SamplesPerPixel, 3);
dataset->putAndInsertUint16(DCM_BitsAllocated, 8);
dataset->putAndInsertUint16(DCM_BitsStored, 8);
dataset->putAndInsertUint16(DCM_HighBit, 7);
dataset->putAndInsertUint16(DCM_Rows, vfs->height());
dataset->putAndInsertUint16(DCM_Columns, vfs->width());
dataset->putAndInsertUint16(DCM_CineRate, vfs->framerate());
dataset->putAndInsertUint16(DCM_FrameTime, 1000.0 * 1 / vfs->framerate());
const Uint16* arr = new Uint16[]{ 0x18,0x00, 0x63, 0x10 };  
dataset->putAndInsertUint16Array(DCM_FrameIncrementPointer, arr, 4);
dataset->putAndInsertString(DCM_NumberOfFrames, std::to_string(vfs->numFrames()).c_str());
dataset->putAndInsertOFStringArray(DCM_FrameOfReferenceUID, dcmGenerateUniqueIdentifier(new char[100], SITE_UID_ROOT));
dataset->putAndInsertUint16(DCM_PixelRepresentation, 0);
dataset->putAndInsertUint16(DCM_PlanarConfiguration, 0);
dataset->putAndInsertOFStringArray(DCM_ImageType, "ORIGINAL");
dataset->putAndInsertOFStringArray(DCM_LossyImageCompression, "01");
dataset->putAndInsertOFStringArray(DCM_LossyImageCompressionMethod, "ISO_14496_10");
dataset->putAndInsertUint16(DCM_LossyImageCompressionRatio, 30);
dataset->putAndInsertUint8Array(DCM_PixelData, (const Uint8 *)bytes.data(), length);

DJ_RPLossy repParam;
dataset->chooseRepresentation(EXS_MPEG4HighProfileLevel4_1, &repParam);
dataset->updateOriginalXfer();

DcmFileFormat fileformat(dataset); 
OFCondition status = fileformat.saveFile("C://temp//videoTest", EXS_LittleEndianExplicit);

技巧是将属性 PixelData 的值重定向到文件流。这样,视频就可以按需分块加载(即当访问属性时)。 但你必须显式地创建整个结构,即:

  • 像素数据元素
  • 像素序列...
  • ...偏移表
  • ...包含 MPEG 文件内容的单个项目

Code

// set length to the size of the video file
DcmInputFileStream dcmFileStream(videofile.c_str(), 0);
DcmPixelSequence* pixelSequence = new DcmPixelSequence(DCM_PixelSequenceTag));
DcmPixelItem* offsetTable = new DcmPixelItem(DCM_PixelItemTag);
pixelSequence->insert(offsetTable);
DcmPixelItem* frame = new DcmPixelItem(DCM_PixelItemTag);
frame->createValueFromTempFile(dcmFileStream.newFactory(), OFstatic_cast(Uint32, length), EBO_LittleEndian);
pixelSequence->insert(frame);
DcmPixelData* pixelData = new DcmPixeldata(DCM_PixelData);
pixelData->putOriginalRepresentation(EXS_MPEG4HighProfileLevel4_1, nullptr, pixelSequence);
dataset->insert(pixelData, true);
DcmFileFormat fileformat(dataset); 
OFCondition status = fileformat.saveFile("C://temp//videoTest");

请注意,如果您以 VR 隐式小尾数法保存文件,则会“破坏”压缩。

如上所述,并且在代码中显而易见,整个 MPEG 文件被包装到 PixelData 中的单个项目中。这符合 DICOM 标准,但您可能希望将每个帧封装在一个项目中。

注意:此处不提供错误处理

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何用C++封装视频文件的H.264码流 的相关文章

  • 每个托管线程是否都有自己对应的本机线程?

    我想知道是否在 Net 中创建托管线程 通过调用Thread Start 导致在后台创建一个本机线程 那么托管线程是否有对应的本机线程呢 如果是 当托管线程等待或睡眠时 是否意味着相应的本机线程也在等待或睡眠 是的 NET 线程映射到所有当
  • 未提供参数时如何指定 C# System.Commandline 行为?

    在我的控制台应用程序中 当未提供控制台参数时 将执行我指定列表 在本例中为参数 3 的任何处理程序 调用该处理程序时 布尔参数设置为 false 但对我来说 根本不调用它更有意义 如何防止这种情况发生并显示帮助文本 using System
  • 计算 Richtextbox 中所有单词的最有效方法是什么?

    我正在编写一个文本编辑器 需要提供实时字数统计 现在我正在使用这个扩展方法 public static int WordCount this string s s s TrimEnd if String IsNullOrEmpty s re
  • C中的malloc内存分配方案

    我在 C 中尝试使用 malloc 发现 malloc 在分配了一些内存后浪费了一些空间 下面是我用来测试 malloc 的一段代码 include
  • 错误:表达式不产生值

    我尝试将以下 C 代码转换为 VB NET 但在编译代码时出现 表达式不产生值 错误 C Code return Fluently Configure Mappings m gt m FluentMappings AddFromAssemb
  • 当我们想要返回对象的引用时,为什么我们在赋值运算符中返回 *this 而通常(而不是 this)?

    我正在学习 C 和指针 我以为我理解了指针 直到我看到这个 一方面 asterix 运算符是解引用的 这意味着它返回值所指向的地址中的值 而与号 运算符则相反 它返回值存储的地址记忆 现在阅读有关赋值重载的内 容 它说 我们返回 this因
  • 复制目录内容

    我想将目录 tmp1 的内容复制到另一个目录 tmp2 tmp1 可能包含文件和其他目录 我想使用C C 复制tmp1的内容 包括模式 如果 tmp1 包含目录树 我想递归复制它们 最简单的解决方案是什么 我找到了一个解决方案来打开目录并读
  • 单个对象的 Monogame XNA 变换矩阵?

    我读过一些解释 XNA Monogame 变换矩阵的教程 问题是这些矩阵应用于 SpriteBatch Begin matrix 这意味着所有 Draw 代码都将被转换 如何将变换矩阵应用于单个可绘制对象 就我而言 我想转换滚动背景 使其自
  • 如何区分用户点击链接和页面自动重定向?

    拥有 C WebBrowser control http msdn microsoft com en us library system windows forms webbrowser aspx在我的 WinForms 应用程序中 并意识
  • 为什么 Google 测试会出现段错误?

    我是 Google Test 的新手 正在尝试提供的示例 我的问题是 当我引入失败并设置GTEST BREAK ON FAILURE 1 或使用命令行选项 GTest 将出现段错误 我正在考虑这个例子 https code google c
  • 由 IHttpClientFactory 注入时模拟 HttpClient 处理程序

    我创建了一个自定义库 它会自动为依赖于特定服务的 Polly 策略设置HttpClient 这是使用以下方法完成的IServiceCollection扩展方法和类型化客户端方法 一个简化的例子 public static IHttpClie
  • 将 Word 文档另存为图像

    我正在使用下面的代码将 Word 文档转换为图像文件 但是图片显得太大 内容不适合 有没有办法渲染图片或将图片保存到合适的尺寸 private void btnConvert Click object sender EventArgs e
  • 从 Linux 内核模块中调用用户空间函数

    我正在编写一个简单的 Linux 字符设备驱动程序 以通过 I O 端口将数据输出到硬件 我有一个执行浮点运算的函数来计算硬件的正确输出 不幸的是 这意味着我需要将此函数保留在用户空间中 因为 Linux 内核不能很好地处理浮点运算 这是设
  • 标准化 UTF-8 到底是什么?

    The 重症监护室项目 http userguide icu project org transforms normalization 现在也有一个PHP库 http us php net manual en class normalize
  • 我可以使用 moq Mock 来模拟类而不是接口吗?

    正在经历https github com Moq moq4 wiki Quickstart https github com Moq moq4 wiki Quickstart 我看到它 Mock 一个接口 我的遗留代码中有一个没有接口的类
  • 如何在 Xaml 文本中添加电子邮件链接?

    我在 Windows Phone 8 应用程序中有一些大文本 我希望其中有电子邮件链接 例如 mailto 功能 这是代码的一部分
  • 使用自定义堆的类似 malloc 的函数

    如果我希望使用自定义预分配堆构造类似 malloc 的功能 那么 C 中最好的方法是什么 我的具体问题是 我有一个可映射 类似内存 的设备 已将其放入我的地址空间中 但我需要获得一种更灵活的方式来使用该内存来存储将随着时间的推移分配和释放的
  • C# 中的合并运算符?

    我想我记得看到过类似的东西 三元运算符 http msdn microsoft com en us library ty67wk28 28VS 80 29 aspx在 C 中 它只有两部分 如果变量值不为空 则返回变量值 如果为空 则返回默
  • 使用管道时,如果子进程数量大于处理器数量,进程是否会被阻塞?

    当子进程数量很大时 我的程序停止运行 我不知道问题是什么 但我猜子进程在运行时以某种方式被阻止 下面是该程序的主要工作流程 void function int process num int i initial variables for
  • 从列表中选择项目以求和

    我有一个包含数值的项目列表 我需要使用这些项目求和 我需要你的帮助来构建这样的算法 下面是一个用 C 编写的示例 描述了我的问题 int sum 21 List

随机推荐

  • Lua检查文件是否打开

    我正在尝试编写一个 lua 文件脚本来检查某个文件是否打开 然后我希望它关闭该文件 如果该文件已打开 我知道如何检查文件是否存在 但我需要知道如何检查文件是否打开 即文件正在运行 Lua 与 C C 和几乎所有其他语言一样 只能关闭它打开的
  • 页面加载时检查引导表复选框

    我在用引导表 http bootstrap table wenzhixin net cn documentation 我正在尝试设置复选框 问题是复选框在没有特殊原因的情况下被启动为选中状态
  • 如何从firestore数据库中的云功能更新多个文档?

    我是 firebase 云功能的新手 我想更新username一些文件的字段来自posts集合时users收藏改变它username特定文档的字段 我使用以下代码来做到这一点 exports updateProfileUsername fu
  • VC++:KB971090 并选择 Visual C 运行时 DLL 依赖项

    如您所知 Microsoft 最近为 Visual Studio 部署了安全更新 KB971090 http support microsoft com kb 971090 除此之外 这还将 Visual C 运行时 DLL 从版本 8 0
  • Java HttpUrlConnection POST 请求特殊字符奇怪的行为

    我正在尝试使用 HttpURLConnection 实现 POST 请求 这是我的代码 private static void call String body throws IOException HttpURLConnection co
  • 了解结构域突变

    来自锈书 https doc rust lang org book structs html关于如何改变结构体字段 let mut point Point x 0 y 0 point x 5 然后 可变性是绑定的属性 而不是结构本身的属性
  • 为什么 setInterval 不能避免 XSS?

    我正在经历OWASP 跨站脚本防止备忘单 https cheatsheetseries owasp org cheatsheets Cross Site Scripting Prevention Cheat Sheet html 规则 3
  • awk 查找特定日期的最大值

    我有一个包含多行的文件 每行包含以下数据 name 20150801 1 20150802 4 20150803 6 20150804 7 20150805 7 20150806 8 20150807 11532 20150808 1239
  • 如何让java日历从星期一开始工作日?

    我已经编写了代码 它使用 Java 日历并显示时间戳中的 DAY OF WEEK 但默认日历从星期日 1 开始 我希望从星期一开始 例如 星期一应该返回 1 这是我的代码 Calender c Calender getInstance Ti
  • 是否存在从 Eclipse 中的同一代码库维护免费和专业应用程序版本的约定?

    我正在发布一个应用程序的两个版本 免费和付费 两者之间的差异很少 我想使用相同的代码库来发布两者 也许为其他版本定义了不同的常量 有人这样做过吗 有人能指出我正确的方向吗 谢谢 Use an Android 库项目 http develop
  • React 的 setState 方法带有 prevState 参数

    我是 React 新手 只是对 setState 方法有疑问 假设我们有一个组件 class MyApp extends React Component state count 3 Increment gt this setState pr
  • 使用 jQuery 文件上传 - blueimp(基于 Ajax)php / yii 上传超过 1GB 到 2GB 的大文件,它在 Firefox 浏览器中显示错误

    我正在尝试上传一个大文件1GB to 2GB using jQuery File Upload blueimp 基于阿贾克斯 php yii Framework 1 15我已设置这些值来上传更大的文件 memory limit 2048M
  • .NET Linq 左连接

    我在 SQL 中有 2 个表 Table 1 Step Id Step Name Table 2 Profile Id Step Id Completed 即使表 2 中不匹配 我也想返回以下结果 Results Table1 Step I
  • Python + SqlAlchemy:当父子都是新建时添加父子记录

    我问过一个类似的问题 https stackoverflow com q 59097167 2144390已经 但我认为如果我不提供我已经编码的示例 而是简单地陈述我的案例的目标 那么会更清楚 开始 我有一个处于自引用一对多关系的表 即 它
  • 使用字符串输入和输出运行进程

    这里有很多与 fork 和 exec 相关的问题 不过 我还没有找到真正使使用它们的过程变得简单的方法 而让程序员的生活变得简单就是目标 我需要一个 C Linux 友好的函数来执行以下操作 string RunCommand string
  • 如何给函数起别名?

    我正在尝试为 R 中的函数创建别名 例如 要获取 R 中向量的长度 length the vector returns the length of the vector 我想创建一个名为 len 的函数的别名 len the vector
  • 使用 Serde 反序列化具有多种类型字段的 JSON

    我有一些 JSON 文本数据 其字段可以是字符串或字符串数 组 以下是四个可能的示例 keya some string keyb some string keya some string keyb some string some stri
  • 比较 SPARQL 图

    如何使用 SPARQL 比较两个 RDF 图 如果我有图表 a 和 b 我想找到 a 出现在 b 中的所有时间 我可以查询 a 的所有主语 谓词和宾语 然后以编程方式构建一个与 b 中的 a 模式匹配的模式查询 有没有一种方法可以在 SPA
  • xcode 命令行测试,参数在启动时传递

    我在 CI 上实施 xcodebuild 命令测试时遇到了小问题 我有与特定设备语言相关的测试 在 xcode 中我可以将 启动时传递的参数 设置为 AppleLanguages 语言 我可以使用 xcodebuild 传递该参数吗 我的脚
  • 如何用C++封装视频文件的H.264码流

    我正在尝试转换视频文件 mp4 到 Dicom 文件 我通过在 Dicom 中存储单个图像 视频的每帧一个图像 成功地做到了这一点 但结果是文件太大 这对我来说不好 相反 我想将存储在视频文件中的 H 264 比特流封装到 Dicom 文件