JavaCpp-FFMpeg avio_reading Example

本文介绍如何使用Java与FFmpeg的AVIOReading功能,通过 FileInputStream 读取内存中的音视频文件,并提供C语言与Java代码示例,适合用于UDP/TCP流媒体处理的基础改造。

JavaCpp FFMpeg Examples -1

1.(avio_reading)
从内存中读取音视频文件,本示例可以深入改造成从udp或者tcp中获取文件

c语言代码链接

Java代码

@Test
	public void test_avio_reading() throws Exception {
		String sourceFilePath = home + "wexin.mp4";
		try (FileInputStream is = new FileInputStream(sourceFilePath)) {
			AVFormatContext inputContext = avformat.avformat_alloc_context();
			int avio_ctx_buffer_size = 4096;
			BytePointer buffer = new BytePointer(avutil.av_malloc(avio_ctx_buffer_size));//必须要调用av_malloc
			AVIOContext avIOContext = avformat.avio_alloc_context(buffer, avio_ctx_buffer_size, 0, null, new Read_packet_Pointer_BytePointer_int() {
				@Override
				public int call(Pointer opaque, BytePointer buf, int buf_size) {
					try {
						byte[] b = new byte[buf_size];
						int size = is.read(b, 0, buf_size);
						if (size < 0) {
							return 0;
						} else {
							buf.put(b, 0, size);
							return size;
						}
					} catch (Throwable t) {
						System.err.println("Error on InputStream.read(): " + t);
						return -1;
					}
				}

			}, null, null);
			inputContext.pb(avIOContext);
			if (avformat.avformat_open_input(inputContext, (BytePointer) null, null, null) < 0) {
				throw new RuntimeException("打开文件失败");
			}
			avformat.avformat_find_stream_info(inputContext, (PointerPointer<?>) null);
			avformat.av_dump_format(inputContext, 0, "", 0);
			avformat.avformat_close_input(inputContext);
		}
	}
在使用 `avio_w8` 函数时出现段错误(Segmentation Fault),通常是由于对无效或未正确初始化的内存地址进行写操作所导致。`avio_w8` 是 FFmpeg 中用于向输出流写入单个字节的函数,它依赖于 `AVIOContext` 的状态。如果该结构体未正确初始化或其内部缓冲区指针 `buf` 或 `buffer` 被错误设置,就可能引发段错误。 ### 常见原因及解决方法 1. **未正确初始化 `AVIOContext`** 在调用 `avio_w8` 之前,必须确保 `AVIOContext` 已通过 `avio_alloc_context` 正确分配并初始化。如果 `buffer` 或 `buf_end` 等字段未设置,或指向无效内存区域,就会导致写入失败[^1]。 ```c uint8_t *buffer = (uint8_t *)av_malloc(32768); AVIOContext *avio = avio_alloc_context(buffer, 32768, 1, NULL, NULL, NULL, NULL); ``` 2. **未正确设置写入回调函数** 如果使用自定义的写入函数(例如网络传输或内存操作),必须确保 `write_packet` 回调函数指针有效且逻辑正确。若该指针为 `NULL` 或者函数内部访问了非法内存,也可能导致段错误[^1]。 ```c int write_packet(void *opaque, uint8_t *buf, int buf_size) { // 自定义写入逻辑 return buf_size; } ``` 3. **多次释放 `AVIOContext` 或其缓冲区** 如果在 `avio_w8` 调用之后或在其他地方错误地释放了 `AVIOContext` 或其内部缓冲区,后续访问就会导致段错误。应确保在调用 `avformat_write_header`、`avformat_write_frame` 和 `av_write_trailer` 等函数后,再调用 `avio_context_free` 释放资源[^1]。 ```c avformat_write_header(fmt_ctx, NULL); avformat_write_frame(fmt_ctx, frame); av_write_trailer(fmt_ctx); avio_context_free(&avio); ``` 4. **未正确处理线程安全问题** 如果在多线程环境下使用 `avio_w8`,必须确保 `AVIOContext` 的访问是线程安全的。FFmpeg 本身不保证 `AVIOContext` 的线程安全性,因此应自行添加锁机制以避免并发写入冲突。 5. **缓冲区大小不足或越界访问** 如果 `AVIOContext` 的缓冲区大小不足,或者在手动操作缓冲区指针时发生越界访问,也可能导致段错误。应确保缓冲区足够大,并在使用 `avio_w8` 时避免手动修改 `buf_ptr` 或 `buf_end`。 ```c // 正确使用 avio_w8 avio_w8(avio, 'A'); ``` ### 调试建议 - 使用 `gdb` 或 `valgrind` 工具检查内存访问问题,定位具体出错位置。 - 检查 `AVIOContext` 的 `buffer`、`buf_ptr`、`buf_end` 等指针是否合法。 - 验证 `write_packet` 回调是否被正确设置并实现。 - 确保所有 FFmpeg 资源在使用完毕后正确释放。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

victorkevin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值