Android,用ijkplay播放rtp流提示缺少sdp

流是电子后视镜传过来的,rtp里是h264。用ijkplay播放rtp流,出错Unable to receive RTP payload type 96 without an SDP file,如下图。意思缺少sdp 。电子后视镜开发人员用的vlc 打开个.sdp文件打开播放的。他说没问题。这.sdp文件,放在Android项目的哪里,怎么用Android ijkplay中的方法设置上去?不要c语言 的方法

img

根据您的描述,问题可能是由于您使用 IJKPlayer 播放 RTP 视频时未提供对应的 SDP 文件导致的。SDP 文件包含有关媒体流的详细信息(例如编解码器类型和参数、传输协议和端口等),没有 SDP 文件,IJKPlayer 就无法正确地解析 RTP 数据包并进行播放。

在 Android 中,您可以将 SDP 文件存储在 assets 目录下,然后使用 IjkMediaPlayer.setOption() 方法来设置 SDP 路径,示例如下:

java
IjkMediaPlayer mediaPlayer = new IjkMediaPlayer();
mediaPlayer.setDataSource("rtp://xxx.xxx.xxx.xxx:xxxxx");
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probesize", "32");
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "flush_packets", "1");
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_transport", "tcp");
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "overlay-format", "fcc-rv32");
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", "1");
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", "48");
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max_cached_duration", "3000");
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "infbuf", "1");
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_flags", "prefer_tcp");
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzeduration", "2000000");
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_timeout", "2000000");
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "max_cached_audio_duration", "10");
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "sync", "video");
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "sdp_file", "sdcard/video.sdp");
mediaPlayer.prepareAsync();
注意,上述代码中的 sdcard/video.sdp 应替换为实际的 SDP 文件路径。另外,还需要在 AndroidManifest.xml 文件中添加以下权限:

xml

通过以上设置,您应该能够在 IJKPlayer 中正确载入和播放 RTP 视频流了。

Android ijkplayer播放rtsp直播流
可以借鉴下
https://blog.csdn.net/ydh7611/article/details/128196374

跟着重新操作

// 如果是rtsp协议,可以优先用tcp(默认是用udp)
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_transport", "tcp");
// 设置播放前的探测时间 1,达到首屏秒开效果
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzeduration", 1);
// 设置播放前的最大探测时间 (100未测试是否是最佳值)
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzemaxduration", 100L);
// 每处理一个packet之后刷新io上下文
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "flush_packets", 1L);
// 需要准备好后自动播放
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 0);
// 是否开启预缓冲,一般直播项目会开启,达到秒开的效果,不过带来了播放丢帧卡顿的体验
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "packet-buffering",  0);
 
String url = mUri.toString();
if (!TextUtils.isEmpty(url) && url.contains("rtsp://")) {  // 如果 rtmp 的协议, 修改 size 后会没有声音
// 播放前的探测Size,默认是1M, 改小一点会出画面更快
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probesize", 1024); //1024L)
}
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "http-detect-range-support", 0);
// 设置是否开启环路过滤: 0开启,画面质量高,解码开销大,48关闭,画面质量差点,解码开销小
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 48L);
// 跳过帧 ??
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_frame", 8);
// 视频帧处理不过来的时候丢弃一些帧达到同步的效果
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", 1);
 

https://blog.csdn.net/ydh7611/article/details/128196374

根据您提供的信息,您想在 Android 项目中使用 IJKPlayer 播放带有 RTP 流的 H264 视频,并解决缺少 SDP 文件的问题。以下是可能的解决方案:

  1. 获取 SDP 文件:首先,您需要获得带有正确 SDP 文件的视频流。根据您提到的电子后视镜开发人员使用 VLC 播放时没有问题,可以尝试联系他们获取 SDP 文件或者了解 SDP 文件的内容和格式。

  2. 将 SDP 文件添加到 Android 项目:一旦您获得了正确的 SDP 文件,您可以将其添加到 Android 项目中的适当位置。您可以将 SDP 文件放置在 assets 文件夹下,或者根据项目结构和需要放置在其他合适的位置。

  3. 使用 IJKPlayer 设置 SDP 文件:使用 IJKPlayer 播放器,您可以使用以下方法来设置 SDP 文件:

