其实是一个用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. C# 动态创建SQL数据库(二)

    使用Entity Framework  创建数据库与表 前面文章有说到使用SQL语句动态创建数据库与数据表,这次直接使用Entriy Framwork 的ORM对象关系映射来创建数据库与表 一 新建项 ...

  2. CODE FIRST之空数据模型

    1.首先添加空Code Firtst模型 2.新建两个实体类,关系一对多 public class UserInfo { public UserInfo() { OrderInfo = new Has ...

  3. UWP 多语言的三个概念

    首先了解一下 RFC4646 和 BCP-47 是什么东西: RFC4646 The name is a combination of an ISO 639 two-letter lowercase ...

  4. 下拉框select中option居中样式

    下拉框select中option居中样式 text-align:center;text-align-last:center;

  5. 【kuangbin专题】计算几何_凸包

    1.poj1113 Wall 题目:http://poj.org/problem?id=1113 题意:用一条线把若干个点包起来,并且线距离任何一个点的距离都不小于r.求这条线的最小距离是多少? 分析 ...

  6. GC日志时间分析

    在GC日志里,一条完整的GC日志记录最后,会带有本次GC所花费的时间,如下面这一条新生代GC: [GC [DefNew: 3298K->149K(5504K), secs] [Times: us ...

  7. hadoop集群搭建(hdfs)

    (搭建hadoop集群的前提是服务器已成功安装jdk以及服务器之间已设置免密码登录,服务器之间的免密码登录可参考<linux服务器间ssh免密码登录>) 1.下载hadoop安装包 wge ...

  8. 课程二(Improving Deep Neural Networks: Hyperparameter tuning, Regularization and Optimization),第三周(Hyperparameter tuning, Batch Normalization and Programming Frameworks) —— 2.Programming assignments

    Tensorflow Welcome to the Tensorflow Tutorial! In this notebook you will learn all the basics of Ten ...

  9. 课程一(Neural Networks and Deep Learning),第三周(Shallow neural networks)—— 3.Programming Assignment : Planar data classification with a hidden layer

    Planar data classification with a hidden layer Welcome to the second programming exercise of the dee ...

  10. (转) 面向对象设计原则(二):开放-封闭原则(OCP)

    原文:https://blog.csdn.net/tjiyu/article/details/57079927 面向对象设计原则(二):开放-封闭原则(OCP) 开放-封闭原则(Open-closed ...