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

时间:2013-12-19 09:18:34

标签: ffmpeg yuv

这是我的步骤:

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

  2. 将rgb565转换为yuv420;(不确定是否有效,功能“Bitmap2Yuv420”)

  3. 将yuv420转换为mp4。 (调用avcodec_open2时崩溃);

  4. 这就是代码:

    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 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);
    

    }

    那么有人能找到问题吗?非常感谢!;

0 个答案:

没有答案