【问题标题】:Video processing on android, how to write MPEG4 data into a MP4 file?android上的视频处理,如何将MPEG4数据写入MP4文件?
【发布时间】:2012-11-06 14:58:36
【问题描述】:

如何在 android 中将 MPEG4 数据写入(包装)到 MP4 文件中?

我正在android平台上进行某种视频处理,但我不知道如何将处理后的数据(以某种标准编码,如MPEG4)写回mp4等视频文件。我认为最好使用 API 来执行此操作,但我找不到需要的 API。

有人有什么想法吗?

【问题讨论】:

    标签: android containers video-processing mpeg-4


    【解决方案1】:
    // Full working solution:
    // 1. Add to app/build.gradle -> implementation 'com.googlecode.mp4parser:isoparser:1.1.22'
    // 2. Add to your code:
    try {
        File mpegFile = new File(); // ... your mpeg file ;
        File mp4file = new File(); // ... you mp4 file;
        DataSource channel = new FileDataSourceImpl(mpegFile);
        IsoFile isoFile = new IsoFile(channel);
        List<TrackBox> trackBoxes = isoFile.getMovieBox().getBoxes(TrackBox.class);
        Movie movie = new Movie();
        for (TrackBox trackBox : trackBoxes) {
            movie.addTrack(new Mp4TrackImpl(channel.toString()
                    + "[" + trackBox.getTrackHeaderBox().getTrackId() + "]", trackBox));
        }
        movie.setMatrix(isoFile.getMovieBox().getMovieHeaderBox().getMatrix());
        Container out = new DefaultMp4Builder().build(movie);
    
        FileChannel fc = new FileOutputStream(mp4file).getChannel();
    
        out.writeContainer(fc);
        fc.close();
        isoFile.close();
        channel.close();
    
        Log.d("TEST", "file mpeg " + mpegFile.getPath() + " was changed to " + mp4file.getPath());
    
        // mpegFile.delete(); // if you wish!
    
    } catch (Exception e) {
        e.printStackTrace();
    }
    
    // It's all! Happy coding =)
    

    【讨论】:

      【解决方案2】:

      mp4parser 只能使用完全创建的帧流,你不能用它逐帧写入。如果我错了,请纠正我

      H264TrackImpl h264Track = new H264TrackImpl(new BufferedInputStream(some input stream here));
      Movie m = new Movie();
      IsoFile out = new DefaultMp4Builder().build(m);
      File file = new File("/sdcard/encoded.mp4");
      FileOutputStream fos = new FileOutputStream(file);
      out.getBox(fos.getChannel());
      fos.close();
      

      现在我们需要知道如何在那里逐帧写入。

      【讨论】:

        【解决方案3】:

        您的问题没有 100% 的意义。 MPEG-4 是一系列规范(所有 ISO/IEC 14496-*),MP4 是 ISO/IEC 14496-14 中指定的文件格式。

        如果您想从原始 AAC 和/或 H264 流创建 MP4 文件,我建议使用 mp4parser 库。有一个example 展示了如何将 AAC 和 H264 混合到 MP4 文件中。

        【讨论】:

          【解决方案4】:

          OpenCV 对这份工作来说可能有点过分了,但我想不出比这更容易的事情了。 OpenCV 是一个为 C、C++ 和 Python 提供 API 的计算机视觉库。

          由于您使用的是 Android,因此您必须为 OpenCV 下载一个名为 JavaCV 的 Java 包装器,它是一个第 3 方 API。我用instructions to install OpenCV/JavaCV on Windows 写了一篇小文章并将它与Netbeans 一起使用,但最后你必须搜索一个教程,说明如何为Android 平台安装OpenCV/JavaCV。

          This is a C++ example 显示如何打开输入视频并将帧复制到输出文件。但是由于您使用的是 Android,因此使用 JavaCV 的示例会更好,因此以下代码会从输入视频中复制帧并将其写入名为 out.mp4 的输出文件中:

          package opencv_videowriter;
          
          import static com.googlecode.javacv.cpp.opencv_core.*;
          import static com.googlecode.javacv.cpp.opencv_imgproc.*;
          import static com.googlecode.javacv.cpp.opencv_highgui.*;
          
          public class OpenCV_videowriter 
          {
              public static void main(String[] args) 
              {
                  CvCapture capture = cvCreateFileCapture("cleanfish47.mp4");
                  if (capture == null)
                  {
                      System.out.println("!!! Failed cvCreateFileCapture");
                      return;
                  }
          
                  int fourcc_code = (int)cvGetCaptureProperty(capture, CV_CAP_PROP_FOURCC);
                  double fps = cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);
                  int w = (int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
                  int h = (int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);
          
                  CvVideoWriter writer = cvCreateVideoWriter("out.mp4",       // filename
                                                              fourcc_code,    // video codec
                                                              fps,            // fps
                                                              cvSize(w, h),   // video dimensions
                                                              1);             // is colored
                  if (writer == null) 
                  {
                      System.out.println("!!! Failed cvCreateVideoWriter");
          
                      return;
                  }
          
          
                  IplImage captured_frame = null;        
                  while (true)
                  {
                      // Retrieve frame from the input file
                      captured_frame = cvQueryFrame(capture);
                      if (captured_frame == null)
                      {
                          System.out.println("!!! Failed cvQueryFrame");
                          break;
                      }
          
          
                      // TODO: write code to process the captured frame (if needed)
          
          
                      // Store frame in output file
                      if (cvWriteFrame(writer, captured_frame) == 0) 
                      {
                          System.out.println("!!! Failed cvWriteFrame");
                          break;
                      }
          
                  }
          
                  cvReleaseCapture(capture);
                  cvReleaseVideoWriter(writer);        
              }
          }
          

          注意:OpenCV 中的帧按BGR 顺序存储像素。

          【讨论】:

          猜你喜欢
          • 2011-11-01
          • 2018-10-15
          • 2012-12-28
          • 1970-01-01
          • 1970-01-01
          • 2011-11-07
          • 1970-01-01
          • 2015-06-25
          • 1970-01-01
          相关资源
          最近更新 更多