其实是一个用java实现录像的功能,还没有实现,但解码和转码已经可以。

1.maven环境,pom.xml配置

 1 <properties>
2 <javacpp.version>1.4.1</javacpp.version>
3 <!-- ffmpeg版本 -->
4 <ffmpeg.version>3.4.2</ffmpeg.version>
5 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
6 <servlet.version>3.1.0</servlet.version>
7 </properties>
8 <dependency>
9 <groupId>org.bytedeco</groupId>
10 <artifactId>javacv-platform</artifactId>
11 <version>${javacpp.version}</version>
12 </dependency>
13 <dependency>
14 <groupId>org.bytedeco</groupId>
15 <artifactId>javacpp</artifactId>
16 <version>${javacpp.version}</version>
17 </dependency>
18 <dependency>
19 <groupId>org.bytedeco.javacpp-presets</groupId>
20 <artifactId>ffmpeg-platform</artifactId>
21 <version>${ffmpeg.version}-${javacpp.version}</version>
22 </dependency>

2.代码

  1 package com.br.test;
2
3 import java.io.ByteArrayOutputStream;
4 import java.io.File;
5 import java.io.FileOutputStream;
6 import java.io.IOException;
7 import java.nio.ByteBuffer;
8 import org.bytedeco.javacpp.*;
9 import static org.bytedeco.javacpp.avcodec.*;
10 import static org.bytedeco.javacpp.avformat.*;
11 import static org.bytedeco.javacpp.avutil.*;
12 import static org.bytedeco.javacpp.swscale.*;
13
14 public class NewTest {
15 // Load only once formats and codecs
16 static {
17 av_register_all();
18 // avformat_network_init();
19 avcodec_register_all();
20 }
21 public int codec_id;
22 public AVCodecContext m_pCodecCtx = null; // URL中视频解码部分内容
23 public AVFrame m_pFrame = null; // 全局使用帧对象
24 public AVFrame m_pFrameRGB = null;
25 public AVCodec m_pCodec = null;
26 public AVCodecParserContext pCodecParserCtx = null;
27 public AVPacket packet = null;
28 public SwsContext m_pImageConvertCtx = null; // 构造全局对象,供sws_scale切割图片使用
29 public SwsContext img_convert_ctx = null;
30 public Integer count = 0;
31 public int count_size;
32 public BytePointer cur_ptr;
33 public FileOutputStream os;
34 private ByteArrayOutputStream myByteArrayOutputStream = new ByteArrayOutputStream();
35
36 public NewTest() {
37 System.out.println("init begin");
38
39 m_pFrame = av_frame_alloc();
40 codec_id = AV_CODEC_ID_H264;
41 m_pFrameRGB = av_frame_alloc();
42 m_pCodec = avcodec_find_decoder(codec_id);
43
44 if (m_pCodec == null) {
45 System.out.println("Codec not found\n");
46 }
47 m_pCodecCtx = avcodec_alloc_context3(m_pCodec);
48 if (m_pCodecCtx == null) {
49 System.out.println("Could not allocate video codec context\n");
50 }
51
52 pCodecParserCtx = av_parser_init(codec_id);
53 if (pCodecParserCtx == null) {
54 System.out.println("Could not allocate video parser context\n");
55 }
56
57 if (avcodec_open2(m_pCodecCtx, m_pCodec, (PointerPointer<Pointer>) null) < 0) {
58 System.out.println("Could not open codec\n");
59 }
60 img_convert_ctx = sws_getContext(1920, 1088, AV_PIX_FMT_YUV420P, 1920, 1088, AV_PIX_FMT_BGRA, SWS_FAST_BILINEAR,
61 null, null, (DoublePointer) null);
62
63 packet = new AVPacket();
64
65 packet = av_packet_alloc();
66
67 av_new_packet(packet, 30000);
68
69 int numBytes = av_image_get_buffer_size(AV_PIX_FMT_BGRA, 1920, 1088, 1);
70
71 BytePointer rgbData = new BytePointer(av_malloc(numBytes));
72
73 av_image_fill_arrays(m_pFrameRGB.data(), m_pFrameRGB.linesize(), rgbData, AV_PIX_FMT_BGRA, 1920, 1088, 1);
74
75 System.out.println("init end");
76 }
77
78 public void dec_loop(byte[] H264) {
79
80 ByteBuffer data = ByteBuffer.allocate(H264.length);
81 data.put(H264);
82 int cur_size = H264.length;
83 IntPointer pktSize = new IntPointer(packet.size());
84 BytePointer temp_bp = new BytePointer();
85 while (cur_size > 0) {
86
87 data.flip();
88 int slen = av_parser_parse2(pCodecParserCtx, m_pCodecCtx, temp_bp, pktSize, new BytePointer(data), cur_size,
89 AV_NOPTS_VALUE, AV_NOPTS_VALUE, AV_NOPTS_VALUE);
90 packet = packet.size(pktSize.get());
91
92 data.position(slen);
93 data = data.compact();
94 cur_size -= slen;
95
96 if (pktSize.get() == 0) {
97 continue;
98 }
99 packet = packet.data(temp_bp);
100 // for(int i = 0;i <5;i++){
101 // byte b = packet.data().get(i);
102 // System.out.print(byteToHex(b)+" ");
103 // }
104 // System.out.println("------------------------------!!!!------------------"+packet.size());
105 // packet.data().asBuffer();
106
107 int asp = avcodec_send_packet(m_pCodecCtx, packet);
108
109 if (avcodec_receive_frame(m_pCodecCtx, m_pFrame) == 0) {
110 // m_pFrame.data(0);
111 // y = m_pFrame->data[0];1920*1088
112 // u = m_pFrame->data[1];1920*1088/4
113 // v = m_pFrame->data[2];1920*1088/4
114
115 System.err.println(
116 "->>> decode success " + "width :" + m_pFrame.width() + " " + "height :" + m_pFrame.height());
117
118 sws_scale(img_convert_ctx, m_pFrame.data(), m_pFrame.linesize(), 0, m_pCodecCtx.height(),
119 m_pFrameRGB.data(), m_pFrameRGB.linesize());
120 BytePointer by_bgra_data = m_pFrameRGB.data(0);
121 try {
122 // String imgName = "C:/Users/user/Desktop/test/test" + count + ".h264";
123 // saveImg(m_pFrame, imgName);
124 // count++;
125 // for (int i = 0; i < 1920 * 1088 * 4; i++) {
126 // myByteArrayOutputStream.write(by_bgra_data.get(i));
127 // }
128 // if (myByteArrayOutputStream.size() == 1920 * 1088 * 4) {
129 // File file = new
130 // File("C://Users//user//Desktop//test//success.yuv");
131 // if (!file.exists()) {
132 // file.createNewFile();
133 // }
134 // FileOutputStream fe = new FileOutputStream(file, true);
135 // fe.write(myByteArrayOutputStream.toByteArray());
136 // fe.flush();
137 // fe.close();
138 // myByteArrayOutputStream.reset();
139 // }
140 } catch (Exception e) {
141 e.printStackTrace();
142 }
143 }
144 // av_packet_unref(packet);
145 }
146 // av_packet_free(packet);
147 }
148
149 public int saveImg(AVFrame pFrame, String out_file) throws IOException {
150 AVCodec codec = null;
151 AVPacket pkt = null;
152 AVStream pAVStream = null;
153 int ret = -1;
154 AVDictionary avd = new AVDictionary(null);
155 int width = pFrame.width(), height = pFrame.height();
156 // 分配AVFormatContext对象
157 AVFormatContext pFormatCtx = avformat_alloc_context();
158 // 设置输出文件格式
159 pFormatCtx.oformat(av_guess_format("h264", null, null));
160 if (pFormatCtx.oformat() == null) {
161 return -1;
162 }
163 try {
164 // 创建并初始化一个和该url相关的AVIOContext
165 AVIOContext pb = new AVIOContext();
166 if (avio_open(pb, out_file, AVIO_FLAG_READ_WRITE) < 0) {// dont open
167 // file
168 return -1;
169 }
170 pFormatCtx.pb(pb);
171 // 构建一个新stream
172 pAVStream = avformat_new_stream(pFormatCtx, codec);
173 if (pAVStream == null) {
174 return -1;
175 }
176 int codec_id = pFormatCtx.oformat().video_codec();
177 // 设置该stream的信息
178 AVCodecContext pCodecCtx = pAVStream.codec();
179 pCodecCtx.codec_id(codec_id);
180 pCodecCtx.codec_type(AVMEDIA_TYPE_VIDEO);
181 pCodecCtx.pix_fmt(AV_PIX_FMT_YUV420P);
182 pCodecCtx.width(width);
183 pCodecCtx.height(height);
184 pCodecCtx.time_base().num(1);
185 pCodecCtx.time_base().den(25);
186 pCodecCtx.qmin(10);
187 pCodecCtx.qmax(51);
188 pCodecCtx.bit_rate(400000);
189 pCodecCtx.gop_size(12);
190 pCodecCtx.qcompress(0.6f);
191
192 if (pCodecCtx.codec_id() == AV_CODEC_ID_H264) {
193 av_dict_set(avd, "preset", "slow", 0);
194 av_dict_set(avd, "tune", "zerolatency", 0);
195 }
196
197 // Begin Output some information
198 av_dump_format(pFormatCtx, 0, out_file, 1);
199 // End Output some information
200
201 // 查找编码器
202 AVCodec pCodec = avcodec_find_encoder(pCodecCtx.codec_id());
203 if (pCodec == null) {// codec not found
204 return -1;
205 }
206 // 设置pCodecCtx的解码器为pCodec
207 if (avcodec_open2(pCodecCtx, pCodec, avd) < 0) {
208 System.err.println("Could not open codec.");
209 av_dict_free(avd);
210 return -1;
211 }
212
213 // Write Header
214 avformat_write_header(pFormatCtx, (PointerPointer<Pointer>) null);
215
216 // 给AVPacket分配足够大的空间
217 pkt = new AVPacket();
218 int yuvSize = ((width * height) / 2) * 3;
219 if (av_new_packet(pkt, yuvSize) < 0) {
220 return -1;
221 }
222
223 int[] got_picture = { 0 };
224 // encode
225
226 if (avcodec_encode_video2(pCodecCtx, pkt, pFrame, got_picture) >= 0) {
227 System.out.println("got_picture[0]:" + got_picture[0]);
228 if (got_picture[0] == 1) {
229 // flush
230 BytePointer pkt_data = pkt.data();
231 // 输出pkt数据到文件
232 for (int i = 0; i < pkt.size(); i++) {
233 myByteArrayOutputStream.write(pkt_data.get(i));
234 }
235 if (myByteArrayOutputStream.size() == pkt.size()) {
236 File file = new File("C://Users//user//Desktop//test//success.h264");
237 if (!file.exists()) {
238 file.createNewFile();
239 }
240 FileOutputStream fe = new FileOutputStream(file, true);
241 fe.write(myByteArrayOutputStream.toByteArray());
242 fe.flush();
243 fe.close();
244 myByteArrayOutputStream.reset();
245 }
246
247 if ((ret = av_write_frame(pFormatCtx, pkt)) >= 0) {
248 // Write Trailer
249 if (av_write_trailer(pFormatCtx) >= 0) {
250 System.err.println("->>> Encode Successful. pkt.size():" + pkt.size());
251 } else {
252 System.err.println("Encode failed.");
253 }
254 }
255 }
256 }
257 return ret;
258 // 结束时销毁
259 } finally {
260 if (pkt != null) {
261 av_free_packet(pkt);
262 }
263 if (pAVStream != null) {
264 avcodec_close(pAVStream.codec());
265 }
266 if (pFormatCtx != null) {
267 avio_close(pFormatCtx.pb());
268 avformat_free_context(pFormatCtx);
269 }
270 }
271 }
272
273 public static byte[] conver(ByteBuffer byteBuffer) {
274 int len = byteBuffer.limit() - byteBuffer.position();
275 byte[] bytes = new byte[len];
276
277 if (byteBuffer.isReadOnly()) {
278 return null;
279 } else {
280 byteBuffer.get(bytes);
281 }
282 return bytes;
283 }
284
285 public static String byteToHex(byte b) {
286 String hex = Integer.toHexString(b & 0xFF);
287 if (hex.length() < 2) {
288 hex = "0" + hex;
289 }
290 return hex;
291 }
292
293 public static void main(String[] args) {
294 NewTest test = new NewTest();
295 }
296
297 }