IjkMediaPlayer ijkMediaPlayer = new IjkMediaPlayer();
String sdpFilePath = "file:///android_asset/your_sdp_file.sdp"; // 根据实际情况设置 SDP 文件的路径
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_transport", "tcp");
ijkMediaPlayer.setDataSource(sdpFilePath);
ijkMediaPlayer.prepareAsync();

上述代码中,您需要将 your_sdp_file.sdp 替换为实际的 SDP 文件名,并确保 SDP 文件的路径是正确的。这样,IJKPlayer 将使用指定的 SDP 文件来播放 RTP 流。

请注意,以上代码仅是示例,您可能需要根据您的项目结构和需求进行相应的调整。

希望以上信息对您有所帮助,祝您成功解决播放 RTP 流缺少 SDP 文件的问题!

1、在Android应用程序的assets目录下创建一个.sdp文件
2、然后,使用AssetManager类来读取该文件并将其传递给IjkMediaPlayer

事例代码你网上搜索,一搜一大把,或者直接看ijkplayer的demo
我给个事例代码,大概就这么个意思


public static final String ASSET_SDP_FILE = "example.sdp"; // 请将此值更改为实际的.sdp文件名

...

AssetManager assetManager = getAssets();
String sdpString = null;
try {
    InputStream is = assetManager.open(ASSET_SDP_FILE);
    int size = is.available();
    byte[] buffer = new byte[size];
    is.read(buffer);
    is.close();
    sdpString = new String(buffer, "UTF-8");
} catch (IOException e) {
    e.printStackTrace();
}

if (sdpString != null) {
    IjkMediaPlayer player = new IjkMediaPlayer();
    player.setDataSource(sdpString);
    ...
}

为了解决这个问题,你需要找到包含SDP(Session Description Protocol)文件的SDP(Session Description Protocol)文件。通常情况下,SDP文件会包含有关音频、视频等多媒体元素的比特流信息,以及与这些比特流相关的元数据(如音频格式、视频帧率等)。

你可以将SDP文件保存在Android项目的资源文件夹中,例如res/sdp文件夹。然后,在Android设备的设置中,你可以找到“声音”或“视频”选项,然后选择“使用默认媒体文件”。这将加载SDP文件,并允许Android设备解析该文件以播放音频或视频。

对于使用ijkplay播放rtp流的问题,你需要在ijkplay中设置正确的SDP文件,具体步骤可以参考文档中的示例代码,该文档提供了如何在ijkplay中设置SDP文件的方法。

另外,需要指出的是,SDP文件通常需要手动编写,并且需要与RTP协议的元数据匹配。因此,需要仔细阅读SDP文件的元数据,确保其与RTP协议的匹配。如果SDP文件中的元数据不正确,将无法正确播放音频或视频。

希望这些步骤能有所帮助。如果还有问题,请继续提问。

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
首先,需要了解SDP(Session Description Protocol)是一种描述多媒体会话的协议,主要用于实现网络多媒体会话,比如音频、视频等。而且,SDP和H.264并没有必然联系,SDP用于描述多媒体会话,而H.264是一种多媒体编码格式,两者目的和内容是不同的。

对于你的问题,错误提示"Unable to receive RTP payload type 96 without an SDP file"说明在接收RTP数据时,缺少SDP文件,需要先解析SDP文件,从而获取流媒体服务端的参数设置等信息,才能正确解析RTP数据并播放。

针对你的问题,你需要将传输的SDP文件保存到手机SD卡或应用目录下,然后在程序中读取SDP文件并解析,然后再使用IjkPlayer来播放RTP流。

以下是解析SDP文件并播放RTP流的示例代码:

import android.media.AudioFormat;
import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import tv.danmaku.ijk.media.player.IjkMediaPlayer;

