ffmpeg resize

This commit is contained in:
Ciro Santilli 2016-04-07 18:02:20 +02:00
parent 018b98dc49
commit d74d415dda
8 changed files with 286 additions and 13 deletions

View File

@ -1,7 +1,8 @@
# FFmpeg # FFmpeg
1. Examples 1. Examples
1. [] 1. [encode](encode.c)
1. [resize](resize.c)
1. Theory 1. Theory
1. [Introduction](introduction.md) 1. [Introduction](introduction.md)
1. [libav](libav.md) 1. [libav](libav.md)

View File

@ -41,7 +41,7 @@ static void ffmpeg_encoder_set_frame_yuv_from_rgb(uint8_t *rgb) {
sws_context = sws_getCachedContext(sws_context, sws_context = sws_getCachedContext(sws_context,
c->width, c->height, AV_PIX_FMT_RGB24, c->width, c->height, AV_PIX_FMT_RGB24,
c->width, c->height, AV_PIX_FMT_YUV420P, c->width, c->height, AV_PIX_FMT_YUV420P,
0, 0, 0, 0); 0, NULL, NULL, NULL);
sws_scale(sws_context, (const uint8_t * const *)&rgb, in_linesize, 0, sws_scale(sws_context, (const uint8_t * const *)&rgb, in_linesize, 0,
c->height, frame->data, frame->linesize); c->height, frame->data, frame->linesize);
} }
@ -151,7 +151,7 @@ void ffmpeg_encoder_start(const char *filename, int codec_id, int fps, int width
frame->format = c->pix_fmt; frame->format = c->pix_fmt;
frame->width = c->width; frame->width = c->width;
frame->height = c->height; frame->height = c->height;
ret = av_image_alloc(frame->data, frame->linesize, c->width, c->height, c->pix_fmt, 32); ret = av_image_alloc(frame->data, frame->linesize, frame->width, frame->height, frame->format, 32);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "Could not allocate raw picture buffer\n"); fprintf(stderr, "Could not allocate raw picture buffer\n");
exit(1); exit(1);

210
ffmpeg/resize.c Normal file
View File

@ -0,0 +1,210 @@
/*
http://stackoverflow.com/questions/12831761/how-to-resize-a-picture-using-ffmpegs-sws-scale
Upstream: encode.c
*/
#include <libavcodec/avcodec.h>
#include <libavutil/imgutils.h>
#include <libavutil/opt.h>
#include <libswscale/swscale.h>
static AVCodecContext *c = NULL;
static AVFrame *frame;
static AVFrame *frame2;
static AVPacket pkt;
static FILE *file;
static struct SwsContext *sws_context = NULL;
static void ffmpeg_encoder_init_frame(AVFrame **framep, int width, int height) {
int ret;
AVFrame *frame;
frame = av_frame_alloc();
if (!frame) {
fprintf(stderr, "Could not allocate video frame\n");
exit(1);
}
frame->format = c->pix_fmt;
frame->width = width;
frame->height = height;
ret = av_image_alloc(frame->data, frame->linesize, frame->width, frame->height, frame->format, 32);
if (ret < 0) {
fprintf(stderr, "Could not allocate raw picture buffer\n");
exit(1);
}
*framep = frame;
}
static void ffmpeg_encoder_scale(uint8_t *rgb) {
sws_context = sws_getCachedContext(sws_context,
frame->width, frame->height, AV_PIX_FMT_YUV420P,
frame2->width, frame2->height, AV_PIX_FMT_YUV420P,
SWS_BICUBIC, NULL, NULL, NULL);
sws_scale(sws_context, (const uint8_t * const *)frame->data, frame->linesize, 0,
frame->height, frame2->data, frame2->linesize);
}
static void ffmpeg_encoder_set_frame_yuv_from_rgb(uint8_t *rgb) {
const int in_linesize[1] = { 3 * frame->width };
sws_context = sws_getCachedContext(sws_context,
frame->width, frame->height, AV_PIX_FMT_RGB24,
frame->width, frame->height, AV_PIX_FMT_YUV420P,
0, NULL, NULL, NULL);
sws_scale(sws_context, (const uint8_t * const *)&rgb, in_linesize, 0,
frame->height, frame->data, frame->linesize);
}
void generate_rgb(int width, int height, int pts, uint8_t **rgbp) {
int x, y, cur;
uint8_t *rgb = *rgbp;
rgb = realloc(rgb, 3 * sizeof(uint8_t) * height * width);
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
cur = 3 * (y * width + x);
rgb[cur + 0] = 0;
rgb[cur + 1] = 0;
rgb[cur + 2] = 0;
if ((frame->pts / 25) % 2 == 0) {
if (y < height / 2) {
if (x < width / 2) {
/* Black. */
} else {
rgb[cur + 0] = 255;
}
} else {
if (x < width / 2) {
rgb[cur + 1] = 255;
} else {
rgb[cur + 2] = 255;
}
}
} else {
if (y < height / 2) {
rgb[cur + 0] = 255;
if (x < width / 2) {
rgb[cur + 1] = 255;
} else {
rgb[cur + 2] = 255;
}
} else {
if (x < width / 2) {
rgb[cur + 1] = 255;
rgb[cur + 2] = 255;
} else {
rgb[cur + 0] = 255;
rgb[cur + 1] = 255;
rgb[cur + 2] = 255;
}
}
}
}
}
*rgbp = rgb;
}
void ffmpeg_encoder_start(const char *filename, int codec_id, int fps, int width, int height, float factor) {
AVCodec *codec;
int ret;
int width2 = width * factor;
int height2 = height * factor;
avcodec_register_all();
codec = avcodec_find_encoder(codec_id);
if (!codec) {
fprintf(stderr, "Codec not found\n");
exit(1);
}
c = avcodec_alloc_context3(codec);
if (!c) {
fprintf(stderr, "Could not allocate video codec context\n");
exit(1);
}
c->bit_rate = 400000;
c->width = width2;
c->height = height2;
c->time_base.num = 1;
c->time_base.den = fps;
c->gop_size = 10;
c->max_b_frames = 1;
c->pix_fmt = AV_PIX_FMT_YUV420P;
if (codec_id == AV_CODEC_ID_H264)
av_opt_set(c->priv_data, "preset", "slow", 0);
if (avcodec_open2(c, codec, NULL) < 0) {
fprintf(stderr, "Could not open codec\n");
exit(1);
}
file = fopen(filename, "wb");
if (!file) {
fprintf(stderr, "Could not open %s\n", filename);
exit(1);
}
ffmpeg_encoder_init_frame(&frame, width, height);
ffmpeg_encoder_init_frame(&frame2, width2, height2);
}
void ffmpeg_encoder_finish(void) {
uint8_t endcode[] = { 0, 0, 1, 0xb7 };
int got_output, ret;
do {
fflush(stdout);
ret = avcodec_encode_video2(c, &pkt, NULL, &got_output);
if (ret < 0) {
fprintf(stderr, "Error encoding frame\n");
exit(1);
}
if (got_output) {
fwrite(pkt.data, 1, pkt.size, file);
av_packet_unref(&pkt);
}
} while (got_output);
fwrite(endcode, 1, sizeof(endcode), file);
fclose(file);
avcodec_close(c);
av_free(c);
av_freep(&frame->data[0]);
av_frame_free(&frame);
av_freep(&frame2->data[0]);
av_frame_free(&frame2);
}
void ffmpeg_encoder_encode_frame(uint8_t *rgb) {
int ret, got_output;
ffmpeg_encoder_set_frame_yuv_from_rgb(rgb);
ffmpeg_encoder_scale(rgb);
frame2->pts = frame->pts;
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
ret = avcodec_encode_video2(c, &pkt, frame2, &got_output);
if (ret < 0) {
fprintf(stderr, "Error encoding frame\n");
exit(1);
}
if (got_output) {
fwrite(pkt.data, 1, pkt.size, file);
av_packet_unref(&pkt);
}
}
static void encode_example(float factor) {
char filename[255];
int pts;
int width = 320;
int height = 240;
uint8_t *rgb = NULL;
snprintf(filename, 255, "tmp." __FILE__ ".%.2f.h264", factor);
ffmpeg_encoder_start(filename, AV_CODEC_ID_H264, 25, width, height, factor);
for (pts = 0; pts < 100; pts++) {
frame->pts = pts;
generate_rgb(width, height, pts, &rgb);
ffmpeg_encoder_encode_frame(rgb);
}
ffmpeg_encoder_finish();
free(rgb);
}
int main(void) {
encode_example(0.5);
encode_example(1.0);
encode_example(2.0);
return EXIT_SUCCESS;
}

View File

@ -14,6 +14,7 @@
1. [Introduction](introduction.md) 1. [Introduction](introduction.md)
1. [Implementations](implementations.md) 1. [Implementations](implementations.md)
1. [Alternatives](alternatives.md) 1. [Alternatives](alternatives.md)
1. [CUDA](cuda.md)
1. [Architecture](architecture.md) 1. [Architecture](architecture.md)
1. [C](c.md) 1. [C](c.md)
1. [Host API](host-api.md) 1. [Host API](host-api.md)

View File

