Ffmpeg 将原始yuv转换为在android上崩溃的mp4

Ffmpeg 将原始yuv转换为在android上崩溃的mp4,ffmpeg,yuv,Ffmpeg,Yuv,以下是我的步骤: 将jpeg文件解码为rgb565;(成功) 将rgb565转换为yuv420;(不确定是否有效,函数“Bitmap2Yuv420”) 将yuv420转换为mp4。(调用avcodec_open2时崩溃) 这就是代码: void ADKJpegDecoder::Bitmap2Yuv420(const char * outfilename) { unsigned char *destination = new unsigned char[m_Width * m_Height

以下是我的步骤:

  • 将jpeg文件解码为rgb565;(成功)

  • 将rgb565转换为yuv420;(不确定是否有效,函数“Bitmap2Yuv420”)

  • 将yuv420转换为mp4。(调用avcodec_open2时崩溃)

  • 这就是代码:

    void ADKJpegDecoder::Bitmap2Yuv420(const char * outfilename) {
    unsigned char *destination = new unsigned char[m_Width * m_Height
            * m_BytesPerPixel / 2];
    unsigned char* rgb = m_RawImage;
    size_t image_size = m_Width * m_Height;
    size_t upos = image_size;
    size_t vpos = upos + upos / 4;
    size_t i = 0;
    
    for (size_t line = 0; line < m_Height; ++line) {
        if (!(line % 2)) {
            for (size_t x = 0; x < m_Width; x += 2) {
                char r = rgb[3 * i];
                char g = rgb[3 * i + 1];
                char b = rgb[3 * i + 2];
    
                destination[i++] = ((66 * r + 129 * g + 25 * b) >> 8) + 16;
    
                destination[upos++] = ((-38 * r + -74 * g + 112 * b) >> 8)
                        + 128;
                destination[vpos++] = ((112 * r + -94 * g + -18 * b) >> 8)
                        + 128;
    
                r = rgb[3 * i];
                g = rgb[3 * i + 1];
                b = rgb[3 * i + 2];
    
                destination[i++] = ((66 * r + 129 * g + 25 * b) >> 8) + 16;
            }
        } else {
            for (size_t x = 0; x < m_Width; x += 1) {
                char r = rgb[3 * i];
                char g = rgb[3 * i + 1];
                char b = rgb[3 * i + 2];
    
                destination[i++] = ((66 * r + 129 * g + 25 * b) >> 8) + 16;
            }
        }
    }
    
    ADKVideoEncoder::getInstance()->startEncodeVideo(destination);
    delete[] destination;
    
    void ADKJpegDecoder::Bitmap2Yuv420(常量字符*outfilename){
    无符号字符*目的地=新的无符号字符[m_宽度*m_高度
    *m_字节/像素/2];
    无符号字符*rgb=m_RawImage;
    图像大小=米宽*米高;
    大小=图像大小;
    尺寸=upos+upos/4;
    尺寸i=0;
    用于(尺寸线=0;线<米高度;++线){
    如果(!(第%2行)){
    对于(尺寸x=0;x>8)+16;
    目的地[upos++]=(-38*r+-74*g+112*b)>>8)
    + 128;
    目的地[vpos++]=((112*r+-94*g+-18*b)>>8)
    + 128;
    r=rgb[3*i];
    g=rgb[3*i+1];
    b=rgb[3*i+2];
    目的地[i++]=((66*r+129*g+25*b)>>8)+16;
    }
    }否则{
    对于(尺寸x=0;x>8)+16;
    }
    }
    }
    ADKVideoEncoder::getInstance()->startEncodeVideo(目标);
    删除[]目的地;
    
    }

    void ADKVideoEncoder::startEncodeVideo(无符号字符*原始数据){
    AVFormatContext*oc;
    AVOutputFormat*fmt;
    AVStream*视频;
    avc*c;
    双视屏;
    uint8_t*视频突发事件;
    AVFrame*图片;
    整数大小;
    int ret;
    int视频大小;
    const char*filename=“/sdcard/test.mpg”;
    av_寄存器_all();
    fmt=av_guess_格式(空,文件名,空);
    oc=avformat_alloc_context();
    oc->oformat=fmt;
    snprintf(oc->filename,sizeof(oc->filename),“%s”,filename);
    视频=空;
    如果(fmt->video\u codec!=codec\u ID\u NONE){
    视频流=av新流(oc,0);
    c=视频->编解码器;
    c->codec_id=fmt->video_codec;
    c->codec\u type=AVMEDIA\u type\u VIDEO;
    c->比特率=400000;
    c->宽度=320;
    c->高度=480;
    c->time_base.num=1;
    c->time_base.den=1;
    c->gop_尺寸=12;
    c->pix_fmt=pix_fmt_YUV420P;
    c->max_b_frames=0;
    如果(!strcmp(oc->oformat->名称,“mp4”)
    ||!strcmp(oc->oformat->名称,“mov”)
    ||!strcmp(oc->oformat->name,“3gp”)){
    c->flags |=编解码器|标志|全局|头;
    }
    }
    av_转储_格式(oc,0,文件名,1);
    如果(视频){
    AVCodec*codec=AVCodec\u find\u编码器(c->codec\u id);
    如果(!编解码器){
    返回;
    }
    AVDictionary*选项DICT=NULL;
    if(avcodec_open2(c、codec和optionsDict)<0){
    返回;
    }
    如果(!(oc->oformat->flags&AVFMT\U RAWCORMATION)){
    视频大小=20000;
    视频突发=(uint8\u t*)av\u malloc(视频突发大小);
    }
    picture=avcodec_alloc_frame();
    大小=avpicture\u get\u大小(c->pix\u fmt,c->宽度,c->高度);
    avpicture_fill((avpicture*)图片,原始数据,c->pix_fmt,c->宽度,
    c->高度);
    }
    如果(!(fmt->标志和AVFMT_文件)){
    如果(avio_打开(&oc->pb,文件名,avio_标志_写入)<0){
    返回;
    }
    }
    avformat_write_头(oc,0);
    如果(视频){
    视频时间=(双精度)(视频时间->时间值*视频时间->时间基数.num
    /视频->时基.den);
    }否则{
    视频_pts=0.0;
    }
    如果(!video_st/*| video_pts>=5.0*/){
    返回;
    }
    c=视频->编解码器;
    尺寸=c->宽度*c->高度;
    图片->数据[0]=原始数据;
    图片->数据[1]=原始数据+大小;
    图片->数据[2]=原始数据+大小*5/4;
    如果(oc->oformat->flags和AVFMT_RAWPICTURE){
    AVPacket-pkt;
    av_初始_数据包(&pkt);
    pkt.flags |=AV_pkt_FLAG_键;
    pkt.stream\u index=video\u st->index;
    pkt.data=(uint8_t*)图片;
    pkt.size=sizeof(AVPicture);
    ret=av写入帧(oc和pkt);
    }否则{
    int out_size=avcodec_encode_video(c,video_EXPUF,video_EXPUF_size,
    图片);
    如果(输出大小>0){
    AVPacket-pkt;
    av_初始_数据包(&pkt);
    pkt.pts=av_rescale_q(c->coded_frame->pts,c->time_base,
    视频->时基);
    如果(c->编码帧->关键帧){
    pkt.flags |=AV_pkt_FLAG_键;
    }
    pkt.stream\u index=video\u st->index;
    pkt.data=video\u exputf;
    pkt.size=外部尺寸;
    ret=av写入帧(oc和pkt);
    }
    }
    如果(视频){
    avcodec_关闭(视频->编解码器);
    av_免费(图片);
    av_免费(视频_论坛);
    }
    av_写入_预告片(oc);
    对于(inti=0;inb\u流;i++){
    av_freep(&oc->streams[i]->codec);
    av_freep(&oc->streams[i]);
    }
    如果(!(fmt->标志和AVFMT_文件)){
    avio_关闭(oc->pb);
    }
    无av_(oc);
    
    }


    有人能找出问题所在吗?非常感谢

    嗨,你能解释一下吗<代码>图片->数据[0]=原始数据;图片->数据[1]=原始数据+大小;图片->数据[2]=原始数据+大小*5/4为什么使用
    5/4
    void ADKVideoEncoder::startEncodeVideo(unsigned char* rawDatas) {
    AVFormatContext* oc;
    AVOutputFormat* fmt;
    AVStream* video_st;
    AVCodecContext* c;
    
    double video_pts;
    uint8_t* video_outbuf;
    AVFrame* picture;
    int size;
    int ret;
    int video_outbuf_size;
    
    const char* filename = "/sdcard/test.mpg";
    
    av_register_all();
    
    fmt = av_guess_format(NULL, filename, NULL);
    oc = avformat_alloc_context();
    oc->oformat = fmt;
    snprintf(oc->filename, sizeof(oc->filename), "%s", filename);
    
    video_st = NULL;
    if (fmt->video_codec != CODEC_ID_NONE) {
        video_st = av_new_stream(oc, 0);
        c = video_st->codec;
        c->codec_id = fmt->video_codec;
        c->codec_type = AVMEDIA_TYPE_VIDEO;
        c->bit_rate = 400000;
        c->width = 320;
        c->height = 480;
        c->time_base.num = 1;
        c->time_base.den = 1;
        c->gop_size = 12;
        c->pix_fmt = PIX_FMT_YUV420P;
        c->max_b_frames = 0;
        if (!strcmp(oc->oformat->name, "mp4")
                || !strcmp(oc->oformat->name, "mov")
                || !strcmp(oc->oformat->name, "3gp")) {
            c->flags |= CODEC_FLAG_GLOBAL_HEADER;
        }
    }
    
    av_dump_format(oc, 0, filename, 1);
    if (video_st) {
        AVCodec* codec = avcodec_find_encoder(c->codec_id);
        if (!codec) {
            return;
        }
        AVDictionary *optionsDict = NULL;
        if (avcodec_open2(c, codec, &optionsDict) < 0) {
            return;
        }
        if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) {
            video_outbuf_size = 20000;
            video_outbuf = (uint8_t*) av_malloc(video_outbuf_size);
        }
        picture = avcodec_alloc_frame();
        size = avpicture_get_size(c->pix_fmt, c->width, c->height);
        avpicture_fill((AVPicture*) picture, rawDatas, c->pix_fmt, c->width,
                c->height);
    }
    
    if (!(fmt->flags & AVFMT_NOFILE)) {
        if (avio_open(&oc->pb, filename, AVIO_FLAG_WRITE) < 0) {
            return;
        }
    }
    avformat_write_header(oc, 0);
    
    if (video_st) {
        video_pts = (double) (video_st->pts.val * video_st->time_base.num
                / video_st->time_base.den);
    } else {
        video_pts = 0.0;
    }
    if (!video_st/* || video_pts >= 5.0*/) {
        return;
    }
    c = video_st->codec;
    size = c->width * c->height;
    
    picture->data[0] = rawDatas;
    picture->data[1] = rawDatas + size;
    picture->data[2] = rawDatas + size * 5 / 4;
    
    if (oc->oformat->flags & AVFMT_RAWPICTURE) {
        AVPacket pkt;
        av_init_packet(&pkt);
        pkt.flags |= AV_PKT_FLAG_KEY;
        pkt.stream_index = video_st->index;
        pkt.data = (uint8_t*) picture;
        pkt.size = sizeof(AVPicture);
        ret = av_write_frame(oc, &pkt);
    } else {
        int out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size,
                picture);
        if (out_size > 0) {
            AVPacket pkt;
            av_init_packet(&pkt);
            pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base,
                    video_st->time_base);
            if (c->coded_frame->key_frame) {
                pkt.flags |= AV_PKT_FLAG_KEY;
            }
            pkt.stream_index = video_st->index;
            pkt.data = video_outbuf;
            pkt.size = out_size;
            ret = av_write_frame(oc, &pkt);
        }
    }
    
    if (video_st) {
        avcodec_close(video_st->codec);
        av_free(picture);
        av_free(video_outbuf);
    }
    av_write_trailer(oc);
    for (int i = 0; i < oc->nb_streams; i++) {
        av_freep(&oc->streams[i]->codec);
        av_freep(&oc->streams[i]);
    }
    if (!(fmt->flags & AVFMT_NOFILE)) {
        avio_close(oc->pb);
    }
    av_free(oc);