因为在网上很少有用javacv来解码的例子,只能自己踩坑前行,一点点的测试,所以可能有很多错误或可以优化的地方。

自己项目中用到,以此来记录,便于以后再遇到相同的问题。

使用javacv,解码socket接收的H264码流(byte[]),转为yuv处理,最后再合成转为H264的更多相关文章

  1. H264码流打包分析

    转自:http://www.360doc.com/content/13/0124/08/9008018_262076786.shtml   SODB 数据比特串-->最原始的编码数据 RBSP ...

  2. H264码流打包分析(精华)

    H264码流打包分析 SODB 数据比特串-->最原始的编码数据 RBSP 原始字节序列载荷-->在SODB的后面填加了结尾比特(RBSP trailing bits 一个bit“1”)若 ...

  3. H264码流解析及NALU

    ffmpeg 从mp4上提取H264的nalu http://blog.csdn.net/gavinr/article/details/7183499 639     /* bitstream fil ...

  4. H264码流中SPS PPS详解<转>

    转载地址:https://zhuanlan.zhihu.com/p/27896239 1 SPS和PPS从何处而来? 2 SPS和PPS中的每个参数起什么作用? 3 如何解析SDP中包含的H.264的 ...

  5. RTP协议全解析(H264码流和PS流)

    转自:http://blog.csdn.net/chen495810242/article/details/39207305 写在前面:RTP的解析,网上找了很多资料,但是都不全,所以我力图整理出一个 ...

  6. (转)RTP协议全解(H264码流和PS流)

    写在前面:RTP的解析,网上找了很多资料,但是都不全,所以我力图整理出一个比较全面的解析, 其中借鉴了很多文章,我都列在了文章最后,在此表示感谢. 互联网的发展离不开大家的无私奉献,我决定从我做起,希 ...

  7. RTP协议全解(H264码流和PS流)

    写在前面:RTP的解析,网上找了很多资料,但是都不全,所以我力图整理出一个比较全面的解析, 其中借鉴了很多文章,我都列在了文章最后,在此表示感谢. 互联网的发展离不开大家的无私奉献,我决定从我做起,希 ...

  8. H264编码原理以及I帧、B和P帧详解, H264码流结构分析

    H264码流结构分析 http://blog.csdn.net/chenchong_219/article/details/37990541 1.码流总体结构: h264的功能分为两层,视频编码层(V ...

  9. 从H264码流中获取视频宽高 (SPS帧) 升级篇

    之前写过 <从H264码流中获取视频宽高 (SPS帧)> . 但发现很多局限性,而且有时解出来是错误的. 所以重新去研究了. 用了 官方提供的代码库来解析. 花了点时间,从代码库里单独把解 ...

  10. 从H264码流中获取视频宽高 (SPS帧)

    获取.h264视频宽高的方法 花了2个通宵终于搞定.(后面附上完整代码) http://write.blog.csdn.net/postedit/7852406 图像的高和宽在H264的SPS帧中.在 ...