@ -1,17 +1,29 @@
# Alternatives # Alternatives
## CUDA As of 2016, CUDA is the top cat.
NVIDIA's. More closed since controlled by NVIDIA. Also more popular for the same reason as they are the Top Dog now.
<https://www.reddit.com/r/programming/comments/49uw97/cuda_reverse_engineered_to_run_on_nonnvidia/>
<https://en.wikipedia.org/wiki/CUDA> NVIDIA's, only runs in NVIDIA hardware. TODO could AMD implement it legally without paying royalties to NVIDIA?
## OpenMP ## OpenMP
<http://stackoverflow.com/questions/7263193/opencl-performance-vs-openmp> <http://stackoverflow.com/questions/7263193/opencl-performance-vs-openmp>
Directive based: you write stuff like:
http://stackoverflow.com/questions/19494786/openacc-vs-openmp-mpi-differences
/* Fork a team of threads giving them their own copies of variables */
#pragma omp parallel private(nthreads, tid)
{
/* Obtain thread number */
tid = omp_get_thread_num();
instead of compiling a kernel.
## OpenACC
<https://en.wikipedia.org/wiki/OpenACC>
NVIDIA's OpenMP, similar to OpenMP: <http://stackoverflow.com/questions/19494786/openacc-vs-openmp-mpi-differences>
## RenderScript ## RenderScript
Google's choice for Android: <http://stackoverflow.com/questions/14385843/why-did-google-choose-renderscript-instead-of-opencl> Google's choice for Android: <http://stackoverflow.com/questions/14385843/why-did-google-choose-renderscript-instead-of-opencl>
@ -42,5 +54,10 @@ Microsoft's
## Unified parallel C ## Unified parallel C
- <https://en.wikipedia.org/wiki/Unified_Parallel_C> <https://en.wikipedia.org/wiki/Unified_Parallel_C>
- OpenGL compute shaders <http://stackoverflow.com/questions/15868498/what-is-the-difference-between-opencl-and-opengls-compute-shader>
## Compute shaders
OpenGL compute shaders <http://stackoverflow.com/questions/15868498/what-is-the-difference-between-opencl-and-opengls-compute-shader>
Easier to integrate with graphics stuff.

View File

@ -23,7 +23,7 @@ Not surprising, since rendering is just a bunch of matrix multiplications, with
Sparse: <http://stackoverflow.com/questions/3438826/sparse-matrix-multiplication-on-gpu-or-cpu> Sparse: <http://stackoverflow.com/questions/3438826/sparse-matrix-multiplication-on-gpu-or-cpu>
Bolt: C++ STL GPU powered implementation by AMD: <http://developer.amd.com/tools-and-sdks/opencl-zone/bolt-c-template-library/> Bolt: C++ STL GPU powered implementation by AMD: <http://developer.amd.com/tools-and-sdks/opencl-zone/bolt-c-template-library/> Other suggestions: <http://stackoverflow.com/questions/16438099/high-level-gpu-programming-in-c>
## Non-applications ## Non-applications

35
opencl/cuda.md Normal file
View File

@ -0,0 +1,35 @@
# CUDA
NVIDIA's. More closed since controlled by NVIDIA. Also more popular for the same reason as they are the Top Dog now.
## Run on AMD
<https://www.reddit.com/r/programming/comments/49uw97/cuda_reverse_engineered_to_run_on_nonnvidia/>
<https://en.wikipedia.org/wiki/CUDA> NVIDIA's, currently only runs in NVIDIA hardware: <http://stackoverflow.com/questions/12828268/is-it-possible-to-run-cuda-on-amd-gpus>
TODO could AMD implement it legally without paying royalties to NVIDIA? Seems yes: <https://www.reddit.com/r/MachineLearning/comments/4di4os/deep_learning_is_so_dependent_on_nvidia_are_there/d1rwuxb>
Vulkan also adds the ability to run SPIR-V. So it is likely that SPIR-V will be well supported in NVIDIA and AMD cards, and we could then compile CUDA to SPIR-V. Result: AMD can run CUDA, and NVIDIA can run OpenCL.
<https://www.reddit.com/r/vulkan/comments/3snrdv/vulkan_or_opencl/>
If GPUCC generates SPIR-V, problem solved. TODO does it?
## GPUCC
LLVM-based CUDA compiler. TODO output format?
http://wujingyue.github.io/docs/gpucc-talk.pdf https://www.youtube.com/watch?v=JHfb8z-iSYk
http://gpuocelot.gatech.edu/ is a precursor it seems https://code.google.com/archive/p/gpuocelot/
## nvcc
<https://en.wikipedia.org/wiki/NVIDIA_CUDA_Compiler>
## CUDA C/C++
The kernel language, like OpenCL C.
Vs ISO: http://stackoverflow.com/questions/9846523/explanation-of-cuda-c-and-c

View File

@ -1,6 +1,15 @@
/* /*
Plot 2D function of time. Plot 2D function of time.
TODO possible to do it faster? Just the loop without anything inside
and only FPS calculation and no optimization max out at 70 FPS already.
Look into surfaces, textures.
- http://stackoverflow.com/questions/20753726/rendering-pixels-from-array-of-rgb-values-in-sdl-1-2
- http://stackoverflow.com/questions/28279242/how-to-render-a-pixel-array-most-efficiently-to-a-window-in-c
- http://stackoverflow.com/questions/20348616/how-to-create-a-color-gradient-in-sdl
- http://stackoverflow.com/questions/21392755/difference-between-surface-and-texture-sdl-general
TODO: get vsync right. TODO: get vsync right.
*/ */