zoukankan      html  css  js  c++  java
  • 用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("无法打开文件
    ");
     36             return;
     37         }
     38 
     39         if (avformat.avformat_find_stream_info(formatCtx, (AVDictionary) null) < 0) {
     40             System.out.println("Couldn't find stream information.
    ");
     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.
    ");
     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.
    ");
     60             return;
     61         }
     62 
     63         if (avcodec.avcodec_open2(codecCtx, codec, (AVDictionary) null) < 0) {
     64             System.out.println("Could not open codec.
    ");
     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 }
  • 相关阅读:
    WebService中Dataset的压缩序列化和解压反序列化(DataSetSurrogate的使用)
    IOleControl 代码一,测试有问题,备忘
    关于Stream和byte之间的转换 .
    webbrowser 实现IOleControl接口2
    JavaScropt获取网页、浏览器、屏幕高度和宽度
    Oracle默认的用户名和密码
    window.showModalDialog()用法及注意事项
    Android1.6开发环境配置
    string与stream互相转换
    GirdView实现单选、FooterTemplate实现新建和PagerTemplate实现分页
  • 原文地址:https://www.cnblogs.com/cuizhf/p/3702513.html
Copyright © 2011-2022 走看看