static int encode_process(struct vidfilt_enc_st *st, struct vidframe *frame) { struct swscale_enc *enc = (struct swscale_enc *)st; enum AVPixelFormat avpixfmt, avpixfmt_dst; const uint8_t *srcSlice[4]; uint8_t *dst[4]; int srcStride[4], dstStride[4]; int width, height, i, h; int err = 0; if (!st) return EINVAL; if (!frame) return 0; width = frame->size.w; height = frame->size.h; avpixfmt = vidfmt_to_avpixfmt(frame->fmt); if (avpixfmt == AV_PIX_FMT_NONE) { warning("swscale: unknown pixel-format (%s)\n", vidfmt_name(frame->fmt)); return EINVAL; } avpixfmt_dst = vidfmt_to_avpixfmt(swscale_format); if (avpixfmt_dst == AV_PIX_FMT_NONE) { warning("swscale: unknown pixel-format (%s)\n", vidfmt_name(swscale_format)); return EINVAL; } if (!enc->sws) { struct SwsContext *sws; int flags = 0; sws = sws_getContext(width, height, avpixfmt, enc->dst_size.w, enc->dst_size.h, avpixfmt_dst, flags, NULL, NULL, NULL); if (!sws) { warning("swscale: sws_getContext error\n"); return ENOMEM; } enc->sws = sws; info("swscale: created SwsContext:" " `%s' %d x %d --> `%s' %u x %u\n", vidfmt_name(frame->fmt), width, height, vidfmt_name(swscale_format), enc->dst_size.w, enc->dst_size.h); } if (!enc->frame) { err = vidframe_alloc(&enc->frame, swscale_format, &enc->dst_size); if (err) { warning("swscale: vidframe_alloc error (%m)\n", err); return err; } } for (i=0; i<4; i++) { srcSlice[i] = frame->data[i]; srcStride[i] = frame->linesize[i]; dst[i] = enc->frame->data[i]; dstStride[i] = enc->frame->linesize[i]; } h = sws_scale(enc->sws, srcSlice, srcStride, 0, height, dst, dstStride); if (h <= 0) { warning("swscale: sws_scale error (%d)\n", h); return EPROTO; } /* Copy the converted frame back to the input frame */ for (i=0; i<4; i++) { frame->data[i] = enc->frame->data[i]; frame->linesize[i] = enc->frame->linesize[i]; } frame->size = enc->frame->size; frame->fmt = enc->frame->fmt; return 0; }
int h265_encode(struct videnc_state *st, bool update, const struct vidframe *frame, uint64_t timestamp) { AVFrame *pict = NULL; AVPacket *pkt = NULL; uint64_t rtp_ts; int i, ret, got_packet = 0, err = 0; if (!st || !frame) return EINVAL; if (!st->ctx || !vidsz_cmp(&st->size, &frame->size) || st->fmt != frame->fmt) { enum AVPixelFormat pix_fmt; pix_fmt = vidfmt_to_avpixfmt(frame->fmt); if (pix_fmt == AV_PIX_FMT_NONE) { warning("h265: encode: pixel format not supported" " (%s)\n", vidfmt_name(frame->fmt)); return ENOTSUP; } debug("h265: encoder: reset %u x %u (%s)\n", frame->size.w, frame->size.h, vidfmt_name(frame->fmt)); err = open_encoder(st, &frame->size, pix_fmt); if (err) return err; st->size = frame->size; st->fmt = frame->fmt; } pict = av_frame_alloc(); if (!pict) { err = ENOMEM; goto out; } pict->format = st->ctx->pix_fmt; pict->width = frame->size.w; pict->height = frame->size.h; pict->pts = timestamp; for (i=0; i<4; i++) { pict->data[i] = frame->data[i]; pict->linesize[i] = frame->linesize[i]; } if (update) { debug("h265: encoder picture update\n"); pict->key_frame = 1; pict->pict_type = AV_PICTURE_TYPE_I; } #if LIBAVUTIL_VERSION_MAJOR >= 55 pict->color_range = AVCOL_RANGE_MPEG; #endif #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 37, 100) pkt = av_packet_alloc(); if (!pkt) { err = ENOMEM; goto out; } ret = avcodec_send_frame(st->ctx, pict); if (ret < 0) { err = EBADMSG; goto out; } /* NOTE: packet contains 4-byte startcode */ ret = avcodec_receive_packet(st->ctx, pkt); if (ret < 0) { info("h265: no packet yet ..\n"); err = 0; goto out; } got_packet = 1; #else pkt = av_malloc(sizeof(*pkt)); if (!pkt) { err = ENOMEM; goto out; } av_init_packet(pkt); av_new_packet(pkt, 65536); ret = avcodec_encode_video2(st->ctx, pkt, pict, &got_packet); if (ret < 0) { err = EBADMSG; goto out; } #endif if (!got_packet) goto out; rtp_ts = video_calc_rtp_timestamp_fix(pkt->dts); err = packetize_annexb(rtp_ts, pkt->data, pkt->size, st->pktsize, st->pkth, st->arg); if (err) goto out; out: if (pict) av_free(pict); if (pkt) av_packet_free(&pkt); return err; }