sannies / mp4parser

A Java API to read, write and create MP4 files
Apache License 2.0
2.76k stars 571 forks source link

Android MP4Parser cannot play video #102

Open hoang89yenthe opened 9 years ago

hoang89yenthe commented 9 years ago

I'm attempting to append a simple, 3 second outro video to an existing video using MP4Parser, but for some reason I cannot play the video after the merge happens. I'm getting the infamous "Sorry, this video cannot be played" error when trying to play the video from my gallery. Anyone have similar experience doing this? I'm testing on an HTC One running 4.4 KitKat

Here's my method to merge to .mp4 clips into a single one, taken from the AppendExample from MP4Parser itself.

private void createFinalOutputVideo() {

CameraHelper helper = new CameraHelper(this);
File outFile = helper.getOutputMediaFile(CameraHelper.MEDIA_TYPE_VIDEO);

try {

    Movie[] movies = new Movie[2];
    movies[0] = MovieCreator.build(mVideoPath);
    movies[1] = MovieCreator.build(mOutroPath);

    Log.d("ShareActivity", "Video 1 path " + mVideoPath);
    Log.d("ShareActivity", "Video 2 path " + mOutroPath);

    List<Track> videoTracks = new LinkedList<Track>();
    List<Track> audioTracks = new LinkedList<Track>();

    for (Movie m : movies) {
        for (Track t : m.getTracks()) {

            if (t.getHandler().equals("soun")) {
                audioTracks.add(t);
            }

            if (t.getHandler().equals("vide")) {
                videoTracks.add(t);
            }
        }
    }

    Movie result = new Movie();
    if (audioTracks.size() > 0) {
        result.addTrack(new AppendTrack(audioTracks.toArray(new Track[audioTracks.size()])));
    }
    if (videoTracks.size() > 0) {
        result.addTrack(new AppendTrack(videoTracks.toArray(new Track[videoTracks.size()])));
    }

    Container out = new DefaultMp4Builder().build(result);

    FileChannel fc = new RandomAccessFile(String.format(outFile.getPath()), "rw").getChannel();

    out.writeContainer(fc);
    fc.close();

    Toast.makeText(this, "Merge successful! Output path is " + outFile.getAbsolutePath(), Toast.LENGTH_SHORT).show();

} catch (IOException e) {
    e.printStackTrace();
    Toast.makeText(this, "Error merging videos!", Toast.LENGTH_SHORT).show();
}

} Has anyone ever had this issue with MP4Parser? Would be great if Sebastian could chime in here.

sannies commented 9 years ago

Could you please make the two input files available? And does the output video play on other players such as VLC?

blackvvine commented 9 years ago

I have the same problem here. The file gets created, and can be played on my laptop using VLC But android VideoView doesn't play it. any ideas why?

sannies commented 9 years ago

Do you get any error messages? Or could you send me an example project that tries to play a file?

2015-10-22 15:32 GMT+02:00 blackvvine notifications@github.com:

I have the same problem here. The file gets created, and can be played on my laptop using VLC But android VideoView doesn't play it. any ideas why?

— Reply to this email directly or view it on GitHub https://github.com/sannies/mp4parser/issues/102#issuecomment-150224526.

blackvvine commented 9 years ago

This is the code I use for muxing video and audio:

