|
|
@@ -49,13 +49,13 @@ typedef struct |
|
|
|
AVFrame *frame; |
|
|
|
|
|
|
|
struct SwsContext *sws_ctx; |
|
|
|
int src_width, src_height; |
|
|
|
int src_width, src_height, src_fmt; |
|
|
|
} |
|
|
|
ffmpeg_codec_t; |
|
|
|
#endif |
|
|
|
|
|
|
|
pipi_sequence_t *pipi_open_sequence(char const *file, |
|
|
|
int width, int height, int fps, |
|
|
|
int width, int height, int rgb, int fps, |
|
|
|
int par_num, int par_den, int bitrate) |
|
|
|
{ |
|
|
|
#if defined USE_FFMPEG |
|
|
@@ -182,6 +182,8 @@ pipi_sequence_t *pipi_open_sequence(char const *file, |
|
|
|
ff->buf_len = 64 * 1024 * 1024; |
|
|
|
ff->buf = (uint8_t *)av_malloc(ff->buf_len); |
|
|
|
|
|
|
|
ff->src_fmt = rgb ? PIX_FMT_RGB32 : PIX_FMT_YUV444P; |
|
|
|
|
|
|
|
av_write_header(ff->fmt_ctx); |
|
|
|
|
|
|
|
return seq; |
|
|
@@ -219,7 +221,7 @@ int pipi_feed_sequence(pipi_sequence_t *seq, uint8_t const *buffer, |
|
|
|
|
|
|
|
if (!ff->sws_ctx) |
|
|
|
{ |
|
|
|
ff->sws_ctx = sws_getContext(width, height, PIX_FMT_YUV444P, |
|
|
|
ff->sws_ctx = sws_getContext(width, height, ff->src_fmt, |
|
|
|
ff->cod_ctx->width, |
|
|
|
ff->cod_ctx->height, |
|
|
|
ff->cod_ctx->pix_fmt, SWS_BICUBIC, |
|
|
@@ -234,21 +236,30 @@ int pipi_feed_sequence(pipi_sequence_t *seq, uint8_t const *buffer, |
|
|
|
return -1; |
|
|
|
|
|
|
|
/* Convert interleaved YUV to planar YUV */ |
|
|
|
if (!seq->convert_buf) |
|
|
|
seq->convert_buf = malloc(width * height * 3); |
|
|
|
if (ff->src_fmt == PIX_FMT_YUV444P) |
|
|
|
{ |
|
|
|
if (!seq->convert_buf) |
|
|
|
seq->convert_buf = malloc(width * height * 3); |
|
|
|
|
|
|
|
for (n = 0; n < width * height; n++) |
|
|
|
{ |
|
|
|
seq->convert_buf[n] = buffer[4 * n]; |
|
|
|
seq->convert_buf[n + width * height] = buffer[4 * n + 1]; |
|
|
|
seq->convert_buf[n + 2 * width * height] = buffer[4 * n + 2]; |
|
|
|
} |
|
|
|
|
|
|
|
for (n = 0; n < width * height; n++) |
|
|
|
/* Feed the buffers to FFmpeg */ |
|
|
|
buflist[0] = seq->convert_buf; |
|
|
|
buflist[1] = seq->convert_buf + 2 * width * height; |
|
|
|
buflist[2] = seq->convert_buf + width * height; |
|
|
|
pitchlist[0] = pitchlist[1] = pitchlist[2] = width; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
seq->convert_buf[n] = buffer[4 * n]; |
|
|
|
seq->convert_buf[n + width * height] = buffer[4 * n + 1]; |
|
|
|
seq->convert_buf[n + 2 * width * height] = buffer[4 * n + 2]; |
|
|
|
buflist[0] = buffer; |
|
|
|
pitchlist[0] = 4 * width; |
|
|
|
} |
|
|
|
|
|
|
|
/* Feed the buffers to FFmpeg */ |
|
|
|
buflist[0] = seq->convert_buf; |
|
|
|
buflist[1] = seq->convert_buf + 2 * width * height; |
|
|
|
buflist[2] = seq->convert_buf + width * height; |
|
|
|
pitchlist[0] = pitchlist[1] = pitchlist[2] = width; |
|
|
|
sws_scale(ff->sws_ctx, buflist, pitchlist, 0, height, |
|
|
|
ff->frame->data, ff->frame->linesize); |
|
|
|
|
|
|
@@ -279,11 +290,13 @@ int pipi_close_sequence(pipi_sequence_t *seq) |
|
|
|
#if defined USE_FFMPEG |
|
|
|
ffmpeg_codec_t *ff = (ffmpeg_codec_t *)seq->codec_priv; |
|
|
|
|
|
|
|
if (ff->fmt_ctx) |
|
|
|
/* Finish the sequence */ |
|
|
|
if (ff->buf) |
|
|
|
{ |
|
|
|
av_write_trailer(ff->fmt_ctx); |
|
|
|
} |
|
|
|
|
|
|
|
/* Close everything */ |
|
|
|
if (ff->buf) |
|
|
|
{ |
|
|
|
av_free(ff->buf); |
|
|
@@ -311,7 +324,7 @@ int pipi_close_sequence(pipi_sequence_t *seq) |
|
|
|
av_freep(&ff->fmt_ctx->streams[0]); |
|
|
|
ff->stream = NULL; |
|
|
|
|
|
|
|
if (!(ff->fmt_ctx->flags & AVFMT_NOFILE)) |
|
|
|
if (!(ff->fmt_ctx->flags & AVFMT_NOFILE) && ff->fmt_ctx->pb) |
|
|
|
url_fclose(ff->fmt_ctx->pb); |
|
|
|
|
|
|
|
av_free(ff->fmt_ctx); |
|
|
|