随机推荐

  1. ASP.NET写的一个博客系统

    由于域名闲置,正好也有服务器空间,短期内开发了一个博客系统. 大家都来谈  http://www.djdlt.com 目前是开放注册,免费发布.(限于空间有限,图片还是尽量少传些) 网站架构: ASP ...

  2. 探索基于.NET下实现一句话木马之asmx篇

    0x01 前言 上篇介绍了一般处理程序(ashx)的工作原理以及实现一句话木马的过程,今天接着介绍Web Service程序 (asmx)下的工作原理和如何实现一句话木马,当然介绍之前笔者找到了一款a ...

  3. 【文文殿下】 [USACO08MAR]土地征用 题解

    题解 斜率优化裸题. 有个很玄学的事情,就是我用\(f[i]=min\{f[j-1]+p[j].y*p[i].x\}\) 会很奇怪的Wa . 明明和\(f[i]=min\{f[j]+p[j+1].y* ...

  4. [WC2005]双面棋盘(线段树+并查集)

    线段树+并查集维护连通性. 好像 \(700ms\) 的时限把我的常数超级大的做法卡掉了, 必须要开 \(O_2\) 才行. 对于线段树的每一个结点都开左边的并查集,右边的并查集,然后合并. \(Co ...

  5. spring boot 中使用LUA脚本

    编写LUA脚本 该脚本功能:先检查redis中某个key的值是否与期望的值V1一致,如果一致则将其修改为新的值V2并返回true,否则返回false.其实就是CAS. local current = ...

  6. Docker三剑客之Docker Swarm

    一.什么是Docker Swarm Swarm是Docker公司推出的用来管理docker集群的平台,几乎全部用GO语言来完成的开发的,代码开源在https://github.com/docker/s ...

  7. 集合框架map_DAY18

    1:map集合(掌握) (1)Map集合存储的是键值对元素.键是唯一的,值可以重复. (2)Map和Collection的区别? A:Map是双列集合,存储的元素键值对,键唯一,值可以重复. B:Co ...

  8. rpm安装JDK方法

    由于版权原因,Linux发行版并没有包含官方版的Oracle JDK,必须自己从官网上下载安装.Oracle官网用Cookie限制下载方式,使得眼下只能用浏览器进行下载,使用其他方式可能会导致下载失败 ...

  9. 线程中的同步辅助类Semaphore

    同步辅助类  线程池  并发集合类 都是在线程同步的基础上增加了一些同步的东西,在线程同步的基础上更好的实现线程同步.实现的效率更高,更方便而已. 多线程并不是很难 需要你把代码写出来...然后分析运 ...

  10. 线程中消费者生产者的实例代码(synchronized关键字)

    http://www.cnblogs.com/DreamDrive/p/6204665.html  这个是用Lock类实现的. 场景: 厨师类: import java.util.List; impo ...