使用Android MediaCodec进行视频转码

问题描述 投票:0回答:1

与Android MediaCodec斗争,我正在寻找一种简单的方法来更改Android中视频文件的分辨率。

目前,我正在尝试一种单线程转码方法,该方法可以逐步完成所有工作,因此我可以很好地理解它,并且从高层次看,它如下所示:

public void TranscodeVideo()
{
    // Extract
    MediaTrack[] tracks = ExtractTracks(InputPath);

    // Decode
    MediaTrack videoTrack = tracks.Where(o => o.IsVideo).FirstOrDefault();
    MediaTrack rawVideoTrack = DecodeTrack(videoTrack);

    // Edit?
    // ResizeVideoTrack(rawVideoTrack);

    // Encode
    MediaFormat newFormat = MediaHelper.CreateVideoOutputFormat(videoTrack.Format);
    MediaTrack encodeVideodTrack = EncodeTrack(rawVideoTrack , newFormat);

    // Muxe
    encodeVideodTrack.Index = videoTrack.Index;
    tracks[Array.IndexOf(tracks, videoTrack)] = encodeVideodTrack;
    MuxeTracks(OutputPath, tracks);
}

提取效果很好,返回仅包含音频的轨道和仅包含视频的轨道。 Muxing可以很好地结合之前的两个曲目。解码有效,但我不知道如何检查,轨道上的原始帧比原始帧重得多,因此我认为这是正确的。

问题

编码器输入缓冲区的大小小于原始帧的大小,并且还与编码配置的格式有关,因此我认为我需要以某种方式调整帧的大小,但是我没有发现任何有用的东西。我是对的吗?我想念什么吗?调整原始视频帧大小的方法是什么?有什么帮助吗? :S

PD

  • [也许您会注意到我正在使用C#(Xamarin.Android)以获得更多乐趣。但是底层的API当然是Java。
  • 我使用的是ByteBuffers,而不是Surfaces,因为它似乎更容易。我将是使用曲面的下一步,欢迎任何建议。
  • 我知道单线程处理效率很低,但是很简单。将解码器输出缓冲区连接到编码器输入缓冲区的下一步是下一步。
  • 我浏览了PhilLabGrafikaBigflake示例,但对我来说似乎没有什么用处。
  • 避免在Android上使用ffmpeg。

谢谢大家的时间。

java android mediacodec
1个回答
0
投票
将此添加到应用程序根目录的build.gradle

allprojects { repositories { ... maven { url 'https://jitpack.io' } } }

将此添加到从属应用程序的build.gradle

dependancies {
    ...
    implementation 'com.github.masterwok:libvlc-android-sdk:3.0.13'
}

这里是将RTSP流作为活动加载的示例

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.camera_stream_layout);


    // Get URL
    this.rtspUrl = getIntent().getExtras().getString(RTSP_URL);
    Log.d(TAG, "Playing back " + rtspUrl);

    this.mSurface = findViewById(R.id.camera_surface);
    this.holder = this.mSurface.getHolder();

    ArrayList<String> options = new ArrayList<>();
    options.add("-vvv"); // verbosity
    //Add vlc transcoder options here

    this.libvlc = new LibVLC(getApplicationContext(), options);
    this.holder.setKeepScreenOn(true);
    //this.holder.setFixedSize();

    // Create media player
    this.mMediaPlayer = new MediaPlayer(this.libvlc);
    this.mMediaPlayer.setEventListener(this.mPlayerListener);

    // Set up video output
    final IVLCVout vout = this.mMediaPlayer.getVLCVout();
    vout.setVideoView(this.mSurface);

    //Set size of video to fit app screen
    DisplayMetrics displayMetrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);

    ViewGroup.LayoutParams videoParams = this.mSurface.getLayoutParams();
    videoParams.width = displayMetrics.widthPixels;
    videoParams.height = displayMetrics.heightPixels;

    vout.setWindowSize(videoParams.width, videoParams.height);
    vout.addCallback(this);
    vout.attachViews();

    final Media m = new Media(this.libvlc, Uri.parse(this.rtspUrl));
    //Use this to add transcoder options m.addOption("vlc transcode options here");
    this.mMediaPlayer.setMedia(m);
    this.mMediaPlayer.play();
}

这里是vlc转码器选项的文档

https://wiki.videolan.org/Documentation:Streaming_HowTo_New/

这里是我用来对RTSP进行转码的选项的示例

private static String[] getStreamOptions(String port, String name) { return new String[]{ ":no-audio", ":sout-deinterlace-mode=Disabled", ":sout=#transcode{vcodec=theo,vb=800,scale=0.25,scodec=none,acodec=none,fps=30}", ":sout-mux-caching=15", ":sout-http-caching=10", ":no-sout-rtp-sap", ":no-sout-standard-sap", ":no-sout-keep", ":no-sout-all", ":no-spu" }; }

© www.soinside.com 2019 - 2024. All rights reserved.