ijkPlayer.5 播放H264裸流

需求:websocket 接收byte[] h264裸流,傳輸?shù)絚層使用ijkplayer 播放

ffmpeg播放H264裸流
功能已實現(xiàn),為了方便,讀取本地文件做為源數(shù)據(jù),此工程亦可播放mp4之類文件
https://github.com/Malone1023/JoyPlayer

int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options);

該函數(shù)支持filename/URL,在不大改的情況下,有兩種方式可以完成播裸流的工作
1.管道文件
2.AndoidIO協(xié)議/新增URLProtocol自定義

AndoidIO之前的文章已經(jīng)介紹過,本文使用管道文件來完成

注釋openVideo()方法如下代碼,catch exception同時注釋

 String scheme = mUri.getScheme();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && mSettings.getUsingMediaDataSource() && (TextUtils.isEmpty(scheme) || scheme.equalsIgnoreCase("file"))) {
                IMediaDataSource dataSource = new FileMediaDataSource(new File(mUri.toString()));
                mMediaPlayer.setDataSource(dataSource);
            }  else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                mMediaPlayer.setDataSource(mAppContext, mUri, mHeaders);
            } else {
                mMediaPlayer.setDataSource(mUri.toString());
            }

新增setDataSourceFd()方法并且在openVideo中調(diào)用,使得調(diào)用ijk中的 setDataSource(FileDescriptor fd)方法,并調(diào)用到
ijkplayer_jni.c中的static void IjkMediaPlayer_setDataSourceFd(JNIEnv *env, jobject thiz, jint fd2)方法

String fileName = "/mnt/sdcard/yy.264";
    FileDescriptor descriptor = null;
    FileOutputStream stream;
    private void setDataSourceFd(){
        try {
            stream = new FileOutputStream(fileName);
            descriptor = stream.getFD();
           //此處只是為了調(diào)用到setDataSourceFd  并不需要實際文件
            mMediaPlayer.setDataSource(descriptor);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

2.修改ijkplayer_jni.c/IjkMediaPlayer_setDataSourceFd方法

新增:

    umask(0);
    if(mkfifo(fifoName, 0664) < 0){
        if(errno == EEXIST){
            MPTRACE("file exits\n");
        }else{    
            perror("mkfifo error");
            return -1;
        }
    }
    int fd = open(fifoName, O_RDWR);
    if(fd < 0){
        MPTRACE("open fifo error\n");
        perror("open fifo error");
        return -1;
    }

修改:

retval = ijkmp_set_data_source(mp, fifoName);

3.新增接收方法

int fd;
void ffp_write_data(FFPlayer *ffp,unsigned char * data,int len){
    if(!fd){
        fd = open(fifoName, O_WRONLY);
        if(fd < 0){
            perror("ffp_joy_write_data fifo error");
            return -1;
        }
    }
   write(fd,data,len);
}

這樣 ijkPlayer就可以支持播放h264裸流啦。

可能遇到的問題:
1.ffmpeg h264 avformat_open_input err code: -1094995529 網(wǎng)上找的時候說各種情況的,本文遇到的問題是沒打開ffmpeg對h264的支持(出現(xiàn)此問題可以先拿ffmpeg直接播該文件,能正常播放的話說明是跟我遇到的一樣)
解決辦法:
do-compile-ffmpeg.sh文件中新增如下配置,并重新編譯ijk的ffmpeg庫(執(zhí)行compile-ffmpeg.sh,同時需要編譯ijk的庫,替換)

FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-demuxer=h264"
FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-protocol=udp"
FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-protocol=264"
FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-decoder=h264"
FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-parser=h264"

FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-hwaccel=h264_vaapi"
FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-hwaccel=h264_dxva2"
FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-demuxer=mjpeg"
FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-demuxer=rtsp"
FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-demuxer=rtp"
FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-encoder=h264"

2.mkfifo Android Permission denied
在mkfifo的時候可能會出錯,原因是需要設(shè)置對應(yīng)的路徑要正確
本文使用的路徑 /data/data/com.abc/test.fifo(在安卓手機上跑)

3.java byte[] to c unsigned char* buf

static void
IjkMediaPlayer_set_joy_receive_data(JNIEnv* env ,jobject thiz,jbyteArray data, jint jlen)
{
    jbyte* bBuffer = (*env)->GetByteArrayElements(env,data,0);
    unsigned char* buf = (unsigned char*)bBuffer;
    IjkMediaPlayer *mp  = jni_get_media_player(env, thiz);
    ijkmp_set_joy_data(mp,buf,jlen);

}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容