int encode_x264(struct videnc_state *st, bool update, const struct vidframe *frame) { x264_picture_t pic_in, pic_out; x264_nal_t *nal; int i_nal; int i, err, ret; int csp, pln; if (!st || !frame) return EINVAL; switch (frame->fmt) { case VID_FMT_YUV420P: csp = X264_CSP_I420; pln = 3; break; case VID_FMT_NV12: csp = X264_CSP_NV12; pln = 2; break; default: warning("avcodec: pixel format not supported (%s)\n", vidfmt_name(frame->fmt)); return ENOTSUP; } if (!st->x264 || !vidsz_cmp(&st->encsize, &frame->size)) { err = open_encoder_x264(st, &st->encprm, &frame->size, csp); if (err) return err; } if (update) { #if X264_BUILD >= 95 x264_encoder_intra_refresh(st->x264); #endif debug("avcodec: x264 picture update\n"); } x264_picture_init(&pic_in); pic_in.i_type = update ? X264_TYPE_IDR : X264_TYPE_AUTO; pic_in.i_qpplus1 = 0; pic_in.i_pts = ++st->pts; pic_in.img.i_csp = csp; pic_in.img.i_plane = pln; for (i=0; i<pln; i++) { pic_in.img.i_stride[i] = frame->linesize[i]; pic_in.img.plane[i] = frame->data[i]; } ret = x264_encoder_encode(st->x264, &nal, &i_nal, &pic_in, &pic_out); if (ret < 0) { fprintf(stderr, "x264 [error]: x264_encoder_encode failed\n"); } if (i_nal == 0) return 0; err = 0; for (i=0; i<i_nal && !err; i++) { const uint8_t hdr = nal[i].i_ref_idc<<5 | nal[i].i_type<<0; int offset = 0; #if X264_BUILD >= 76 const uint8_t *p = nal[i].p_payload; /* Find the NAL Escape code [00 00 01] */ if (nal[i].i_payload > 4 && p[0] == 0x00 && p[1] == 0x00) { if (p[2] == 0x00 && p[3] == 0x01) offset = 4 + 1; else if (p[2] == 0x01) offset = 3 + 1; } #endif /* skip Supplemental Enhancement Information (SEI) */ if (nal[i].i_type == H264_NAL_SEI) continue; err = h264_nal_send(true, true, (i+1)==i_nal, hdr, nal[i].p_payload + offset, nal[i].i_payload - offset, st->encprm.pktsize, st->pkth, st->arg); } return err; }
int encode_x264(struct videnc_state *st, bool update, const struct vidframe *frame, videnc_packet_h *pkth, void *arg) { x264_picture_t pic_in, pic_out; x264_nal_t *nal; int i_nal; int i, err, ret; if (!st->x264 || !vidsz_cmp(&st->encsize, &frame->size)) { err = open_encoder_x264(st, &st->encprm, &frame->size); if (err) return err; } if (update) { #if X264_BUILD >= 95 x264_encoder_intra_refresh(st->x264); #endif re_printf("x264 picture update\n"); } memset(&pic_in, 0, sizeof(pic_in)); pic_in.i_type = update ? X264_TYPE_IDR : X264_TYPE_AUTO; pic_in.i_qpplus1 = 0; pic_in.i_pts = ++st->pts; pic_in.img.i_csp = X264_CSP_I420; pic_in.img.i_plane = 3; for (i=0; i<3; i++) { pic_in.img.i_stride[i] = frame->linesize[i]; pic_in.img.plane[i] = frame->data[i]; } ret = x264_encoder_encode(st->x264, &nal, &i_nal, &pic_in, &pic_out); if (ret < 0) { fprintf(stderr, "x264 [error]: x264_encoder_encode failed\n"); } if (i_nal == 0) return 0; err = 0; for (i=0; i<i_nal && !err; i++) { const uint8_t hdr = nal[i].i_ref_idc<<5 | nal[i].i_type<<0; int offset = 0; #if X264_BUILD >= 76 const uint8_t *p = nal[i].p_payload; /* Find the NAL Escape code [00 00 01] */ if (nal[i].i_payload > 4 && p[0] == 0x00 && p[1] == 0x00) { if (p[2] == 0x00 && p[3] == 0x01) offset = 4 + 1; else if (p[2] == 0x01) offset = 3 + 1; } #endif /* skip Supplemental Enhancement Information (SEI) */ if (nal[i].i_type == H264_NAL_SEI) continue; err = h264_nal_send(true, true, (i+1)==i_nal, hdr, nal[i].p_payload + offset, nal[i].i_payload - offset, st->encprm.pktsize, pkth, arg); } return err; }