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 | * 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 | * All Rights Reserved | ||||
* | * | ||||
* $Id$ | * $Id$ | ||||
@@ -18,111 +18,31 @@ | |||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <libavformat/avformat.h> | |||||
#include <libswscale/swscale.h> | |||||
#include <pipi.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[]) | int main(int argc, char *argv[]) | ||||
{ | { | ||||
char file[1024]; | char file[1024]; | ||||
AVPacket packet; | |||||
AVFormatContext *fmt; | |||||
AVCodecContext *ctx; | |||||
AVStream *stream; | |||||
AVCodec *codec; | |||||
AVFrame *frame; | |||||
struct SwsContext *sws = NULL; | |||||
pipi_image_t *image; | pipi_image_t *image; | ||||
pipi_sequence_t *seq; | |||||
pipi_pixels_t *p; | pipi_pixels_t *p; | ||||
uint8_t *buffer, *tmp; | |||||
int f, len; | |||||
int f; | |||||
if(argc < 2) | if(argc < 2) | ||||
return EXIT_FAILURE; | 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; | 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++) | for(f = 0; ; f++) | ||||
{ | { | ||||
uint8_t *start; | uint8_t *start; | ||||
int w = 0, h = 0, bytes, pitch; | |||||
int w = 0, h = 0; | |||||
if(!fgets(file, sizeof(file), stdin)) | if(!fgets(file, sizeof(file), stdin)) | ||||
break; | break; | ||||
@@ -133,61 +53,15 @@ int main(int argc, char *argv[]) | |||||
return EXIT_FAILURE; | return EXIT_FAILURE; | ||||
p = pipi_get_pixels(image, PIPI_PIXELS_RGBA_U8); | p = pipi_get_pixels(image, PIPI_PIXELS_RGBA_U8); | ||||
start = (uint8_t *)p->pixels; | 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); | 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, "frame %d\r", f); | ||||
} | } | ||||
fprintf(stderr, "\n"); | 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; | 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 \ | resize.c \ | ||||
dither.c \ | dither.c \ | ||||
accessors.c \ | accessors.c \ | ||||
sequence.c \ | |||||
$(codec_sources) \ | $(codec_sources) \ | ||||
$(paint_sources) \ | $(paint_sources) \ | ||||
$(render_sources) \ | $(render_sources) \ | ||||
@@ -18,8 +18,8 @@ | |||||
<Configurations> | <Configurations> | ||||
<Configuration | <Configuration | ||||
Name="Debug|Win32" | Name="Debug|Win32" | ||||
OutputDirectory="$(SolutionDir)/win32/$(ConfigurationName)/bin" | |||||
IntermediateDirectory="$(OutDir)/$(ProjectName)" | |||||
OutputDirectory="$(SolutionDir)\win32\$(ConfigurationName)\bin" | |||||
IntermediateDirectory="$(OutDir)\$(ProjectName)" | |||||
ConfigurationType="2" | ConfigurationType="2" | ||||
> | > | ||||
<Tool | <Tool | ||||
@@ -40,7 +40,7 @@ | |||||
<Tool | <Tool | ||||
Name="VCCLCompilerTool" | Name="VCCLCompilerTool" | ||||
Optimization="0" | Optimization="0" | ||||
AdditionalIncludeDirectories="..\win32;.;.." | |||||
AdditionalIncludeDirectories="..\win32;..\win32\ffmpeg\include" | |||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBPIPI_EXPORTS;__LIBPIPI__" | PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBPIPI_EXPORTS;__LIBPIPI__" | ||||
MinimalRebuild="true" | MinimalRebuild="true" | ||||
BasicRuntimeChecks="3" | BasicRuntimeChecks="3" | ||||
@@ -61,9 +61,10 @@ | |||||
/> | /> | ||||
<Tool | <Tool | ||||
Name="VCLinkerTool" | 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" | OutputFile="$(OutDir)\$(ProjectName)-0.dll" | ||||
LinkIncremental="2" | LinkIncremental="2" | ||||
AdditionalLibraryDirectories="..\win32\ffmpeg\lib" | |||||
GenerateDebugInformation="true" | GenerateDebugInformation="true" | ||||
SubSystem="2" | SubSystem="2" | ||||
RandomizedBaseAddress="1" | RandomizedBaseAddress="1" | ||||
@@ -90,12 +91,13 @@ | |||||
/> | /> | ||||
<Tool | <Tool | ||||
Name="VCPostBuildEventTool" | Name="VCPostBuildEventTool" | ||||
CommandLine="xcopy /Y /D $(SolutionDir)\win32\ffmpeg\lib\*.dll $(OutDir)" | |||||
/> | /> | ||||
</Configuration> | </Configuration> | ||||
<Configuration | <Configuration | ||||
Name="Release|Win32" | Name="Release|Win32" | ||||
OutputDirectory="$(SolutionDir)/win32/$(ConfigurationName)/bin" | |||||
IntermediateDirectory="$(OutDir)/$(ProjectName)" | |||||
OutputDirectory="$(SolutionDir)\win32\$(ConfigurationName)\bin" | |||||
IntermediateDirectory="$(OutDir)\$(ProjectName)" | |||||
ConfigurationType="2" | ConfigurationType="2" | ||||
> | > | ||||
<Tool | <Tool | ||||
@@ -115,7 +117,7 @@ | |||||
/> | /> | ||||
<Tool | <Tool | ||||
Name="VCCLCompilerTool" | Name="VCCLCompilerTool" | ||||
AdditionalIncludeDirectories="..\win32;.;.." | |||||
AdditionalIncludeDirectories="..\win32;..;.;..\win32\ffmpeg\include" | |||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBPIPI_EXPORTS;__LIBPIPI__" | PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBPIPI_EXPORTS;__LIBPIPI__" | ||||
RuntimeLibrary="2" | RuntimeLibrary="2" | ||||
UsePrecompiledHeader="0" | UsePrecompiledHeader="0" | ||||
@@ -134,9 +136,10 @@ | |||||
/> | /> | ||||
<Tool | <Tool | ||||
Name="VCLinkerTool" | 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" | OutputFile="$(OutDir)\$(ProjectName)-0.dll" | ||||
LinkIncremental="2" | LinkIncremental="2" | ||||
AdditionalLibraryDirectories="..\win32\ffmpeg\lib" | |||||
GenerateDebugInformation="true" | GenerateDebugInformation="true" | ||||
SubSystem="2" | SubSystem="2" | ||||
OptimizeReferences="2" | OptimizeReferences="2" | ||||
@@ -165,6 +168,7 @@ | |||||
/> | /> | ||||
<Tool | <Tool | ||||
Name="VCPostBuildEventTool" | Name="VCPostBuildEventTool" | ||||
CommandLine="xcopy /Y /D $(SolutionDir)\win32\ffmpeg\lib\*.dll $(OutDir)" | |||||
/> | /> | ||||
</Configuration> | </Configuration> | ||||
</Configurations> | </Configurations> | ||||
@@ -238,6 +242,10 @@ | |||||
RelativePath=".\resize.c" | RelativePath=".\resize.c" | ||||
> | > | ||||
</File> | </File> | ||||
<File | |||||
RelativePath=".\sequence.c" | |||||
> | |||||
</File> | |||||
<File | <File | ||||
RelativePath=".\stock.c" | RelativePath=".\stock.c" | ||||
> | > | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* libpipi Pathetic image processing interface library | * 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 | * 2008 Jean-Yves Lamoureux <jylam@lnxscene.org | ||||
* All Rights Reserved | * All Rights Reserved | ||||
* | * | ||||
@@ -107,6 +107,9 @@ typedef struct pipi_tile pipi_tile_t; | |||||
/* pipi_image_t: the main image type */ | /* pipi_image_t: the main image type */ | ||||
typedef struct pipi_image pipi_image_t; | 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 */ | /* pipi_context_t: the processing stack */ | ||||
typedef struct pipi_context pipi_context_t; | 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_free_histogram(pipi_histogram_t*); | ||||
__extern int pipi_render_histogram(pipi_image_t *, pipi_histogram_t*, int); | __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 | #ifdef __cplusplus | ||||
} | } | ||||
#endif | #endif | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* libpipi Pathetic image processing interface library | * 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 | * All Rights Reserved | ||||
* | * | ||||
* $Id$ | * $Id$ | ||||
@@ -82,6 +82,13 @@ struct pipi_image | |||||
int (*codec_free)(pipi_image_t *); | int (*codec_free)(pipi_image_t *); | ||||
}; | }; | ||||
struct pipi_sequence | |||||
{ | |||||
int w, h, fps; | |||||
void *codec_priv; | |||||
}; | |||||
struct pipi_context | struct pipi_context | ||||
{ | { | ||||
int nimages; | 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_GDI 1 | ||||
#define USE_GDIPLUS 1 | #define USE_GDIPLUS 1 | ||||
/* #undef USE_COCOA */ | /* #undef USE_COCOA */ | ||||
#define USE_FFMPEG 1 | |||||
/* #undef const */ | /* #undef const */ | ||||
#ifndef __cplusplus | #ifndef __cplusplus | ||||
#define inline __inline | #define inline __inline | ||||