public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {
    private static final String TAG = "MainActivity";
    private SurfaceView mSurfaceView;
    private SurfaceHolder mSurfaceHolder;
    private MediaPlayer mMediaPlayer;
    private IjkMediaPlayer mIjkMediaPlayer;
    private ExecutorService mExecutorService;
    private boolean mIsPlaying = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mSurfaceView = findViewById(R.id.surface_view);
        mSurfaceHolder = mSurfaceView.getHolder();
        mSurfaceHolder.addCallback(this);
        mExecutorService = Executors.newSingleThreadExecutor();
        //初始化IjkMediaPlayer
        mIjkMediaPlayer = new IjkMediaPlayer();
    }

    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        //SurfaceView被创建后,启动播放流
        startPlay();
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        //SurfaceView被销毁后,停止播放流
        stopPlay();
    }

    //启动播放流
    private void startPlay() {
        //读取SDP文件
        String sdpFilePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "test.sdp";
        File sdpFile = new File(sdpFilePath);
        if (sdpFile.exists()) {
            try {
                FileInputStream fis = new FileInputStream(sdpFile);
                BufferedReader reader = new BufferedReader(new InputStreamReader(fis, "UTF-8"));
                StringBuffer buffer = new StringBuffer();
                String line;
                while ((line = reader.readLine()) != null) {
                    buffer.append(line);
                    buffer.append("\n");
                }
                reader.close();
                fis.close();
                String sdpContent = buffer.toString();
                //解析SDP文件,获取流媒体参数设置等信息
                //TODO: 在这里解析SDP文件,

                //然后使用IjkMediaPlayer播放RTP流
                //设置播放地址和SurfaceHolder
                String playUrl = "rtp://127.0.0.1:8888";//RTP流地址
                mIjkMediaPlayer.setDataSource(playUrl);
                mIjkMediaPlayer.setSurface(mSurfaceHolder.getSurface());
                //异步准备
                mIjkMediaPlayer.prepareAsync();
                mIjkMediaPlayer.setOnPreparedListener(new IjkMediaPlayer.OnPreparedListener() {
                    @Override
                    public void onPrepared(IjkMediaPlayer ijkMediaPlayer) {
                        //准备完成后,开始播放
                        mIsPlaying = true;
                        mIjkMediaPlayer.start();
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            Toast.makeText(this, "SDP文件不存在", Toast.LENGTH_SHORT).show();
        }
    }

    //停止播放流
    private void stopPlay() {
        if (mIsPlaying) {
            mIjkMediaPlayer.stop();
            mIsPlaying = false;
        }
    }
}

需要注意的是,以上示例代码仅作为演示用途,实际使用中还需要根据SDP文件的格式和内容进行解析。
如果我的回答解决了您的问题,请采纳!

以下答案由GPT-4.0Plus大模型与博主A努力中.......共同编写:
根据您的描述,ijkplay无法播放RTP流是因为没有SDP文件提供流信息,需要设置SDP文件才能正常播放。
在Android中,使用ijkplay播放RTP流的步骤如下:

  1. 将SDP文件assets目录下,例如:sdp/stream.sdp。
  2. 读取SDP文件内容到字符串。可以用:
java
String sdp = readAssetFile("sdp/stream.sdp");

  1. 构造IjkMediaPlayer,设置SDP信息。
java
IjkMediaPlayer ijkMediaPlayer = new IjkMediaPlayer();
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "sdp_file", sdp);

  1. 设置RTP流URL,格式为:
    rtp://@ip:port
    例如:
java
ijkMediaPlayer.setDataSource("rtp://@192.168.1.10:5000");

  1. 准备和开始播放等正常的播放步骤。
    所以,您需要将电子后视镜提供的SDP文件放在Android项目的assets目录下,读取成字符串,在创建IjkMediaPlayer对象时调用setOption()方法设置"sdp_file"选项为该SDP字符串。
    然后设置RTP流URL开始播放,ijkplay就可以正常播放RTP流了。
    完整例子代码如下:
java
String sdp = readAssetFile("sdp/stream.sdp");
IjkMediaPlayer ijkMediaPlayer = new IjkMediaPlayer();
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "sdp_file", sdp);  
ijkMediaPlayer.setDataSource("rtp://@192.168.1.10:5000");
ijkMediaPlayer.prepareAsync();
ijkMediaPlayer.start();