其实是一个用java实现录像的功能,还没有实现,但解码和转码已经可以。
1.maven环境,pom.xml配置
12 81.4.1 3 43.4.2 5UTF-8 63.1.0 79 13org.bytedeco 10javacv-platform 11${javacpp.version} 1214 18org.bytedeco 15javacpp 16${javacpp.version} 1719 org.bytedeco.javacpp-presets 20ffmpeg-platform 21${ffmpeg.version}-${javacpp.version} 22
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) 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*1088112 // u = m_pFrame->data[1];1920*1088/4113 // v = m_pFrame->data[2];1920*1088/4114 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 = new130 // 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相关的AVIOContext165 AVIOContext pb = new AVIOContext();166 if (avio_open(pb, out_file, AVIO_FLAG_READ_WRITE) < 0) {// dont open167 // file168 return -1;169 }170 pFormatCtx.pb(pb);171 // 构建一个新stream172 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 information198 av_dump_format(pFormatCtx, 0, out_file, 1);199 // End Output some information200 201 // 查找编码器202 AVCodec pCodec = avcodec_find_encoder(pCodecCtx.codec_id());203 if (pCodec == null) {// codec not found204 return -1;205 }206 // 设置pCodecCtx的解码器为pCodec207 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 Header214 avformat_write_header(pFormatCtx, (PointerPointer ) 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 // encode225 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 // flush230 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 Trailer249 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来解码的例子,只能自己踩坑前行,一点点的测试,所以可能有很多错误或可以优化的地方。
自己项目中用到,以此来记录,便于以后再遇到相同的问题。