【发布时间】:2012-11-06 14:58:36
【问题描述】:
如何在 android 中将 MPEG4 数据写入(包装)到 MP4 文件中?
我正在android平台上进行某种视频处理,但我不知道如何将处理后的数据(以某种标准编码,如MPEG4)写回mp4等视频文件。我认为最好使用 API 来执行此操作,但我找不到需要的 API。
有人有什么想法吗?
【问题讨论】:
标签: android containers video-processing mpeg-4
如何在 android 中将 MPEG4 数据写入(包装)到 MP4 文件中?
我正在android平台上进行某种视频处理,但我不知道如何将处理后的数据(以某种标准编码,如MPEG4)写回mp4等视频文件。我认为最好使用 API 来执行此操作,但我找不到需要的 API。
有人有什么想法吗?
【问题讨论】:
标签: android containers video-processing mpeg-4
// 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 =)
【讨论】:
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();
现在我们需要知道如何在那里逐帧写入。
【讨论】:
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 顺序存储像素。
【讨论】: