当前位置: 首页 > 知识库问答 >
问题:

使用ffmpeg和H264编解码器创建的视频不能在android上播放:播放器说它不是divx文件

井疏珂
2023-03-14

我已经创建了一个视频从图像使用ffmpeg和H264编解码器在C。我可以运行视频使用第三方播放器(V播放器)在android设备上。但是本机播放器不播放视频。它说该文件不是Divx文件。下面是我用来从图像创建视频的代码:

JNIEXPORT void Java_com_canvasm_mediclinic_VideoGenerator_generate(JNIEnv *pEnv, jobject pObj,jobjectArray stringArray,int famerate,int width,int height,jstring videoFilename)
{
    AVCodec *codec;
    AVCodecContext *c= NULL;
    //int framesnum=5;
    int i,looper, out_size, size, x, y,j;
    int ret,pts,got_pkt_ptr;

    int imagecount= (*pEnv)->GetArrayLength(pEnv, stringArray); 
    int retval=-10;
    uint8_t endcode[]={0,0,1,0xb7};
    AVPacket outpacket;
    FILE *f;
    AVFrame *picture,*encoded_avframe;  
    jbyte *raw_record;
    char logdatadata[100];
    int returnvalue = -1,numBytes =-1;
    const char *gVideoFileName = (char *)(*pEnv)->GetStringUTFChars(pEnv, videoFilename, NULL); 
        /* find the mpeg1 video encoder */  
    codec = avcodec_find_encoder_by_name("libx264");
    if (!codec) {
        __android_log_write(ANDROID_LOG_INFO, "record","codec not found");
        exit(1);
    }
    c= avcodec_alloc_context();
    c->bit_rate = 500000;
    c->width = width;
    c->height = height;
    c->time_base= (AVRational){1,famerate};
    c->gop_size = 12; // emit one intra frame every ten frames
    c->max_b_frames=1;
    c->pix_fmt = PIX_FMT_YUV420P;
    c->codec_type = AVMEDIA_TYPE_VIDEO;
    c->codec_id = codec->id;
    c->max_b_frames = 0;
    c->me_range = 16;
    c->max_qdiff = 4;
    c->qmin = 10;
    c->qmax = 26;
    c->qcompress = 0.6;
    c->trellis=0;
    c->level = 30;
    c->refs = 5;
    c->coder_type = 0;
    c->scenechange_threshold = 0;
    //new
    c->flags|=CODEC_FLAG_LOOP_FILTER;//new  
    c->scenechange_threshold = 40; //new
    c-> rc_buffer_size = 0;
    c->gop_size=250; //new
    c->max_b_frames=1;//new
    c->me_method=7;
    c->me_cmp|= 1;
    c->me_subpel_quality = 6;
    c->qmax=51;
    c->keyint_min=25;
    av_opt_set(c->priv_data,"subq","6",0);
    av_opt_set(c->priv_data,"crf","20.0",0);
    av_opt_set(c->priv_data,"weighted_p_pred","0",0);
    av_opt_set(c->priv_data,"profile","baseline",AV_OPT_SEARCH_CHILDREN);
    av_opt_set(c->priv_data,"preset","medium",0);
    av_opt_set(c->priv_data,"tune","zerolatency",0);
    av_opt_set(c->priv_data,"x264opts","rc-lookahead=0",0);




    /* open it */
    retval = avcodec_open(c, codec);
    if ( retval < 0)
    {
    __android_log_write(ANDROID_LOG_INFO, "record","could not open codec");
        exit(1);
    }   
    f = fopen(gVideoFileName, "ab");

    if (!f) {
        __android_log_write(ANDROID_LOG_INFO, "record","could not open video file");
        exit(1);
    }
    pts = 0;
    for(i=0;i<=imagecount;i++) {


        jboolean isCp;
        int progress = 0;
        float temp;

        jstring string;
        if(i==imagecount)
            string = (jstring) (*pEnv)->GetObjectArrayElement(pEnv, stringArray,
                      imagecount-1);
        else
            string = (jstring) (*pEnv)->GetObjectArrayElement(pEnv, stringArray, i);

        const char *rawString = (*pEnv)->GetStringUTFChars(pEnv, string, &isCp);        
        picture = OpenImage(rawString,width,height,i);      
        av_init_packet(&outpacket);
        fflush(stdout);


        {               
            picture->pts=i ;//c->frame_number;          
            do{
                out_size = avcodec_encode_video2(c, &outpacket, 
                                 picture,&got_pkt_ptr);             
            }while(!got_pkt_ptr);   

        }

        returnvalue = fwrite(outpacket.data, 1, outpacket.size, f);
        av_free_packet(&outpacket); 

    }


    /* get the delayed frames */
    for(got_pkt_ptr =1; got_pkt_ptr; i++) {
        fflush(stdout);
        avcodec_encode_video2(c, &outpacket, NULL,&got_pkt_ptr);

        if(got_pkt_ptr)
        {
            fwrite(outpacket.data, 1, outpacket.size, f);
            av_free_packet(&outpacket);
        }   
    }

    fwrite(endcode,1,sizeof(endcode),f);
    fclose(f);  
    avcodec_close(c);
    av_free(c);     
}
AVFrame* OpenImage(const char* imageFileName,int w,int h,int index)
{
    AVFrame *pFrame;
    AVCodec *pCodec ;
    AVFormatContext *pFormatCtx = NULL;
    AVCodecContext *pCodecCtx;
    uint8_t *buffer;
    int frameFinished,framesNumber = 0,retval = -1,numBytes=0;
    AVPacket packet;
    char logdatadata[100];
    int result = -1;



    result=avformat_open_input(&pFormatCtx,imageFileName,NULL,NULL);
    if(result!=0)       
    {       
        __android_log_write(ANDROID_LOG_INFO, "record",
                "Can't open image file ");
        return NULL;
    }
    pCodecCtx = pFormatCtx->streams[0]->codec;
    pCodecCtx->width = w;
    pCodecCtx->height = h;
    pCodecCtx->pix_fmt = PIX_FMT_YUV420P;

    // Find the decoder for the video stream
    pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
    if (!pCodec)
    {
        __android_log_write(ANDROID_LOG_INFO, "record",
                "Can't open image file ");
        return NULL;
    }

    pFrame = avcodec_alloc_frame();

    numBytes = avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
    buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t)); 

    retval = avpicture_fill((AVPicture *) pFrame, buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx-
            >height);

    // Open codec
    if(avcodec_open(pCodecCtx, pCodec)<0)
    {
        __android_log_write(ANDROID_LOG_INFO, "record","Could not open codec");
        return NULL;
    }

    if (!pFrame)
    {
        __android_log_write(ANDROID_LOG_INFO, "record","Can't allocate memory for AVFrame\n");
        return NULL;
    }
    int readval = -5;
    while (readval = av_read_frame(pFormatCtx, &packet) >= 0)
    {
        if(packet.stream_index != 0)
            continue;       
        int ret = avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);

        if (ret > 0)
        {
            __android_log_write(ANDROID_LOG_INFO, "record","Frame is decoded\n");
            pFrame->quality = 4;
            av_free_packet(&packet);
            av_close_input_file(pFormatCtx);            
            return pFrame;
        }
        else
        {
            __android_log_write(ANDROID_LOG_INFO, "record","error while decoding frame \n");
        }
    }   
}

