mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-02 09:01:50 -05:00
videoconvert-ffmpeg: support transcoding
When the input and output is an encoded format but the dimensions are different, do a decode, scale and encode.
This commit is contained in:
parent
f8dcf32c8d
commit
479ba33685
1 changed files with 29 additions and 24 deletions
|
|
@ -863,6 +863,7 @@ static int setup_convert(struct impl *this)
|
||||||
{
|
{
|
||||||
struct dir *in, *out;
|
struct dir *in, *out;
|
||||||
uint32_t format;
|
uint32_t format;
|
||||||
|
int decoder_id = 0, encoder_id = 0;
|
||||||
|
|
||||||
in = &this->dir[SPA_DIRECTION_INPUT];
|
in = &this->dir[SPA_DIRECTION_INPUT];
|
||||||
out = &this->dir[SPA_DIRECTION_OUTPUT];
|
out = &this->dir[SPA_DIRECTION_OUTPUT];
|
||||||
|
|
@ -876,6 +877,9 @@ static int setup_convert(struct impl *this)
|
||||||
if (!in->have_format || !out->have_format)
|
if (!in->have_format || !out->have_format)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
|
get_format(in, &in->width, &in->height, &format);
|
||||||
|
get_format(out, &out->width, &out->height, &format);
|
||||||
|
|
||||||
switch (in->format.media_subtype) {
|
switch (in->format.media_subtype) {
|
||||||
case SPA_MEDIA_SUBTYPE_raw:
|
case SPA_MEDIA_SUBTYPE_raw:
|
||||||
in->pix_fmt = format_to_pix_fmt(in->format.info.raw.format);
|
in->pix_fmt = format_to_pix_fmt(in->format.info.raw.format);
|
||||||
|
|
@ -884,20 +888,14 @@ static int setup_convert(struct impl *this)
|
||||||
out->pix_fmt = format_to_pix_fmt(out->format.info.raw.format);
|
out->pix_fmt = format_to_pix_fmt(out->format.info.raw.format);
|
||||||
break;
|
break;
|
||||||
case SPA_MEDIA_SUBTYPE_mjpg:
|
case SPA_MEDIA_SUBTYPE_mjpg:
|
||||||
if ((this->encoder.codec = avcodec_find_encoder(AV_CODEC_ID_MJPEG)) == NULL) {
|
encoder_id = AV_CODEC_ID_MJPEG;
|
||||||
spa_log_error(this->log, "failed to find MJPEG encoder");
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
out->format.media_subtype = SPA_MEDIA_SUBTYPE_raw;
|
out->format.media_subtype = SPA_MEDIA_SUBTYPE_raw;
|
||||||
out->format.info.raw.format = SPA_VIDEO_FORMAT_I420;
|
out->format.info.raw.format = SPA_VIDEO_FORMAT_I420;
|
||||||
out->format.info.raw.size = in->format.info.raw.size;
|
out->format.info.raw.size = in->format.info.raw.size;
|
||||||
out->pix_fmt = AV_PIX_FMT_YUVJ420P;
|
out->pix_fmt = AV_PIX_FMT_YUVJ420P;
|
||||||
break;
|
break;
|
||||||
case SPA_MEDIA_SUBTYPE_h264:
|
case SPA_MEDIA_SUBTYPE_h264:
|
||||||
if ((this->encoder.codec = avcodec_find_encoder(AV_CODEC_ID_H264)) == NULL) {
|
encoder_id = AV_CODEC_ID_H264;
|
||||||
spa_log_error(this->log, "failed to find H264 encoder");
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
|
|
@ -906,14 +904,16 @@ static int setup_convert(struct impl *this)
|
||||||
case SPA_MEDIA_SUBTYPE_mjpg:
|
case SPA_MEDIA_SUBTYPE_mjpg:
|
||||||
switch (out->format.media_subtype) {
|
switch (out->format.media_subtype) {
|
||||||
case SPA_MEDIA_SUBTYPE_mjpg:
|
case SPA_MEDIA_SUBTYPE_mjpg:
|
||||||
/* passthrough */
|
/* passthrough if same dimensions or else reencode */
|
||||||
|
if (in->width != out->width ||
|
||||||
|
in->height != out->height) {
|
||||||
|
encoder_id = decoder_id = AV_CODEC_ID_MJPEG;
|
||||||
|
out->pix_fmt = AV_PIX_FMT_YUVJ420P;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SPA_MEDIA_SUBTYPE_raw:
|
case SPA_MEDIA_SUBTYPE_raw:
|
||||||
out->pix_fmt = format_to_pix_fmt(out->format.info.raw.format);
|
out->pix_fmt = format_to_pix_fmt(out->format.info.raw.format);
|
||||||
if ((this->decoder.codec = avcodec_find_decoder(AV_CODEC_ID_MJPEG)) == NULL) {
|
decoder_id = AV_CODEC_ID_MJPEG;
|
||||||
spa_log_error(this->log, "failed to find MJPEG decoder");
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
|
|
@ -922,14 +922,14 @@ static int setup_convert(struct impl *this)
|
||||||
case SPA_MEDIA_SUBTYPE_h264:
|
case SPA_MEDIA_SUBTYPE_h264:
|
||||||
switch (out->format.media_subtype) {
|
switch (out->format.media_subtype) {
|
||||||
case SPA_MEDIA_SUBTYPE_h264:
|
case SPA_MEDIA_SUBTYPE_h264:
|
||||||
/* passthrough */
|
/* passthrough if same dimensions or else reencode */
|
||||||
|
if (in->width != out->width ||
|
||||||
|
in->height != out->height)
|
||||||
|
encoder_id = decoder_id = AV_CODEC_ID_H264;
|
||||||
break;
|
break;
|
||||||
case SPA_MEDIA_SUBTYPE_raw:
|
case SPA_MEDIA_SUBTYPE_raw:
|
||||||
out->pix_fmt = format_to_pix_fmt(out->format.info.raw.format);
|
out->pix_fmt = format_to_pix_fmt(out->format.info.raw.format);
|
||||||
if ((this->decoder.codec = avcodec_find_decoder(AV_CODEC_ID_H264)) == NULL) {
|
decoder_id = AV_CODEC_ID_H264;
|
||||||
spa_log_error(this->log, "failed to find H264 decoder");
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
|
|
@ -939,10 +939,11 @@ static int setup_convert(struct impl *this)
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
get_format(in, &in->width, &in->height, &format);
|
if (decoder_id) {
|
||||||
get_format(out, &out->width, &out->height, &format);
|
if ((this->decoder.codec = avcodec_find_decoder(decoder_id)) == NULL) {
|
||||||
|
spa_log_error(this->log, "failed to find %d decoder", decoder_id);
|
||||||
if (this->decoder.codec) {
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
if ((this->decoder.context = avcodec_alloc_context3(this->decoder.codec)) == NULL)
|
if ((this->decoder.context = avcodec_alloc_context3(this->decoder.codec)) == NULL)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
|
|
@ -958,7 +959,12 @@ static int setup_convert(struct impl *this)
|
||||||
}
|
}
|
||||||
if ((this->decoder.frame = av_frame_alloc()) == NULL)
|
if ((this->decoder.frame = av_frame_alloc()) == NULL)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
if (this->encoder.codec) {
|
|
||||||
|
if (encoder_id) {
|
||||||
|
if ((this->encoder.codec = avcodec_find_encoder(encoder_id)) == NULL) {
|
||||||
|
spa_log_error(this->log, "failed to find %d encoder", encoder_id);
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
if ((this->encoder.context = avcodec_alloc_context3(this->encoder.codec)) == NULL)
|
if ((this->encoder.context = avcodec_alloc_context3(this->encoder.codec)) == NULL)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
|
|
@ -981,7 +987,6 @@ static int setup_convert(struct impl *this)
|
||||||
if ((this->convert.frame = av_frame_alloc()) == NULL)
|
if ((this->convert.frame = av_frame_alloc()) == NULL)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
|
|
||||||
this->setup = true;
|
this->setup = true;
|
||||||
|
|
||||||
emit_node_info(this, false);
|
emit_node_info(this, false);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue