瀏覽代碼

Move the whole makemovie logic to libpipi. It's really hackish

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-862c8a59935f
master
sam 15 年之前
父節點
當前提交
23901ebc24
共有 9 個文件被更改,包括 702 次插入147 次删除
  1. +11
    -137
      examples/makemovie.c
  2. +192
    -0
      examples/makemovie.vcproj
  3. +186
    -0
      examples/sharpen.vcproj
  4. +1
    -0
      pipi/Makefile.am
  5. +16
    -8
      pipi/libpipi.vcproj
  6. +8
    -1
      pipi/pipi.h
  7. +8
    -1
      pipi/pipi_internals.h
  8. +279
    -0
      pipi/sequence.c
  9. +1
    -0
      win32/config.h

+ 11
- 137
examples/makemovie.c 查看文件

@@ -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;
}


+ 192
- 0
examples/makemovie.vcproj 查看文件

@@ -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>

+ 186
- 0
examples/sharpen.vcproj 查看文件

@@ -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>

+ 1
- 0
pipi/Makefile.am 查看文件

@@ -28,6 +28,7 @@ libpipi_la_SOURCES = \
resize.c \
dither.c \
accessors.c \
sequence.c \
$(codec_sources) \
$(paint_sources) \
$(render_sources) \


+ 16
- 8
pipi/libpipi.vcproj 查看文件

@@ -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"
>


+ 8
- 1
pipi/pipi.h 查看文件

@@ -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


+ 8
- 1
pipi/pipi_internals.h 查看文件

@@ -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;


+ 279
- 0
pipi/sequence.c 查看文件

@@ -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;
}

+ 1
- 0
win32/config.h 查看文件

@@ -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


Loading…
取消
儲存