FFMPEG的文档少,JavaCV的文档就更少了。从网上找到这篇100行代码实现最简单的基于FFMPEG+SDL的视频播放器 。地址是http://blog.csdn.net/leixiaohua1020/article/details/8652605。
用JavaCV重新实现并使用opencv_highgui进行显示。
1 import com.googlecode.javacpp.IntPointer; 2 import com.googlecode.javacpp.Pointer; 3 import com.googlecode.javacv.cpp.avcodec; 4 import com.googlecode.javacv.cpp.avcodec.AVPacket; 5 import com.googlecode.javacv.cpp.avcodec.AVPicture; 6 import com.googlecode.javacv.cpp.avformat; 7 import com.googlecode.javacv.cpp.avutil; 8 import com.googlecode.javacv.cpp.avutil.AVDictionary; 9 import com.googlecode.javacv.cpp.opencv_core; 10 import static com.googlecode.javacv.cpp.opencv_core.IPL_DEPTH_8U; 11 import com.googlecode.javacv.cpp.opencv_core.IplImage; 12 import static com.googlecode.javacv.cpp.opencv_core.cvSize; 13 import com.googlecode.javacv.cpp.opencv_highgui; 14 import static com.googlecode.javacv.cpp.opencv_highgui.cvDestroyWindow; 15 import static com.googlecode.javacv.cpp.opencv_highgui.cvNamedWindow; 16 import com.googlecode.javacv.cpp.swscale; 17 import com.googlecode.javacv.cpp.swscale.SwsContext; 18 19 /** 20 * 21 * @author cuizhenfu@gmail.com 22 */ 23 public class DecodingH264 { 24 25 public static void main(String[] args) { 26 String filePath = "Images/butterfly.h264"; 27 28 // Register all formats and codes 29 avformat.av_register_all(); 30 avcodec.avcodec_register_all(); 31 32 // Open video file 33 avformat.AVFormatContext formatCtx = avformat.avformat_alloc_context(); 34 if (avformat.avformat_open_input(formatCtx, filePath, null, null) != 0) { 35 System.out.println("无法打开文件\n"); 36 return; 37 } 38 39 if (avformat.avformat_find_stream_info(formatCtx, (AVDictionary) null) < 0) { 40 System.out.println("Couldn't find stream information.\n"); 41 return; 42 } 43 int videoIndex = -1; 44 for (int i = 0; i < formatCtx.nb_streams(); i++) { 45 if (formatCtx.streams(i).codec().codec_type() == avutil.AVMEDIA_TYPE_VIDEO) { 46 videoIndex = i; 47 break; 48 } 49 } 50 51 if (videoIndex == -1) { 52 System.out.println("Didn't find a video stream.\n"); 53 return; 54 } 55 56 avcodec.AVCodecContext codecCtx = formatCtx.streams(videoIndex).codec(); 57 avcodec.AVCodec codec = avcodec.avcodec_find_decoder(codecCtx.codec_id()); 58 if (codec == null) { 59 System.out.println("Codec not found.\n"); 60 return; 61 } 62 63 if (avcodec.avcodec_open2(codecCtx, codec, (AVDictionary) null) < 0) { 64 System.out.println("Could not open codec.\n"); 65 } 66 67 avutil.AVFrame frame = avcodec.avcodec_alloc_frame(); 68 avutil.AVFrame frameRGB = avcodec.avcodec_alloc_frame(); 69 70 // 注意AVPicture的构造方法,参考http://blog.csdn.net/wahrlr/article/details/21970755 71 // 注意avutil.av_malloc的返回值(用Pointer代替uint8_t*) 72 int nunBytes = avcodec.avpicture_get_size(avutil.AV_PIX_FMT_RGB24, codecCtx.width(), codecCtx.height()); 73 Pointer outBuffer = avutil.av_malloc(nunBytes); 74 avcodec.avpicture_fill(new AVPicture(frameRGB), outBuffer.asByteBuffer(), avutil.AV_PIX_FMT_RGB24, codecCtx.width(), codecCtx.height()); 75 76 avformat.av_dump_format(formatCtx, 0, filePath, 0); 77 78 SwsContext img_convert_ctx = swscale.sws_getContext(codecCtx.width(), codecCtx.height(), codecCtx.pix_fmt(), codecCtx.width(), codecCtx.height(), avutil.AV_PIX_FMT_RGB24, swscale.SWS_BICUBIC, null, null, (double[])null); 79 80 AVPacket packet = new AVPacket(); 81 int y_size = codecCtx.width() * codecCtx.height(); 82 avcodec.av_new_packet(packet, y_size); 83 cvNamedWindow("butterfly.h264"); 84 IplImage showImage = opencv_core.cvCreateImage(cvSize(codecCtx.width(),codecCtx.height()), IPL_DEPTH_8U, 3); 85 while(avformat.av_read_frame(formatCtx, packet) >= 0) { 86 if(packet.stream_index() == videoIndex) { 87 IntPointer ip = new IntPointer(); 88 int ret = avcodec.avcodec_decode_video2(codecCtx, frame, ip, packet); 89 if(ret < 0) { 90 System.out.println("解码错误"); 91 return; 92 } 93 if(ip.get() != 0) { 94 swscale.sws_scale(img_convert_ctx, frame.data(), frame.linesize(), 0, codecCtx.height(), frameRGB.data(), frameRGB.linesize()); 95 96 showImage.imageData(frameRGB.data(0)); 97 showImage.widthStep(frameRGB.linesize().get(0)); 98 99 opencv_highgui.cvShowImage("butterfly.h264", showImage); 100 opencv_highgui.cvWaitKey(25); 101 } 102 } 103 avcodec.av_free_packet(packet); 104 } 105 106 showImage.release(); 107 cvDestroyWindow("butterfly.h264"); 108 avutil.av_free(frameRGB); 109 avcodec.avcodec_close(codecCtx); 110 avformat.avformat_close_input(formatCtx); 111 } 112 113 }
——————————————————————————————————
傲轩游戏网
傲轩游戏网