@Override protected File doInBackground(Void... params) {

        H264TrackImpl h264Track = null;
        AACTrackImpl aacTrack = null;
        Track voiceLessTrack = null;
        Movie undubbed = null;

        try {

            undubbed = MovieCreator.build(new FileDataSourceImpl(new File(data.getStoredFileAbsPath(context))));
            voiceLessTrack = undubbed.getTracks().get(0);
            undubbed.getTracks().clear();
            undubbed.getTracks().add(voiceLessTrack);

            logd("XXXXXXx mux:", undubbed.getTracks().size());

            // create file reference to un-dubbed video file
            File videoFile = new File(data.getStoredFileAbsPath(context));

            logd("videofile isfile", videoFile.isFile(), "name", videoFile.getName());

            // create AAC/H.264 tracks
            //h264Track = new H264TrackImpl(new FileDataSourceImpl(videoFile));
            aacTrack = new AACTrackImpl(new FileDataSourceImpl(audioFile));

            /*IsoFile isoFile = new IsoFile(new FileDataSourceImpl(videoFile));
            TrackBox t = new TrackBox();
            Mp4TrackImpl mp4track = new Mp4TrackImpl(isoFile.getMovieBox().getBoxes().get(0), isoFile);*/

        } catch (IOException e) {
            e.printStackTrace();

            // emit event
            MuxErrorEvent event = new MuxErrorEvent(id, e, "Error h.264/aac creating tracks");
            VideoEventManager.getBus().post(event);

            // terminate
            return null;
        }

        // create mux project file
        /*Movie movie = undubbed;*/
        Movie movie = new Movie();
        movie.addTrack(voiceLessTrack);
        movie.addTrack(aacTrack);

        // make output file
        String name = clip.title.replace(" ", "_") + "-" + new SimpleDateFormat("yyyy-MM-dd-EEE-HH:mm:ss.SSS").format(new Date(System.currentTimeMillis())) + ".mp4";
        String fullPath = String.format("%s%s%s",
                Environment.getExternalStorageDirectory().getAbsolutePath(),
                ClientInfo.VIDEO_DUB_DIR,
                name
        );
        File outFile = new File(fullPath);
        FileChannel fc = null;

        try {

            // checks if output directory exists, creates it if not
            FileUtils.checkDubDir(context);

            // open file
            fc = new FileOutputStream(outFile).getChannel();

        } catch (IOException e) {
            e.printStackTrace();

            // emit event
            MuxErrorEvent event = new MuxErrorEvent(id, e, "Output file open error");
            VideoEventManager.getBus().post(event);

            // TODO damage control

            // terminate
            return null;
        }

        // feed movie project into MP4Builder
        Container mp4file = new DefaultMp4Builder().build(movie);

        try {

            // create the mp4 file
            mp4file.writeContainer(fc);
            fc.close();

        } catch (IOException e) {
            e.printStackTrace();

            // emit error
            MuxErrorEvent event = new MuxErrorEvent(id, e, "MP4 creation failure");
            VideoEventManager.getBus().post(event);

            // TODO damage control

            // terminate
            return null;
        }

        Log.d(TAG, "doInBackground ");

        // create and save dub info
        VideoDubData data = new VideoDubData(clip, outFile);
        data.save();

        // emit event
        MuxSuccessEvent event = new MuxSuccessEvent(id, data);
        VideoEventManager.getBus().post(event);

        return outFile;

    } // end doInBackground()

the audio is AAC recorded using android AudioCapture and the video is this: http://download.openbricks.org/sample/H264/big_buck_bunny_480p_H264_AAC_25fps_1800K_short.MP4

Thanks

blackvvine commented 9 years ago

The problem is that when I send the output using an intent to other applications, they also don't recognize it as video

sannies commented 9 years ago

How do I reproduce the problem?

  1. Mux an MP4 file
  2. Open it. How? Which player?

Could you perhaps send me the logcat of what happens when you try to open it and it fails?

2015-10-22 15:55 GMT+02:00 blackvvine notifications@github.com:

The problem is that when I send the output using an intent to other applications, they also don't recognize it as video

— Reply to this email directly or view it on GitHub https://github.com/sannies/mp4parser/issues/102#issuecomment-150230589.

blackvvine commented 9 years ago

Yes... If I try to open it with the default player or play it with a VideoView, it says it's not supported, and If I share it to say, Telegram Messenger, It sends it as a normal binary file and not a video.

here's the error log of the VideoView which tries to open it:

10-22 17:54:42.737 27143-27143/com.rahafilm.doremi.android W/VideoView﹕ Unable to open content: file:///storage/emulated/0/dubbed/Bunny-2015-10-22-Thu-17%3A54%3A42.036 java.io.IOException: setDataSource failed.: status=0x80000000 at android.media.MediaPlayer.nativeSetDataSource(Native Method) at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1061) at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1022) at android.media.MediaPlayer.setDataSource(MediaPlayer.java:974) at android.widget.VideoView.openVideo(VideoView.java:353) at android.widget.VideoView.access$2200(VideoView.java:72) at android.widget.VideoView$7.surfaceCreated(VideoView.java:664) at android.view.SurfaceView.updateWindow(SurfaceView.java:579) at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:176) at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:847) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1985) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1077) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5845) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767) at android.view.Choreographer.doCallbacks(Choreographer.java:580) at android.view.Choreographer.doFrame(Choreographer.java:550) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5274) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:909) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:704)

blackvvine commented 9 years ago

OMG I'm so sorry, The problem was much more stupid than I thought, I had put : signs in the file name and it had been URL coded. that's why it didn't play properly. Sorry for your time and the inconvenience and thanks you very much.

sannies commented 9 years ago

no problem. I didn't spend any time on it case the error message does not really point anywhere

2015-10-22 17:43 GMT+02:00 blackvvine notifications@github.com:

OMG I'm so sorry, The problem was much more stupid than I thought, I had put : signs in the file name and it had been URL coded. that's why it didn't play properly. Sorry for your time and the inconvenience and thanks you very much.

— Reply to this email directly or view it on GitHub https://github.com/sannies/mp4parser/issues/102#issuecomment-150266942.

sandeep-agrawal commented 8 years ago

Archive.zip VidepMerger.zip I am trying to split 2 videoes in multiple clips and merge them in 1 video and output video can't play. I have attached the complete project and sample video. I would appreciate if you take some time and provide me the solution for it.

MounicaKodela commented 7 years ago

I am using the same code. If i merge the same files it is working. If i merge two different files, it is creating a file but could not open that file.

please help me