上述代码产生了一个视频,可以使用第三方播放器如VLC运行。我只想知道我错过了什么让视频在android上播放,我如何才能删除“不是一个divx文件”错误。

共有1个答案

郑胡媚
2023-03-14

也许你转换的视频文件有。AVI扩展名?ffmpeg使用扩展来选择视频容器格式,H264需要MPEG4容器格式。

 类似资料:
  • 在我的网络应用程序中,用户应该能够上传自己的视频(任意一种格式)。我正在使用ffmpeg对视频进行编码。mp4和。flv使用命令: ffmpeg-iuservid.whateveroutput.mp4output.flv 当ffmpeg对视频进行编码时,它会加载到用户页面上的flowplayer中。但flowplayer总是说“找不到文件”,因为ffmpeg编码尚未完成。 是否有可能在某个播放器中

  • 我想玩。iPhone应用程序中的mpd文件,为此我尝试了VLC播放器,但它没有按照预期工作,播放视频花费了太多时间。我还有其他选择吗。像Android中的exoplayer这样的mpd文件。 我已经为此目的实现了VLC媒体播放器,但现在我正在寻找另一种选择。如果有人对此有任何想法,请帮助。

  • 嗨,我为我的视频网站创建了一个WebView应用程序。网站的设计是为移动用户加载的混合体。只有与移动设备兼容的视频才会加载到混合动力上。玩家来自Vk,DailyMotion,YouTube和QuickTime。 (WebViewActivity.java) (main.xml) (Manifest.xml)

  • 嗨,我有几个视频不能在Android(直接在Chrome上)和iOS(直接在Safari上)上播放,但可以在Windows、Mac和Linux上任何浏览器上播放。 下面是输出 下面是另一段在Android和Chrome上播放的视频的ffprobe输出: 两者都是.mp4格式,并使用编解码器。就我所见,我注意到编解码器配置文件与和与以及元数据部分的差异。 我尝试用ffmpeg重新编码第一个视频,但没

  • 我正在开发一个应用程序,它使用webview来显示网页,如果url是视频链接(youtube)或作为网页一部分的视频,我想播放视频。我试着把url直接添加到webview中,但它连youtube链接都不播放,我已经在webview中启用了插件和javascript.....有谁能在这个问题上帮我,

  • 大家好,我正在尝试使用两个独立的媒体播放器实例播放音频和视频文件。当我从一开始播放它时,它工作得很好。但当我寻找时,我可以看到音频和视频的延迟 这是我寻找音频和视频的代码 //sikAudio(msec); if(media播放器!=null) { // 没有直播流,如果(medialayer.get持续时间() }