首页 > 代码库 > 用JavaCV改写“100行代码实现最简单的基于FFMPEG+SDL的视频播放器 ”

用JavaCV改写“100行代码实现最简单的基于FFMPEG+SDL的视频播放器 ”

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 }