for now, but it seems to work. git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/libpipi/trunk@3627 92316355-f0b4-4df1-b90c-862c8a59935fmaster
@@ -1,6 +1,6 @@ | |||
/* | |||
* makemovie read image names from stdin and create a movie | |||
* Copyright (c) 2009 Sam Hocevar <sam@zoy.org> | |||
* Copyright (c) 2009 Sam Hocevar <sam@hocevar.net> | |||
* All Rights Reserved | |||
* | |||
* $Id$ | |||
@@ -18,111 +18,31 @@ | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <libavformat/avformat.h> | |||
#include <libswscale/swscale.h> | |||
#include <pipi.h> | |||
/* These values define a 720x576 anamorphic widescreen image that gets | |||
* scaled to 1024x576 (16:9). */ | |||
#define WIDTH 720 | |||
#define HEIGHT 576 | |||
#define PAR_NUM 64 | |||
#define PAR_DEN 45 | |||
#define FPS 25 | |||
#define BITRATE 16*1024*1024 | |||
#define WIDTH 1280 | |||
#define HEIGHT 720 | |||
#define FPS 30 | |||
int main(int argc, char *argv[]) | |||
{ | |||
char file[1024]; | |||
AVPacket packet; | |||
AVFormatContext *fmt; | |||
AVCodecContext *ctx; | |||
AVStream *stream; | |||
AVCodec *codec; | |||
AVFrame *frame; | |||
struct SwsContext *sws = NULL; | |||
pipi_image_t *image; | |||
pipi_sequence_t *seq; | |||
pipi_pixels_t *p; | |||
uint8_t *buffer, *tmp; | |||
int f, len; | |||
int f; | |||
if(argc < 2) | |||
return EXIT_FAILURE; | |||
av_register_all(); | |||
fmt = avformat_alloc_context(); | |||
if(!fmt) | |||
return EXIT_FAILURE; | |||
snprintf(fmt->filename, sizeof(fmt->filename), "%s", argv[1]); | |||
fmt->oformat = guess_format(NULL, argv[1], NULL); | |||
if(!fmt->oformat) | |||
fmt->oformat = guess_format("mpeg", NULL, NULL); | |||
if(!fmt->oformat) | |||
return EXIT_FAILURE; | |||
stream = av_new_stream(fmt, 0); | |||
if(!stream) | |||
return EXIT_FAILURE; | |||
stream->sample_aspect_ratio.num = PAR_NUM; | |||
stream->sample_aspect_ratio.den = PAR_DEN; | |||
ctx = stream->codec; | |||
ctx->width = WIDTH; | |||
ctx->height = HEIGHT; | |||
ctx->sample_aspect_ratio.num = PAR_NUM; | |||
ctx->sample_aspect_ratio.den = PAR_DEN; | |||
ctx->codec_id = fmt->oformat->video_codec; | |||
//ctx->codec_id = CODEC_ID_FFV1; | |||
//ctx->codec_id = CODEC_ID_THEORA; | |||
//ctx->codec_id = CODEC_ID_SNOW; | |||
//ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; /* Snow */ | |||
//ctx->codec_id = CODEC_ID_MJPEG; | |||
ctx->codec_type = CODEC_TYPE_VIDEO; | |||
ctx->bit_rate = BITRATE; | |||
ctx->time_base.num = 1; | |||
ctx->time_base.den = FPS; /* 25 fps */ | |||
ctx->gop_size = FPS / 2; | |||
ctx->pix_fmt = PIX_FMT_YUV420P; /* send YUV 420 */ | |||
if(ctx->codec_id == CODEC_ID_MPEG2VIDEO) | |||
ctx->max_b_frames = 2; | |||
if(ctx->codec_id == CODEC_ID_MPEG1VIDEO) | |||
ctx->mb_decision = 2; | |||
if(fmt->oformat->flags & AVFMT_GLOBALHEADER) | |||
ctx->flags |= CODEC_FLAG_GLOBAL_HEADER; | |||
if(av_set_parameters(fmt, NULL) < 0) | |||
return EXIT_FAILURE; | |||
codec = avcodec_find_encoder(ctx->codec_id); | |||
if(!codec) | |||
return EXIT_FAILURE; | |||
if(avcodec_open(ctx, codec) < 0) | |||
return EXIT_FAILURE; | |||
frame = avcodec_alloc_frame(); | |||
if(!frame) | |||
return EXIT_FAILURE; | |||
tmp = av_malloc(avpicture_get_size(ctx->pix_fmt, ctx->width, ctx->height)); | |||
if(!tmp) | |||
seq = pipi_open_sequence(argv[1], WIDTH, HEIGHT, FPS); | |||
if(!seq) | |||
return EXIT_FAILURE; | |||
avpicture_fill((AVPicture *)frame, tmp, ctx->pix_fmt, | |||
ctx->width, ctx->height); | |||
if(!(fmt->flags & AVFMT_NOFILE)) | |||
if(url_fopen(&fmt->pb, argv[1], URL_WRONLY) < 0) | |||
return EXIT_FAILURE; | |||
len = 64 * 1024 * 1024; | |||
buffer = av_malloc(len); | |||
av_write_header(fmt); | |||
for(f = 0; ; f++) | |||
{ | |||
uint8_t *start; | |||
int w = 0, h = 0, bytes, pitch; | |||
int w = 0, h = 0; | |||
if(!fgets(file, sizeof(file), stdin)) | |||
break; | |||
@@ -133,61 +53,15 @@ int main(int argc, char *argv[]) | |||
return EXIT_FAILURE; | |||
p = pipi_get_pixels(image, PIPI_PIXELS_RGBA_U8); | |||
start = (uint8_t *)p->pixels; | |||
pitch = p->w * 4; | |||
if(w != p->w || h != p->h) | |||
{ | |||
w = p->w; | |||
h = p->h; | |||
if(sws) | |||
sws_freeContext(sws); | |||
sws = NULL; | |||
} | |||
if(!sws) | |||
sws = sws_getContext(w, h, PIX_FMT_RGB32, ctx->width, ctx->height, | |||
ctx->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL); | |||
sws_scale(sws, &start, &pitch, 0, h, frame->data, frame->linesize); | |||
pipi_feed_sequence(seq, start, p->w, p->h); | |||
pipi_free(image); | |||
bytes = avcodec_encode_video(ctx, buffer, len, frame); | |||
if(bytes <= 0) | |||
continue; | |||
av_init_packet(&packet); | |||
if(ctx->coded_frame->pts != (int64_t)AV_NOPTS_VALUE) | |||
packet.pts = av_rescale_q(ctx->coded_frame->pts, | |||
ctx->time_base, stream->time_base); | |||
if(ctx->coded_frame->key_frame) | |||
packet.flags |= PKT_FLAG_KEY; | |||
packet.stream_index = 0; | |||
packet.data = buffer; | |||
packet.size = bytes; | |||
if(av_interleaved_write_frame(fmt, &packet) < 0) | |||
return EXIT_FAILURE; | |||
fprintf(stderr, "frame %d\r", f); | |||
} | |||
fprintf(stderr, "\n"); | |||
av_write_trailer(fmt); | |||
avcodec_close(stream->codec); | |||
av_free(frame->data[0]); | |||
av_free(frame); | |||
av_free(buffer); | |||
av_freep(&fmt->streams[0]->codec); | |||
av_freep(&fmt->streams[0]); | |||
if(sws) | |||
sws_freeContext(sws); | |||
if(!(fmt->flags & AVFMT_NOFILE)) | |||
url_fclose(fmt->pb); | |||
av_free(fmt); | |||
pipi_close_sequence(seq); | |||
return EXIT_SUCCESS; | |||
} | |||
@@ -0,0 +1,192 @@ | |||
<?xml version="1.0" encoding="Windows-1252"?> | |||
<VisualStudioProject | |||
ProjectType="Visual C++" | |||
Version="9.00" | |||
Name="makemovie" | |||
ProjectGUID="{A65DC7CE-D5BF-4CB6-942F-C970076E68C9}" | |||
RootNamespace="makemovie" | |||
Keyword="Win32Proj" | |||
TargetFrameworkVersion="131072" | |||
> | |||
<Platforms> | |||
<Platform | |||
Name="Win32" | |||
/> | |||
</Platforms> | |||
<ToolFiles> | |||
</ToolFiles> | |||
<Configurations> | |||
<Configuration | |||
Name="Debug|Win32" | |||
OutputDirectory="$(SolutionDir)\win32\$(ConfigurationName)\bin" | |||
IntermediateDirectory="$(OutDir)\$(ProjectName)" | |||
ConfigurationType="1" | |||
CharacterSet="1" | |||
> | |||
<Tool | |||
Name="VCPreBuildEventTool" | |||
CommandLine="" | |||
/> | |||
<Tool | |||
Name="VCCustomBuildTool" | |||
/> | |||
<Tool | |||
Name="VCXMLDataGeneratorTool" | |||
/> | |||
<Tool | |||
Name="VCWebServiceProxyGeneratorTool" | |||
/> | |||
<Tool | |||
Name="VCMIDLTool" | |||
/> | |||
<Tool | |||
Name="VCCLCompilerTool" | |||
Optimization="0" | |||
AdditionalIncludeDirectories="..\win32;..\pipi;..\win32\ffmpeg\include" | |||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" | |||
MinimalRebuild="true" | |||
BasicRuntimeChecks="3" | |||
RuntimeLibrary="3" | |||
UsePrecompiledHeader="0" | |||
WarningLevel="3" | |||
Detect64BitPortabilityProblems="true" | |||
DebugInformationFormat="4" | |||
/> | |||
<Tool | |||
Name="VCManagedResourceCompilerTool" | |||
/> | |||
<Tool | |||
Name="VCResourceCompilerTool" | |||
/> | |||
<Tool | |||
Name="VCPreLinkEventTool" | |||
/> | |||
<Tool | |||
Name="VCLinkerTool" | |||
AdditionalDependencies="avutil-50.lib avformat-52.lib avcodec-52.lib swscale-0.lib" | |||
LinkIncremental="2" | |||
AdditionalLibraryDirectories="..\win32\ffmpeg\lib" | |||
GenerateDebugInformation="true" | |||
SubSystem="1" | |||
RandomizedBaseAddress="1" | |||
DataExecutionPrevention="0" | |||
TargetMachine="1" | |||
/> | |||
<Tool | |||
Name="VCALinkTool" | |||
/> | |||
<Tool | |||
Name="VCManifestTool" | |||
/> | |||
<Tool | |||
Name="VCXDCMakeTool" | |||
/> | |||
<Tool | |||
Name="VCBscMakeTool" | |||
/> | |||
<Tool | |||
Name="VCFxCopTool" | |||
/> | |||
<Tool | |||
Name="VCAppVerifierTool" | |||
/> | |||
<Tool | |||
Name="VCPostBuildEventTool" | |||
CommandLine="xcopy /Y /D $(SolutionDir)\win32\ffmpeg\lib\*.dll $(OutDir)" | |||
/> | |||
</Configuration> | |||
<Configuration | |||
Name="Release|Win32" | |||
OutputDirectory="$(SolutionDir)\win32\$(ConfigurationName)\bin" | |||
IntermediateDirectory="$(OutDir)\$(ProjectName)" | |||
ConfigurationType="1" | |||
CharacterSet="1" | |||
WholeProgramOptimization="1" | |||
> | |||
<Tool | |||
Name="VCPreBuildEventTool" | |||
CommandLine="" | |||
/> | |||
<Tool | |||
Name="VCCustomBuildTool" | |||
/> | |||
<Tool | |||
Name="VCXMLDataGeneratorTool" | |||
/> | |||
<Tool | |||
Name="VCWebServiceProxyGeneratorTool" | |||
/> | |||
<Tool | |||
Name="VCMIDLTool" | |||
/> | |||
<Tool | |||
Name="VCCLCompilerTool" | |||
AdditionalIncludeDirectories="..\win32;..\pipi;..\win32\ffmpeg\include" | |||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE" | |||
RuntimeLibrary="2" | |||
UsePrecompiledHeader="0" | |||
WarningLevel="3" | |||
Detect64BitPortabilityProblems="true" | |||
DebugInformationFormat="3" | |||
/> | |||
<Tool | |||
Name="VCManagedResourceCompilerTool" | |||
/> | |||
<Tool | |||
Name="VCResourceCompilerTool" | |||
/> | |||
<Tool | |||
Name="VCPreLinkEventTool" | |||
/> | |||
<Tool | |||
Name="VCLinkerTool" | |||
AdditionalDependencies="avutil-50.lib avformat-52.lib avcodec-52.lib swscale-0.lib" | |||
LinkIncremental="2" | |||
AdditionalLibraryDirectories="..\win32\ffmpeg\lib" | |||
GenerateDebugInformation="true" | |||
SubSystem="1" | |||
OptimizeReferences="2" | |||
EnableCOMDATFolding="2" | |||
RandomizedBaseAddress="1" | |||
DataExecutionPrevention="0" | |||
TargetMachine="1" | |||
/> | |||
<Tool | |||
Name="VCALinkTool" | |||
/> | |||
<Tool | |||
Name="VCManifestTool" | |||
/> | |||
<Tool | |||
Name="VCXDCMakeTool" | |||
/> | |||
<Tool | |||
Name="VCBscMakeTool" | |||
/> | |||
<Tool | |||
Name="VCFxCopTool" | |||
/> | |||
<Tool | |||
Name="VCAppVerifierTool" | |||
/> | |||
<Tool | |||
Name="VCPostBuildEventTool" | |||
CommandLine="xcopy /Y /D $(SolutionDir)\win32\ffmpeg\lib\*.dll $(OutDir)" | |||
/> | |||
</Configuration> | |||
</Configurations> | |||
<References> | |||
</References> | |||
<Files> | |||
<File | |||
RelativePath="..\win32\config.h" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\makemovie.c" | |||
> | |||
</File> | |||
</Files> | |||
<Globals> | |||
</Globals> | |||
</VisualStudioProject> |
@@ -0,0 +1,186 @@ | |||
<?xml version="1.0" encoding="Windows-1252"?> | |||
<VisualStudioProject | |||
ProjectType="Visual C++" | |||
Version="9.00" | |||
Name="sharpen" | |||
ProjectGUID="{D405CD0E-F47F-4C6E-9CB5-2B0F00E7C6D0}" | |||
RootNamespace="sharpen" | |||
Keyword="Win32Proj" | |||
TargetFrameworkVersion="131072" | |||
> | |||
<Platforms> | |||
<Platform | |||
Name="Win32" | |||
/> | |||
</Platforms> | |||
<ToolFiles> | |||
</ToolFiles> | |||
<Configurations> | |||
<Configuration | |||
Name="Debug|Win32" | |||
OutputDirectory="$(SolutionDir)/win32/$(ConfigurationName)/bin" | |||
IntermediateDirectory="$(OutDir)/$(ProjectName)" | |||
ConfigurationType="1" | |||
CharacterSet="1" | |||
> | |||
<Tool | |||
Name="VCPreBuildEventTool" | |||
CommandLine="" | |||
/> | |||
<Tool | |||
Name="VCCustomBuildTool" | |||
/> | |||
<Tool | |||
Name="VCXMLDataGeneratorTool" | |||
/> | |||
<Tool | |||
Name="VCWebServiceProxyGeneratorTool" | |||
/> | |||
<Tool | |||
Name="VCMIDLTool" | |||
/> | |||
<Tool | |||
Name="VCCLCompilerTool" | |||
Optimization="0" | |||
AdditionalIncludeDirectories="..\win32;..\pipi" | |||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" | |||
MinimalRebuild="true" | |||
BasicRuntimeChecks="3" | |||
RuntimeLibrary="3" | |||
UsePrecompiledHeader="0" | |||
WarningLevel="3" | |||
Detect64BitPortabilityProblems="true" | |||
DebugInformationFormat="4" | |||
/> | |||
<Tool | |||
Name="VCManagedResourceCompilerTool" | |||
/> | |||
<Tool | |||
Name="VCResourceCompilerTool" | |||
/> | |||
<Tool | |||
Name="VCPreLinkEventTool" | |||
/> | |||
<Tool | |||
Name="VCLinkerTool" | |||
LinkIncremental="2" | |||
GenerateDebugInformation="true" | |||
SubSystem="1" | |||
RandomizedBaseAddress="1" | |||
DataExecutionPrevention="0" | |||
TargetMachine="1" | |||
/> | |||
<Tool | |||
Name="VCALinkTool" | |||
/> | |||
<Tool | |||
Name="VCManifestTool" | |||
/> | |||
<Tool | |||
Name="VCXDCMakeTool" | |||
/> | |||
<Tool | |||
Name="VCBscMakeTool" | |||
/> | |||
<Tool | |||
Name="VCFxCopTool" | |||
/> | |||
<Tool | |||
Name="VCAppVerifierTool" | |||
/> | |||
<Tool | |||
Name="VCPostBuildEventTool" | |||
/> | |||
</Configuration> | |||
<Configuration | |||
Name="Release|Win32" | |||
OutputDirectory="$(SolutionDir)/win32/$(ConfigurationName)/bin" | |||
IntermediateDirectory="$(OutDir)/$(ProjectName)" | |||
ConfigurationType="1" | |||
CharacterSet="1" | |||
WholeProgramOptimization="1" | |||
> | |||
<Tool | |||
Name="VCPreBuildEventTool" | |||
CommandLine="" | |||
/> | |||
<Tool | |||
Name="VCCustomBuildTool" | |||
/> | |||
<Tool | |||
Name="VCXMLDataGeneratorTool" | |||
/> | |||
<Tool | |||
Name="VCWebServiceProxyGeneratorTool" | |||
/> | |||
<Tool | |||
Name="VCMIDLTool" | |||
/> | |||
<Tool | |||
Name="VCCLCompilerTool" | |||
AdditionalIncludeDirectories="..\win32;..\pipi" | |||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE" | |||
RuntimeLibrary="2" | |||
UsePrecompiledHeader="0" | |||
WarningLevel="3" | |||
Detect64BitPortabilityProblems="true" | |||
DebugInformationFormat="3" | |||
/> | |||
<Tool | |||
Name="VCManagedResourceCompilerTool" | |||
/> | |||
<Tool | |||
Name="VCResourceCompilerTool" | |||
/> | |||
<Tool | |||
Name="VCPreLinkEventTool" | |||
/> | |||
<Tool | |||
Name="VCLinkerTool" | |||
LinkIncremental="2" | |||
GenerateDebugInformation="true" | |||
SubSystem="1" | |||
OptimizeReferences="2" | |||
EnableCOMDATFolding="2" | |||
RandomizedBaseAddress="1" | |||
DataExecutionPrevention="0" | |||
TargetMachine="1" | |||
/> | |||
<Tool | |||
Name="VCALinkTool" | |||
/> | |||
<Tool | |||
Name="VCManifestTool" | |||
/> | |||
<Tool | |||
Name="VCXDCMakeTool" | |||
/> | |||
<Tool | |||
Name="VCBscMakeTool" | |||
/> | |||
<Tool | |||
Name="VCFxCopTool" | |||
/> | |||
<Tool | |||
Name="VCAppVerifierTool" | |||
/> | |||
<Tool | |||
Name="VCPostBuildEventTool" | |||
/> | |||
</Configuration> | |||
</Configurations> | |||
<References> | |||
</References> | |||
<Files> | |||
<File | |||
RelativePath="..\win32\config.h" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\sharpen.c" | |||
> | |||
</File> | |||
</Files> | |||
<Globals> | |||
</Globals> | |||
</VisualStudioProject> |
@@ -28,6 +28,7 @@ libpipi_la_SOURCES = \ | |||
resize.c \ | |||
dither.c \ | |||
accessors.c \ | |||
sequence.c \ | |||
$(codec_sources) \ | |||
$(paint_sources) \ | |||
$(render_sources) \ | |||
@@ -18,8 +18,8 @@ | |||
<Configurations> | |||
<Configuration | |||
Name="Debug|Win32" | |||
OutputDirectory="$(SolutionDir)/win32/$(ConfigurationName)/bin" | |||
IntermediateDirectory="$(OutDir)/$(ProjectName)" | |||
OutputDirectory="$(SolutionDir)\win32\$(ConfigurationName)\bin" | |||
IntermediateDirectory="$(OutDir)\$(ProjectName)" | |||
ConfigurationType="2" | |||
> | |||
<Tool | |||
@@ -40,7 +40,7 @@ | |||
<Tool | |||
Name="VCCLCompilerTool" | |||
Optimization="0" | |||
AdditionalIncludeDirectories="..\win32;.;.." | |||
AdditionalIncludeDirectories="..\win32;..\win32\ffmpeg\include" | |||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBPIPI_EXPORTS;__LIBPIPI__" | |||
MinimalRebuild="true" | |||
BasicRuntimeChecks="3" | |||
@@ -61,9 +61,10 @@ | |||
/> | |||
<Tool | |||
Name="VCLinkerTool" | |||
AdditionalDependencies="gdiplus.lib gdi32.lib user32.lib" | |||
AdditionalDependencies="gdiplus.lib gdi32.lib user32.lib avutil-50.lib avformat-52.lib avcodec-52.lib swscale-0.lib" | |||
OutputFile="$(OutDir)\$(ProjectName)-0.dll" | |||
LinkIncremental="2" | |||
AdditionalLibraryDirectories="..\win32\ffmpeg\lib" | |||
GenerateDebugInformation="true" | |||
SubSystem="2" | |||
RandomizedBaseAddress="1" | |||
@@ -90,12 +91,13 @@ | |||
/> | |||
<Tool | |||
Name="VCPostBuildEventTool" | |||
CommandLine="xcopy /Y /D $(SolutionDir)\win32\ffmpeg\lib\*.dll $(OutDir)" | |||
/> | |||
</Configuration> | |||
<Configuration | |||
Name="Release|Win32" | |||
OutputDirectory="$(SolutionDir)/win32/$(ConfigurationName)/bin" | |||
IntermediateDirectory="$(OutDir)/$(ProjectName)" | |||
OutputDirectory="$(SolutionDir)\win32\$(ConfigurationName)\bin" | |||
IntermediateDirectory="$(OutDir)\$(ProjectName)" | |||
ConfigurationType="2" | |||
> | |||
<Tool | |||
@@ -115,7 +117,7 @@ | |||
/> | |||
<Tool | |||
Name="VCCLCompilerTool" | |||
AdditionalIncludeDirectories="..\win32;.;.." | |||
AdditionalIncludeDirectories="..\win32;..;.;..\win32\ffmpeg\include" | |||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBPIPI_EXPORTS;__LIBPIPI__" | |||
RuntimeLibrary="2" | |||
UsePrecompiledHeader="0" | |||
@@ -134,9 +136,10 @@ | |||
/> | |||
<Tool | |||
Name="VCLinkerTool" | |||
AdditionalDependencies="gdiplus.lib gdi32.lib user32.lib" | |||
AdditionalDependencies="gdiplus.lib gdi32.lib user32.lib avutil-50.lib avformat-52.lib avcodec-52.lib swscale-0.lib" | |||
OutputFile="$(OutDir)\$(ProjectName)-0.dll" | |||
LinkIncremental="2" | |||
AdditionalLibraryDirectories="..\win32\ffmpeg\lib" | |||
GenerateDebugInformation="true" | |||
SubSystem="2" | |||
OptimizeReferences="2" | |||
@@ -165,6 +168,7 @@ | |||
/> | |||
<Tool | |||
Name="VCPostBuildEventTool" | |||
CommandLine="xcopy /Y /D $(SolutionDir)\win32\ffmpeg\lib\*.dll $(OutDir)" | |||
/> | |||
</Configuration> | |||
</Configurations> | |||
@@ -238,6 +242,10 @@ | |||
RelativePath=".\resize.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\sequence.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\stock.c" | |||
> | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* libpipi Pathetic image processing interface library | |||
* Copyright (c) 2004-2008 Sam Hocevar <sam@zoy.org> | |||
* Copyright (c) 2004-2009 Sam Hocevar <sam@hocevar.net> | |||
* 2008 Jean-Yves Lamoureux <jylam@lnxscene.org | |||
* All Rights Reserved | |||
* | |||
@@ -107,6 +107,9 @@ typedef struct pipi_tile pipi_tile_t; | |||
/* pipi_image_t: the main image type */ | |||
typedef struct pipi_image pipi_image_t; | |||
/* pipi_sequence_t: the image sequence type */ | |||
typedef struct pipi_sequence pipi_sequence_t; | |||
/* pipi_context_t: the processing stack */ | |||
typedef struct pipi_context pipi_context_t; | |||
@@ -234,6 +237,10 @@ __extern int pipi_get_image_histogram(pipi_image_t *, pipi_histogram_t *, int); | |||
__extern int pipi_free_histogram(pipi_histogram_t*); | |||
__extern int pipi_render_histogram(pipi_image_t *, pipi_histogram_t*, int); | |||
__extern pipi_sequence_t *pipi_open_sequence(char *, int, int, int); | |||
__extern int pipi_feed_sequence(pipi_sequence_t *, uint8_t *, int, int); | |||
__extern int pipi_close_sequence(pipi_sequence_t *); | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* libpipi Pathetic image processing interface library | |||
* Copyright (c) 2004-2008 Sam Hocevar <sam@zoy.org> | |||
* Copyright (c) 2004-2009 Sam Hocevar <sam@hocevar.net> | |||
* All Rights Reserved | |||
* | |||
* $Id$ | |||
@@ -82,6 +82,13 @@ struct pipi_image | |||
int (*codec_free)(pipi_image_t *); | |||
}; | |||
struct pipi_sequence | |||
{ | |||
int w, h, fps; | |||
void *codec_priv; | |||
}; | |||
struct pipi_context | |||
{ | |||
int nimages; | |||
@@ -0,0 +1,279 @@ | |||
/* | |||
* libpipi Pathetic image processing interface library | |||
* Copyright (c) 2004-2009 Sam Hocevar <sam@hocevar.net> | |||
* All Rights Reserved | |||
* | |||
* $Id$ | |||
* | |||
* This library is free software. It comes without any warranty, to | |||
* the extent permitted by applicable law. You can redistribute it | |||
* and/or modify it under the terms of the Do What The Fuck You Want | |||
* To Public License, Version 2, as published by Sam Hocevar. See | |||
* http://sam.zoy.org/wtfpl/COPYING for more details. | |||
*/ | |||
/* | |||
* codec.c: image I/O functions | |||
*/ | |||
#include "config.h" | |||
#if defined _WIN32 | |||
# undef _CRT_SECURE_NO_WARNINGS | |||
# define _CRT_SECURE_NO_WARNINGS /* I know how to use snprintf, thank you */ | |||
# define snprintf _snprintf | |||
#endif | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#if defined USE_FFMPEG | |||
# include <libavformat/avformat.h> | |||
# include <libswscale/swscale.h> | |||
#endif | |||
#include "pipi.h" | |||
#include "pipi_internals.h" | |||
#if defined USE_FFMPEG | |||
typedef struct | |||
{ | |||
uint8_t *buf; | |||
size_t buf_len; | |||
AVFormatContext *fmt_ctx; | |||
AVStream *stream; | |||
AVCodecContext *cod_ctx; | |||
AVCodec *codec; | |||
AVFrame *frame; | |||
struct SwsContext *sws_ctx; | |||
int src_width, src_height; | |||
} | |||
ffmpeg_codec_t; | |||
#endif | |||
#define PAR_NUM 1 | |||
#define PAR_DEN 1 | |||
#define BITRATE (16 * 1024 * 1024) | |||
pipi_sequence_t *pipi_open_sequence(char *file, int width, int height, int fps) | |||
{ | |||
#if defined USE_FFMPEG | |||
static int initialised = 0; | |||
pipi_sequence_t *seq; | |||
ffmpeg_codec_t *ff; | |||
uint8_t *tmp; | |||
seq = malloc(sizeof(pipi_sequence_t)); | |||
seq->w = width; | |||
seq->h = height; | |||
seq->fps = fps; | |||
ff = malloc(sizeof(ffmpeg_codec_t)); | |||
memset(ff, 0, sizeof(*ff)); | |||
seq->codec_priv = ff; | |||
if (!initialised) | |||
{ | |||
av_register_all(); | |||
initialised = 1; | |||
} | |||
ff->fmt_ctx = avformat_alloc_context(); | |||
if (!ff->fmt_ctx) | |||
goto error; | |||
/* Careful here: the Win32 snprintf doesn't seem to add a trailing | |||
* zero to the truncated output. */ | |||
snprintf(ff->fmt_ctx->filename, sizeof(ff->fmt_ctx->filename), | |||
file); | |||
ff->fmt_ctx->filename[sizeof(ff->fmt_ctx->filename) - 1] = '\0'; | |||
ff->fmt_ctx->oformat = guess_format(NULL, file, NULL); | |||
if (!ff->fmt_ctx->oformat) | |||
ff->fmt_ctx->oformat = guess_format("mpeg", NULL, NULL); | |||
if (!ff->fmt_ctx->oformat) | |||
goto error; | |||
ff->stream = av_new_stream(ff->fmt_ctx, 0); | |||
if (!ff->stream) | |||
goto error; | |||
ff->stream->sample_aspect_ratio.num = PAR_NUM; | |||
ff->stream->sample_aspect_ratio.den = PAR_DEN; | |||
ff->cod_ctx = ff->stream->codec; | |||
ff->cod_ctx->width = width; | |||
ff->cod_ctx->height = height; | |||
ff->cod_ctx->sample_aspect_ratio.num = PAR_NUM; | |||
ff->cod_ctx->sample_aspect_ratio.den = PAR_DEN; | |||
ff->cod_ctx->codec_id = ff->fmt_ctx->oformat->video_codec; | |||
ff->cod_ctx->codec_type = CODEC_TYPE_VIDEO; | |||
ff->cod_ctx->bit_rate = BITRATE; | |||
ff->cod_ctx->time_base.num = 1; | |||
ff->cod_ctx->time_base.den = fps; | |||
ff->cod_ctx->gop_size = fps * 3 / 4; /* empirical */ | |||
ff->cod_ctx->pix_fmt = PIX_FMT_YUV420P; /* send YUV 420 */ | |||
if (ff->cod_ctx->codec_id == CODEC_ID_MPEG2VIDEO) | |||
ff->cod_ctx->max_b_frames = 2; | |||
if (ff->cod_ctx->codec_id == CODEC_ID_MPEG1VIDEO) | |||
ff->cod_ctx->mb_decision = 2; | |||
if (ff->fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) | |||
ff->cod_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER; | |||
if (av_set_parameters(ff->fmt_ctx, NULL) < 0) | |||
goto error; | |||
ff->codec = avcodec_find_encoder(ff->cod_ctx->codec_id); | |||
if (!ff->codec) | |||
goto error; | |||
if (avcodec_open(ff->cod_ctx, ff->codec) < 0) | |||
goto error; | |||
ff->frame = avcodec_alloc_frame(); | |||
if (!ff->frame) | |||
goto error; | |||
tmp = (uint8_t *)av_malloc(avpicture_get_size(ff->cod_ctx->pix_fmt, | |||
ff->cod_ctx->width, | |||
ff->cod_ctx->height)); | |||
if (!tmp) | |||
goto error; | |||
avpicture_fill((AVPicture *)ff->frame, tmp, ff->cod_ctx->pix_fmt, | |||
ff->cod_ctx->width, ff->cod_ctx->height); | |||
if (!(ff->fmt_ctx->flags & AVFMT_NOFILE)) | |||
if (url_fopen(&ff->fmt_ctx->pb, file, URL_WRONLY) < 0) | |||
goto error; | |||
ff->buf_len = 64 * 1024 * 1024; | |||
ff->buf = (uint8_t *)av_malloc(ff->buf_len); | |||
av_write_header(ff->fmt_ctx); | |||
return seq; | |||
error: | |||
pipi_close_sequence(seq); | |||
return NULL; | |||
#else | |||
return NULL; | |||
#endif | |||
} | |||
int pipi_feed_sequence(pipi_sequence_t *seq, uint8_t *buffer, int width, int height) | |||
{ | |||
#if defined USE_FFMPEG | |||
AVPacket packet; | |||
size_t bytes; | |||
int pitch; | |||
ffmpeg_codec_t *ff = (ffmpeg_codec_t *)seq->codec_priv; | |||
if (ff->src_width != width || ff->src_height != height) | |||
{ | |||
ff->src_width = width; | |||
ff->src_height = height; | |||
if (ff->sws_ctx) | |||
sws_freeContext(ff->sws_ctx); | |||
ff->sws_ctx = NULL; | |||
} | |||
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); | |||
if (!ff->sws_ctx) | |||
return -1; | |||
pitch = width * 4; | |||
sws_scale(ff->sws_ctx, &buffer, &pitch, 0, height, | |||
ff->frame->data, ff->frame->linesize); | |||
bytes = avcodec_encode_video(ff->cod_ctx, ff->buf, | |||
ff->buf_len, ff->frame); | |||
if (bytes <= 0) | |||
return 0; | |||
av_init_packet(&packet); | |||
if (ff->cod_ctx->coded_frame->pts != 0x8000000000000000LL) | |||
packet.pts = av_rescale_q(ff->cod_ctx->coded_frame->pts, | |||
ff->cod_ctx->time_base, ff->stream->time_base); | |||
if (ff->cod_ctx->coded_frame->key_frame) | |||
packet.flags |= PKT_FLAG_KEY; | |||
packet.stream_index = 0; | |||
packet.data = ff->buf; | |||
packet.size = bytes; | |||
if (av_interleaved_write_frame(ff->fmt_ctx, &packet) < 0) | |||
return -1; | |||
#endif | |||
return 0; | |||
} | |||
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) | |||
{ | |||
av_write_trailer(ff->fmt_ctx); | |||
} | |||
if (ff->buf) | |||
{ | |||
av_free(ff->buf); | |||
ff->buf = NULL; | |||
} | |||
if (ff->cod_ctx) | |||
{ | |||
avcodec_close(ff->cod_ctx); | |||
ff->cod_ctx = NULL; | |||
} | |||
if (ff->frame) | |||
{ | |||
av_free(ff->frame->data[0]); | |||
av_free(ff->frame); | |||
ff->frame = NULL; | |||
} | |||
if (ff->fmt_ctx) | |||
{ | |||
av_freep(&ff->fmt_ctx->streams[0]->codec); | |||
ff->codec = NULL; | |||
av_freep(&ff->fmt_ctx->streams[0]); | |||
ff->stream = NULL; | |||
if (!(ff->fmt_ctx->flags & AVFMT_NOFILE)) | |||
url_fclose(ff->fmt_ctx->pb); | |||
av_free(ff->fmt_ctx); | |||
ff->fmt_ctx = NULL; | |||
} | |||
if (ff->sws_ctx) | |||
{ | |||
sws_freeContext(ff->sws_ctx); | |||
ff->sws_ctx = NULL; | |||
ff->src_width = ff->src_height = 0; | |||
} | |||
free(ff); | |||
free(seq); | |||
#endif | |||
return 0; | |||
} |
@@ -43,6 +43,7 @@ | |||
#define USE_GDI 1 | |||
#define USE_GDIPLUS 1 | |||
/* #undef USE_COCOA */ | |||
#define USE_FFMPEG 1 | |||
/* #undef const */ | |||
#ifndef __cplusplus | |||
#define inline __inline | |||