git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/libpipi/trunk@4704 92316355-f0b4-4df1-b90c-862c8a59935fmaster
@@ -37,11 +37,17 @@ int main(int argc, char *argv[]) | |||||
pipi_pixels_t *p; | pipi_pixels_t *p; | ||||
uint8_t *dst[4], *data = NULL; | uint8_t *dst[4], *data = NULL; | ||||
char *parser; | char *parser; | ||||
int stream, pitch[4], i, k = 0; | |||||
int stream, pitch[4], i, k = 0, nframes = -1; | |||||
double skip_seconds = 0.0; | |||||
if(argc < 2) | |||||
if (argc < 2) | |||||
return EXIT_FAILURE; | return EXIT_FAILURE; | ||||
if (argc > 2) | |||||
skip_seconds = atof(argv[2]); | |||||
if (argc > 3) | |||||
nframes = atoi(argv[3]); | |||||
/* Ensure our linear YUV values do not get gamma-corrected */ | /* Ensure our linear YUV values do not get gamma-corrected */ | ||||
pipi_set_gamma(1.0); | pipi_set_gamma(1.0); | ||||
@@ -72,9 +78,14 @@ int main(int argc, char *argv[]) | |||||
if(avcodec_open(ctx, codec) < 0) | if(avcodec_open(ctx, codec) < 0) | ||||
return EXIT_FAILURE; | return EXIT_FAILURE; | ||||
skip_seconds /= av_q2d(fmt->streams[stream]->time_base); | |||||
av_seek_frame(fmt, stream, (int)(skip_seconds + 0.5), SEEK_SET); | |||||
//avformat_seek_file(fmt, stream, skip_bytes, skip_bytes, | |||||
// skip_bytes, AVSEEK_FLAG_BYTE); | |||||
frame = avcodec_alloc_frame(); | frame = avcodec_alloc_frame(); | ||||
for(;;) | |||||
for (k = 0; k < nframes || nframes == -1; /* k incremented below */) | |||||
{ | { | ||||
int finished, ret, x, y; | int finished, ret, x, y; | ||||
@@ -112,34 +123,37 @@ int main(int argc, char *argv[]) | |||||
image = pipi_new(ctx->width, ctx->height); | image = pipi_new(ctx->width, ctx->height); | ||||
} | } | ||||
sws_scale(sws, (uint8_t const **)frame->data, frame->linesize, 0, | |||||
ctx->height, dst, pitch); | |||||
{ | |||||
char buf[1024]; | |||||
sprintf(buf, fmtstr, k); | |||||
printf("saving in %s\n", buf); | |||||
p = pipi_get_pixels(image, PIPI_PIXELS_RGBA_U8); | |||||
data = (uint8_t *)p->pixels; | |||||
sws_scale(sws, (uint8_t const **)frame->data, frame->linesize, 0, | |||||
ctx->height, dst, pitch); | |||||
for (y = 0; y < ctx->height; y++) | |||||
{ | |||||
int off = y * ctx->width; | |||||
p = pipi_get_pixels(image, PIPI_PIXELS_RGBA_U8); | |||||
data = (uint8_t *)p->pixels; | |||||
for (x = 0; x < ctx->width; x++, off++) | |||||
for (y = 0; y < ctx->height; y++) | |||||
{ | { | ||||
/* Reorder components to store YUVA */ | |||||
data[4 * off] = dst[0][off]; | |||||
data[4 * off + 1] = dst[2][off]; | |||||
data[4 * off + 2] = dst[1][off]; | |||||
data[4 * off + 3] = 0xff; | |||||
int off = y * ctx->width; | |||||
for (x = 0; x < ctx->width; x++, off++) | |||||
{ | |||||
/* Reorder components to store YUVA */ | |||||
data[4 * off] = dst[0][off]; | |||||
data[4 * off + 1] = dst[2][off]; | |||||
data[4 * off + 2] = dst[1][off]; | |||||
data[4 * off + 3] = 0xff; | |||||
} | |||||
} | } | ||||
} | |||||
{ | |||||
char buf[1024]; | |||||
sprintf(buf, fmtstr, k++); | |||||
printf("saving in %s\n", buf); | |||||
pipi_save(image, buf); | pipi_save(image, buf); | ||||
} | } | ||||
av_free_packet(&packet); | av_free_packet(&packet); | ||||
k++; | |||||
} | } | ||||
return EXIT_SUCCESS; | return EXIT_SUCCESS; | ||||
@@ -85,6 +85,7 @@ struct pipi_image | |||||
struct pipi_sequence | struct pipi_sequence | ||||
{ | { | ||||
int w, h, fps; | int w, h, fps; | ||||
uint8_t *convert_buf; | |||||
void *codec_priv; | void *codec_priv; | ||||
}; | }; | ||||
@@ -69,6 +69,7 @@ pipi_sequence_t *pipi_open_sequence(char const *file, | |||||
seq->w = width; | seq->w = width; | ||||
seq->h = height; | seq->h = height; | ||||
seq->fps = fps; | seq->fps = fps; | ||||
seq->convert_buf = NULL; | |||||
ff = malloc(sizeof(ffmpeg_codec_t)); | ff = malloc(sizeof(ffmpeg_codec_t)); | ||||
memset(ff, 0, sizeof(*ff)); | memset(ff, 0, sizeof(*ff)); | ||||
@@ -200,8 +201,10 @@ int pipi_feed_sequence(pipi_sequence_t *seq, uint8_t const *buffer, | |||||
{ | { | ||||
#if defined USE_FFMPEG | #if defined USE_FFMPEG | ||||
AVPacket packet; | AVPacket packet; | ||||
uint8_t const *buflist[3]; | |||||
int pitchlist[3]; | |||||
size_t bytes; | size_t bytes; | ||||
int pitch; | |||||
int n; | |||||
ffmpeg_codec_t *ff = (ffmpeg_codec_t *)seq->codec_priv; | ffmpeg_codec_t *ff = (ffmpeg_codec_t *)seq->codec_priv; | ||||
@@ -215,16 +218,38 @@ int pipi_feed_sequence(pipi_sequence_t *seq, uint8_t const *buffer, | |||||
} | } | ||||
if (!ff->sws_ctx) | if (!ff->sws_ctx) | ||||
ff->sws_ctx = sws_getContext(width, height, PIX_FMT_RGB32, | |||||
ff->cod_ctx->width, | |||||
ff->cod_ctx->height, | |||||
ff->cod_ctx->pix_fmt, SWS_BICUBIC, | |||||
NULL, NULL, NULL); | |||||
{ | |||||
ff->sws_ctx = sws_getContext(width, height, PIX_FMT_YUV444P, | |||||
ff->cod_ctx->width, | |||||
ff->cod_ctx->height, | |||||
ff->cod_ctx->pix_fmt, SWS_BICUBIC, | |||||
NULL, NULL, NULL); | |||||
if (seq->convert_buf) | |||||
{ | |||||
free(seq->convert_buf); | |||||
seq->convert_buf = NULL; | |||||
} | |||||
} | |||||
if (!ff->sws_ctx) | if (!ff->sws_ctx) | ||||
return -1; | return -1; | ||||
pitch = width * 4; | |||||
sws_scale(ff->sws_ctx, &buffer, &pitch, 0, height, | |||||
/* Convert interleaved YUV to planar YUV */ | |||||
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]; | |||||
} | |||||
/* 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); | ff->frame->data, ff->frame->linesize); | ||||
bytes = avcodec_encode_video(ff->cod_ctx, ff->buf, | bytes = avcodec_encode_video(ff->cod_ctx, ff->buf, | ||||