使用avcodec_encode_video2进行分段故障,同时从基带编码帧(ffmpeg)

时间:2017-11-21 15:33:20

标签: c image-processing ffmpeg segmentation-fault video-encoding

我在尝试从基带编码帧时最近遇到了一个问题。 avcodec_encode_video2调用发生了分段错误,但我不明白为什么。

这是我初始化AVCodecContext的函数:

void
create_codec_context(
    Header *hdr,
    AVCodecContext *cc,
    AVStream *st,
    AVCodec *codec)
{
    switch (hdr->stream_info)
    {
        case (Line1080i60):
            cc->time_base.num = 1;
            cc->time_base.den = 30;
            break;
        case (Line1080i5994):
            cc->time_base.num = 1001;
        cc->time_base.den = 30000;
        break;
        case (Line1080i50):
            cc->time_base.num = 1;
            cc->time_base.den = 25;
            break;
        case (Line720p60):
            cc->time_base.num = 1;
            cc->time_base.den = 60;
            break;
        case (Line1080p60):
            cc->time_base.num = 1;
            cc->time_base.den = 60;
            break;
        case (Line720p5994):
            cc->time_base.num = 1001;
            cc->time_base.den = 60000;
            break;
        case (Line1080p5994):
            cc->time_base.num = 1001;
            cc->time_base.den = 60000;
            break;
        case (Line720p50):
            cc->time_base.num = 1;
            cc->time_base.den = 50;
        case (Line1080p50):
            cc->time_base.num = 1;
            cc->time_base.den = 50;
            break;
        default:
            syslog(LOG_ERR, "Unknown local socket header stream info (VidStd): %d", hdr->stream_info);
            exit(EXIT_FAILURE);
            break;
    }

    cc->width = hdr->width;
    cc->height = hdr->height;

    st->r_frame_rate.num = cc->time_base.den;
    st->r_frame_rate.den = cc->time_base.num;

    cc->codec_type = AVMEDIA_TYPE_VIDEO;
    cc->codec_id = codec->id;
    cc->bit_rate = (int64_t)cc->width * (cc->height >> !!hdr->interlaced) * 2 * 8 * cc->time_base.den / cc->time_base.num;
    cc->pix_fmt = hdr->pix_fmt;

    st->time_base.num = 1;
    st->time_base.den = 90000;

    if (cc->codec_id == AV_CODEC_ID_RAWVIDEO)
    {
        cc->codec_tag = get_raw_pix_fmt_tag(cc->pix_fmt);
        if (cc->codec_tag == 0)
        {
            syslog(LOG_ERR, "Failed to get codec tag for raw video pix fmt: %d", cc->pix_fmt);
            exit(EXIT_FAILURE);
        }
    }

    cc->max_b_frames = 0;
    cc->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
}

这是我每个帧的过程循环:

size_t
process_bb_data(
    uint8_t *src,
    uint8_t *dst)
{
    Header *src_hdr = (Header *)src;
    uint8_t *src_y = src + sizeof(Header);
    uint8_t *src_u = src_y + (src_hdr->Y_linesize * src_hdr->height);
    uint8_t *src_v = src_u + (src_hdr->U_linesize * src_hdr->height);

    Header *dst_hdr = (Header *)dst;
    uint8_t *dst_y = dst + sizeof(Header);
    uint8_t *dst_u = dst_y + (dst_hdr->Y_linesize * dst_hdr->height);
    uint8_t *dst_v = dst_u + (dst_hdr->U_linesize * dst_hdr->height);

    memcpy(dst_hdr, src_hdr, sizeof(Header));

    memcpy(dst_y, src_y, dst_hdr->Y_linesize * dst_hdr->height);
    memcpy(dst_u, src_u, dst_hdr->U_linesize * dst_hdr->height);
    memcpy(dst_v, src_v, dst_hdr->V_linesize * dst_hdr->height);

    av_register_all();
    avcodec_register_all();

    AVCodec *codec = avcodec_find_encoder_by_name("mpeg2video");
    AVCodecContext *cc = avcodec_alloc_context3(codec);
    avcodec_get_context_defaults3(cc, codec)

    AVFormatContext *fmt_ctx = avformat_alloc_context();
    AVStream *st = avformat_new_stream(fmt_ctx, NULL);

    /* My function from above */
    create_codec_context(dst_hdr, cc, st, codec);

    AVFrame *frame = av_frame_alloc();
    frame->width = dst_hdr->width;
    frame->height = dst_hdr->height;
    frame->format = dst_hdr->pix_fmt;
    frame->data[0] = dst_y;
    frame->data[1] = dst_u;
    frame->data[2] = dst_v;
    frame->linesize[0] = dst_hdr->Y_linesize;
    frame->linesize[1] = dst_hdr->U_linesize;
    frame->linesize[2] = dst_hdr->V_linesize;
    int ret;
    int got_packet = 0;

    AVPacket pkt = {0};
    av_init_packet(&pkt);
    pkt.data = NULL; //dst_y;
    pkt.size = 0; //(dst_hdr->Y_linesize + dst_hdr->U_linesize + dst_hdr->V_linesize) * dst_hdr->height;

    /* SEGMENTATION FAULT HERE */
    ret = avcodec_encode_video2(cc, &pkt, frame, &got_packet);

    if (got_packet)
    {
        ret = av_write_frame(fmt_ctx, &pkt);
        av_packet_unref(&pkt);
    }
    else
    {
        ret = 0;
    }

    if (ret < 0)
    {
        exit(EXIT_FAILURE);
    }

    return (sizeof(Header) + dst_hdr->data_size);
}

我在这里错过了一些非常愚蠢的东西吗?

1 个答案:

答案 0 :(得分:1)

哇,刚发现问题......别忘了你的 avcodec_open2(cc,codec,NULL) 电话,女士们和男士们。