pax_global_header00006660000000000000000000000064126630076620014522gustar00rootroot0000000000000052 comment=24571212d205d9ebfbbf6446e67f447940cee7bf yorick-av-0.0.4/000077500000000000000000000000001266300766200134275ustar00rootroot00000000000000yorick-av-0.0.4/Makefile000066400000000000000000000047561266300766200151030ustar00rootroot00000000000000# these values filled in by yorick -batch make.i Y_MAKEDIR= Y_EXE= Y_EXE_PKGS= Y_EXE_HOME= Y_EXE_SITE= Y_HOME_PKG= # ----------------------------------------------------- optimization flags # options for make command line, e.g.- make COPT=-g TGT=exe COPT=$(COPT_DEFAULT) TGT=$(DEFAULT_TGT) # ------------------------------------------------ macros for this package PKG_NAME=yav PKG_I=libav.i OBJS=yav.o # change to give the executable a name other than yorick PKG_EXENAME=yorick # PKG_DEPLIBS=-Lsomedir -lsomelib for dependencies of this package PKG_DEPLIBS=-lavformat -lswscale -lavutil -lavcodec # set compiler (or rarely loader) flags specific to this package PKG_CFLAGS= PKG_LDFLAGS= # list of additional package names you want in PKG_EXENAME # (typically $(Y_EXE_PKGS) should be first here) EXTRA_PKGS=$(Y_EXE_PKGS) # list of additional files for clean PKG_CLEAN=libavtest.* libavcheck.* test.mpg # autoload file for this package, if any PKG_I_START=zlibav-auto.i # non-pkg.i include files for this package, if any PKG_I_EXTRA=avtest.i libav-mpeg.i # -------------------------------- standard targets and rules (in Makepkg) # set macros Makepkg uses in target and dependency names # DLL_TARGETS, LIB_TARGETS, EXE_TARGETS # are any additional targets (defined below) prerequisite to # the plugin library, archive library, and executable, respectively PKG_I_DEPS=$(PKG_I) Y_DISTMAKE=distmake include $(Y_MAKEDIR)/Make.cfg include $(Y_MAKEDIR)/Makepkg include $(Y_MAKEDIR)/Make$(TGT) # override macros Makepkg sets for rules and other macros # see comments in Y_HOME/Makepkg for a list of possibilities # if this package built with mpy: 1. be sure mpy appears in EXTRA_PKGS, # 2. set TGT=exe, and 3. uncomment following two lines # Y_MAIN_O=$(Y_LIBEXE)/mpymain.o # include $(Y_MAKEDIR)/Makempy # configure script for this package may produce make macros: # include output-makefile-from-package-configure # Y_HOME and Y_SITE in Make.cfg may not be correct (e.g.- relocatable) Y_HOME=$(Y_EXE_HOME) Y_SITE=$(Y_EXE_SITE) # reduce chance of yorick-1.5 corrupting this Makefile MAKE_TEMPLATE = protect-against-1.5 # ------------------------------------- targets and rules for this package install:: $(YNSTALL) yav.info $(DEST_Y_SITE)/packages/installed/ # simple example: #myfunc.o: myapi.h # more complex example (also consider using PKG_CFLAGS above): #myfunc.o: myapi.h myfunc.c # $(CC) $(CPPFLAGS) $(CFLAGS) -DMY_SWITCH -o $@ -c myfunc.c # -------------------------------------------------------- end of Makefile yorick-av-0.0.4/README000066400000000000000000000042641266300766200143150ustar00rootroot00000000000000 *** yorick-av - write movies in Yorick using LibAV *** This plug-in uses the LibAV / FFmpeg family of libraries (libavformat, libavcodec, libavutils, libswscale...) to write movies from within Yorick. In essence, it is a compatible rewrite of the ympeg plug-in, but instead of shipping its own, trimmed-down version of FFmpeg, libav uses the full-featured LibAV (or FFmpeg). This allows using more recent codecs such as h.264, MP4 / DivX, Ogg/Vorbis. libav-mpeg.i provides a drop-in replacement for mpeg.i avtest.i contains a limited test suite INSTALLATION ============ First install libavcodec, libavformat, libavutil and libswscale from either the LibAV or the FFmpeg project (compatible versions are yet to check, LibAV 0.9 and 0.10 are known to work, not 0.8). Then as usual for Yorick plug-ins: yorick -batch make.i make make check make install USAGE ===== From within Yorick: #include "libav.i" help, av_create COPYRIGHT AND LICENSE INFORMATION ================================= The C code is based on the famous FFmpeg example file example-output.c by Fabrice Bellard Copyright (c) 2003 Fabrice Bellard (for yav.c) Copyright (c) 2012 Thibaut Paumard (for yav.c, *libav*.i) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. yorick-av-0.0.4/avtest.i000066400000000000000000000033371266300766200151150ustar00rootroot00000000000000/* * avtest.i - test / example file for libav.i * This file is part of yorick-av, a Yorick plu-ing to write movies * using LibAV/FFmpeg. * * Copyright (c) 2012 Thibaut Paumard * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ if (open("libav.i", "r", 1)) plug_dir, _("./", plug_dir()); require, "libav.i"; func avtest_draw_frame(i) { x = span(0, 2*pi, 100); nframes=200.; y = sin(x-2.*pi*i/nframes); plg, y, x; return i<=nframes; } func avtest(fname, params=, vcodec=, pix_fmt=, b=, r=, g=, bf=) { if (is_void(fname)) fname = "avtest2.ogg"; winkill; window; range, -1, 1; av_movie, fname, avtest_draw_frame, params=params, vcodec=vcodec, pix_fmt=pix_fmt, b=b, r=r, g=g, bf=bf; winkill; } yorick-av-0.0.4/check.i000066400000000000000000000062751266300766200146700ustar00rootroot00000000000000/* * check.i - Check / example file for yorick-av * This file is part of yorick-av, a Yorick plu-ing to write movies * using LibAV/FFmpeg. * * ============================================================================ * Copyright (c) 2012-2013 Thibaut Paumard * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * ============================================================================ * * This script should create a number of movie files called * libavcheck.* with the same content encoded in various formats using * various codecs. * * Those movies should show a red band coming from the left (brighter * at the bottom), then yellow stuff comes, and finally white. The * movie ends when the red bar reaches the middle of the image. * * Unless the environment variable YAV_NODISPLAY is set, a window * should pop-up displaying a moving sine curve. This movie will be * saved as libavtest.*. * * If, in addition, mpgtest.i (from the ympeg plug-in) can be located, * it will be run, the mpeg_* functions replaced by their av_* * counterparts using libav-mpeg.i. This will create a file named * test.mpg. * */ if (open("libav.i", "r", 1)) plug_dir, _("./", plug_dir()); #include "libav.i" exts=["mpg", "avi", "ogg", "mkv", "mp4", "mov", "wmv", "vob"]; vcodec=["mpeg1video", "mpeg4", "libtheora", "libtheora", "mpeg4", "mpeg4", "mpeg4", "mpeg2video"]; for (e=1; e<=numberof(exts); ++e) { fname="libavcheck."+exts(e); write, format="==========================================\n"+ " testing extension: '%s'\n"+ "==========================================\n", exts(e); obj=av_create(fname, vcodec=vcodec(e)); data = array(char, 3, 704, 288); for (i=1; i<=352; ++i) { data(1, i, ) = span(0,255,288); if (i>100) data(2,i-100,) = span(0,255,288); if (i>200) data(3,i-200,) = span(0,255,288); av_write, obj, data; } write, format="done, closing file '%s'\n", fname; av_close, obj; } if (!get_env("YAV_NODISPLAY")) { require, "avtest.i"; for (e=1; e<=numberof(exts); ++e) avtest, "libavtest."+exts(e), vcodec=vcodec(e); include,"mpgtest.i", 3; require, "libav-mpeg.i"; if (is_func(mpgtest)) mpgtest; } if (batch()) quit; yorick-av-0.0.4/configure000077500000000000000000000000551266300766200153360ustar00rootroot00000000000000#!/bin/sh set -e yorick -batch make.i exit 0 yorick-av-0.0.4/custom.i000066400000000000000000000002321266300766200151100ustar00rootroot00000000000000// this custom.i file should not be installed: it is just there to // ease debugging within the source tree plug_dir, _("./", plug_dir()); process_argv; yorick-av-0.0.4/libav-mpeg.i000066400000000000000000000030621266300766200156250ustar00rootroot00000000000000/* * libav-mpeg.i - compatibility layer to expose av_* routines as mpeg_* * Use this as a drop-in replacemant for mpeg.i (from the ympeg plug-in). * * This file is part of yorick-av, a Yorick plu-ing to write movies * using LibAV/FFmpeg. * * Copyright (c) 2012 Thibaut Paumard * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "libav.i" if ((Y_VERSION>="2.2") && is_void(old_mpg)) old_mpg=save(old_mpg, mpeg_create, mpeg_write, mpeg_close, mpeg_movie); mpeg_create=av_create; mpeg_write=av_write; mpeg_close=av_close; mpeg_movie=av_movie; yorick-av-0.0.4/libav.i000066400000000000000000000145611266300766200147050ustar00rootroot00000000000000if (!is_void(plug_in)) plug_in, "yav"; local libav; /* DOCUMENT #include "libav.i" * * This is yorick-av, a Yorick plug-ing to write movies using * LibAV/FFmpeg. * * This plug-in uses the LibAV / FFmpeg family of libraries * (libavformat, libavcodec, libavutils, libswscale...) to write * movies from within Yorick. * * In essence, it is a compatible rewrite of the yompeg plug-in, but * instead of shipping its own, trimmed-down version of FFmpeg, libav * uses the full-featured LibAV (or FFmpeg). This allows using more * recent codecs than MPEG1, such as h.264, MP4 / DivX, ogg/vorbis * (Theora). yorick-av can write in about any format supported by * LibAV: mpeg, mp4, avi, mov, ogg, mkv. * * libav-mpeg.i provides a drop-in replacement for mpeg.i * avtest.i contains a limited test suite * * COPYRIGHT AND LICENSE INFORMATION * The C code is based on the famous FFmpeg example file * example-output.c by Fabrice Bellard * * Copyright (c) 2003 Fabrice Bellard (for yav.c) * Copyright (c) 2012 Thibaut Paumard (for yav.c, *libav*.i) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * * SEE ALSO: av_create, av_write, av_close, av_movie, avtest */ extern av_create; /* DOCUMENT encoder = av_create(filename) * or encoder = av_create(filename, params) * * Create a LibAV encoder object to write a movie to disk. The type of * file container is determine by FILENAME's extension (e.g. ogg, mpg, * avi, mkv, mov, wmv, h264). The video codec is LibAV's default for * that container. * * Frames can then be added to the movie using av_write and the file * is closed using av_close. * * For compatibility with mpeg_create, 4 parameters can be specified * as one positional argument: * PARAMS = [b, r, g, bf] * * KEYWORDS * av_create accepts a few keywords corresponding to eponymous * options in avconv/ffmpeg, see "avconv -h" or "ffmpeg -h". * vcodec: string naming a specific video codec. If not specified, * the default for FILENAME's extension will be used. * pix_fmt: output pixel format, e.g. "rgb24", "yuv420p"... see * avconv -pix_fmts * b: bit rate. Default: 400000 * r: frame rate. Default: 25 * g: group of picture (a.k.a. gop) size. Default: 25 * bf: max number of consecutive B frames. Default: 16. * * SEE ALSO: av_write, av_close, av_movie */ extern av_write; /* DOCUMENT av_write, encoder, rgb * * Write the frame RGB to movie file using ENCODER, an LibAV encoder * object created using av_create. * * RGB must be a 3xWIDTHxHEIGHT array of char and every frame must * have the same WIDTH and HEIGHT. Certain codecs may have specific * requirements on WIDTH and HEIGHT. In particular, they must be even * numbers in all(?) cases, and using mutliples of 8 helps. * * Beware that movie frames are stored in top-to-bottom order. RGB * should be flipped vertically if pli displays it correctly: * rbg = rgb(,,::-1) * * Once all frames have been fed to the ENCODER, close the movie using * av_close. * * SEE ALSO: av_create, av_close, av_movie */ extern av_codec_opt_set; /* DOCUMENT av_codec_opt_set, encoder, parname, value * * Experimental, has never been shown to work. * * Set parameter PARNAME to VALUE (both strings) in the codec stored * in ENCODER. * * SEE ALSO: av_create, av_write, av_close, av_movie */ func av_close(&obj) /* DOCUMENT av_close, encoder * * Close ENCODER, a LibAV encoder object previously created using * av_write. Currently, it merely destroys the object but it should * still be used for forward compatibility. * * Destroying the last reference to ENCODER writes the last, buffered * frames in the file and writes whatever trailer is required by the * video codec or container file format. * * SEE ALSO: av_create, av_write, av_movie */ { obj = []; } func av_movie(filename, draw_frame,time_limit,min_interframe,bracket_time, params=, vcodec=, pix_fmt=, b=, r=, g=, bf=) /* DOCUMENT av_movie, filename, draw_frame * or av_movie, filename, draw_frame, time_limit * or av_movie, filename, draw_frame, time_limit, min_interframe * * A wrapper around the movie function in movie.i, which writes the * animation to file FILENAME using the av_* family of functions from * libav.i. * * KEYWORDS * av_movie accepts the same keywords as av_create. In addition, * av_create's PARAM argument can be passed as a keyword to av_movie. * * SEE ALSO: movie, av_create */ { require, "movie.i"; if (is_void(params)) params=[0, 0, 16, 2]; _av_movie_encoder = av_create(filename, params, vcodec=vcodec, pix_fmt=pix_fmt, b=b, r=r, g=g, bf=bf); fma = _av_movie_fma; _av_movie_count = 0; return movie(draw_frame, time_limit, min_interframe, bracket_time); } if (is_void(_av_movie_real_fma)) _av_movie_real_fma = fma; func _av_movie_fma /* xDOCUMENT _av_movie_fma Called internally by av_movie. Writes image displayed in current graphic window to _av_movie_encoder and performs a real fma. Image is trimmed until its size is a multple of 8. SEE ALSO: movie, av_write, fma */ { if (_av_movie_count++) { img = rgb_read(); rest = dimsof(img) % 8; if (anyof(rest)) { img = img(,rest(3)/2+1:-(rest(3)+1)/2,rest(4)/2+1:-(rest(4)+1)/2); } av_write, _av_movie_encoder, img; } _av_movie_real_fma; } // intilialize plug-in (register codecs et al.) extern __av_init; __av_init; yorick-av-0.0.4/yav.c000066400000000000000000000336741266300766200144070ustar00rootroot00000000000000/* * yav.c * This file is part of yorick-av, a Yorick plu-ing to write movies * using LibAV/FFmpeg. It is based on the famous FFmpeg example file * example-output.c by Fabrice Bellard and keeps its license. * * Copyright (c) 2003 Fabrice Bellard * Copyright (c) 2012-2013, 2016 Thibaut Paumard * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "yapi.h" #include #include #include #include #include #include #ifndef AVIO_FLAG_WRITE # define AVIO_FLAG_WRITE AVIO_WRONLY #endif #if (LIBAVFORMAT_VERSION_MAJOR < 53) || \ ((LIBAVFORMAT_VERSION_MAJOR == 53) && (LIBAVFORMAT_VERSION_MINOR < 9)) # define avformat_new_stream(a, b) av_new_stream(a, 0) #endif #if (LIBAVUTIL_VERSION_MAJOR < 50) || \ ((LIBAVUTIL_VERSION_MAJOR == 50) && (LIBAVUTIL_VERSION_MINOR < 44)) // av_opt_set missing at least until this version int av_opt_set (void *obj, const char * name, const char * val, int search_flags) { y_error("av_opt_set unimplemented in this libav/ffmpeg"); return -1; } #endif /* default parameter values */ #define YAV_BIT_RATE 400000 #define YAV_FRAME_RATE 24 #define YAV_GOP_SIZE 25 #define YAV_MAX_B_FRAMES 16 #define YAV_PIX_FMT AV_PIX_FMT_YUV420P /* default pix_fmt */ inline int yav_arg_set(iarg) { return (iarg >= 0) && !yarg_nil(iarg); } typedef struct yav_ctxt { AVFrame *picture, *tmp_picture; uint8_t *video_outbuf; int frame_count, video_outbuf_size; AVOutputFormat *fmt; AVFormatContext *oc; AVStream *audio_st, *video_st; struct SwsContext *img_convert_ctx; AVCodec *codec; int open; } yav_ctxt; void yav_free(void*obj); static y_userobj_t yav_ops = {"LibAV object", &yav_free, 0, 0, 0, 0}; void yav_opencodec(yav_ctxt *obj, unsigned int width, unsigned int height); yav_ctxt *ypush_av() { yav_ctxt * obj = (yav_ctxt *)ypush_obj(&yav_ops, sizeof(yav_ctxt)); obj->picture=0; obj->tmp_picture=0; obj->video_outbuf=0; obj->frame_count=0; obj->video_outbuf_size=0; obj->oc=0; obj->video_st=0; obj->img_convert_ctx = 0; obj->codec=0; obj->open=0; // audio_st=0; return obj; } void yav_free(void*obj_) { yav_ctxt * obj = (yav_ctxt *)obj_; if (obj->open) av_write_trailer(obj->oc); if (obj->picture){ av_free(obj->picture->data[0]); av_free(obj->picture); } if (obj->tmp_picture){ av_free(obj->tmp_picture->data[0]); av_free(obj->tmp_picture); } if (obj->video_outbuf) { av_free(obj->video_outbuf); } //if (obj->frame_count); // if (obj->video_outbuf_size); if (obj->video_st) { avcodec_close(obj->video_st->codec); obj->video_st=0; } if (obj->oc) { avformat_free_context(obj->oc); obj->oc=0; } if (obj->img_convert_ctx) { sws_freeContext(obj->img_convert_ctx); obj->img_convert_ctx=0; } } void Y_av_create(int argc) { static long default_params[]= {YAV_BIT_RATE, YAV_FRAME_RATE, YAV_GOP_SIZE, YAV_MAX_B_FRAMES}; long *params=default_params; // PARSE ARGUMENTS: SEPARATE KEYWORDS FROM POSITIONAL ARGUMENTS static char * knames[] = { "vcodec", "pix_fmt", "b", "r", "g", "bf", 0 }; #define YAC_CREATE_NKW 6 static long kglobs[YAC_CREATE_NKW+1]; int kiargs[YAC_CREATE_NKW]; int piargs[]={-1, -1}; yarg_kw_init(knames, kglobs, kiargs); int iarg=argc-1, parg=0; while (iarg>=0) { iarg = yarg_kw(iarg, kglobs, kiargs); if (iarg>=0) { if (parg<2) piargs[parg++]=iarg--; else y_error("av_create takes at most 2 positional arguments"); } } // INTERPRET POSITIONAL ARGUMENTS // filename (mandatory) if ((iarg=piargs[0])<0) y_error("FILENAME must be specified"); char *filename = ygets_q(iarg); // params vector (optional) if (yav_arg_set(iarg=piargs[1])) { long ntot ; long dims[Y_DIMSIZE]={0,0}; params = ygeta_l(iarg, &ntot, dims); if (dims[0]!=1 || dims[1]!=4) y_error("bad dimensions for PARAMS vector"); if (params[0]<0 || params[1]<0 || params[2]<0) y_error("bad values in PARAMS vector"); } // INTERPRET KEYWORD ARGUMENTS char* vcodec = NULL, *pix_fmt = NULL; int k=0; if (yav_arg_set(iarg=kiargs[k++])) vcodec = ygets_q(iarg); // vcodec if (yav_arg_set(iarg=kiargs[k++])) pix_fmt = ygets_q(iarg); // pix_fmt if (yav_arg_set(iarg=kiargs[k++])) params[0] = ygets_l(iarg); // b if (yav_arg_set(iarg=kiargs[k++])) params[1] = ygets_l(iarg); // r if (yav_arg_set(iarg=kiargs[k++])) params[2] = ygets_l(iarg); // g if (yav_arg_set(iarg=kiargs[k++])) params[3] = ygets_l(iarg); // bf // PUSH RETURN VALUE yav_ctxt * obj = ypush_av(); /* allocate the output media context */ obj->oc = avformat_alloc_context(); if (!obj->oc) { y_error("Memory error"); } /* auto detect the output format from the name. default is mpeg. */ obj->oc->oformat = av_guess_format(NULL, filename, NULL); if (!obj->oc->oformat) { y_warn("Could not deduce output format from file extension: using MPEG."); obj->oc->oformat = av_guess_format("mpeg", NULL, NULL); } if (!obj->oc->oformat) { y_error("Could not find suitable output format."); } snprintf(obj->oc->filename, sizeof(obj->oc->filename), "%s", filename); /* add the audio and video streams using the default format codecs and initialize the codecs */ obj->video_st = NULL; // audio_st = NULL; if (obj->oc->oformat->video_codec != AV_CODEC_ID_NONE) { AVCodecContext *c; obj->video_st = avformat_new_stream(obj->oc, NULL); c = obj->video_st->codec; if (vcodec) { obj->codec = avcodec_find_encoder_by_name(vcodec); if (!obj->codec) y_error("can't find requested codec"); c->codec_id = obj->codec->id; } else { c->codec_id = obj->oc->oformat->video_codec; obj->codec = avcodec_find_encoder(c->codec_id); if (!obj->codec) y_error("default codec not found"); } c->codec_type = AVMEDIA_TYPE_VIDEO; avcodec_get_context_defaults3(c, obj->codec); if (c->codec_id == AV_CODEC_ID_NONE) c->codec_id = obj->codec->id; /* put sample parameters */ c->width = 0; c->height = 0; c->pix_fmt = pix_fmt ? av_get_pix_fmt(pix_fmt) : YAV_PIX_FMT; c->bit_rate = params[0] ? params[0] : YAV_BIT_RATE; c->time_base.den = params[1] ? params[1] : YAV_FRAME_RATE; c->time_base.num = 1; c->gop_size = params[2] ? params[2] : YAV_GOP_SIZE; c->max_b_frames = (params[3]>=0) ? params[3] : YAV_MAX_B_FRAMES; if(obj->oc->oformat->flags & AVFMT_GLOBALHEADER) c->flags |= CODEC_FLAG_GLOBAL_HEADER; // codec-specific limitations switch (c->codec_id) { case AV_CODEC_ID_RAWVIDEO: case AV_CODEC_ID_GIF: if (!pix_fmt) c->pix_fmt = AV_PIX_FMT_RGB24; break; case AV_CODEC_ID_MSMPEG4V3: case AV_CODEC_ID_H263: case AV_CODEC_ID_H263P: case AV_CODEC_ID_RV10: case AV_CODEC_ID_RV20: case AV_CODEC_ID_FLV1: case AV_CODEC_ID_ASV1: case AV_CODEC_ID_ASV2: c->max_b_frames = 0; break; default:; } } if (!(obj->oc->oformat->flags & AVFMT_RAWPICTURE)) { obj->video_outbuf_size = 200000; obj->video_outbuf = av_malloc(obj->video_outbuf_size); } } void yav_opencodec(yav_ctxt *obj, unsigned int width, unsigned int height) { obj->video_st->codec->width=width; obj->video_st->codec->height=height; av_dump_format(obj->oc, 0, obj->oc->filename, 1); if (obj->video_st) { AVCodecContext *c; c = obj->video_st->codec; if (avcodec_open2(c, obj->codec, NULL) < 0) y_error("could not open codec\n"); obj->picture = av_frame_alloc(); if (!obj->picture) y_error("Could not allocate picture"); int size = avpicture_get_size(c->pix_fmt, c->width, c->height); uint8_t *picture_buf = av_malloc(size); if (!picture_buf) { av_frame_free(&obj->picture); y_error("unable to allocate memory"); } avpicture_fill((AVPicture *)obj->picture, picture_buf, c->pix_fmt, c->width, c->height); if (obj->oc->oformat->video_codec == AV_CODEC_ID_H264 || obj->oc->oformat->video_codec == AV_CODEC_ID_THEORA) obj->picture->pts=-1; /* if the output format is not RGB24, then a temporary RGB24 picture is needed too. It is then converted to the required output format */ if (c->pix_fmt != AV_PIX_FMT_RGB24) { obj->tmp_picture = av_frame_alloc(); if (!obj->tmp_picture) { y_error("Could not allocate picture"); } size = avpicture_get_size(AV_PIX_FMT_RGB24, c->width, c->height); uint8_t *tmp_picture_buf = av_malloc(size); if (!tmp_picture_buf) { av_frame_free(&obj->tmp_picture); av_frame_free(&obj->picture); y_error("unable to allocate memory"); } avpicture_fill((AVPicture *)obj->tmp_picture, tmp_picture_buf, AV_PIX_FMT_RGB24, c->width, c->height); } } /* open the output file, if needed */ if (!(obj->oc->oformat->flags & AVFMT_NOFILE)) if (avio_open(&obj->oc->pb, obj->oc->filename, AVIO_FLAG_WRITE) < 0) y_errorq("Could not open '%s'", obj->oc->filename); obj->open = 1; /* write the stream header, if any */ avformat_write_header(obj->oc, NULL); } void Y_av_codec_opt_set(int argc) { yav_ctxt * obj = yget_obj(argc-1, &yav_ops); AVCodecContext *c = obj->video_st->codec; char* name = ygets_q(argc-2); char* val = ygets_q(argc-3); ypush_long(av_opt_set(c, name, val, AV_OPT_SEARCH_CHILDREN )); } void Y_av_write(int argc) { yav_ctxt * obj = yget_obj(argc-1, &yav_ops); AVCodecContext *c = obj->video_st->codec; long ntot=0; long dims[Y_DIMSIZE]={0,0}; uint8_t *data = ygeta_c(argc-2, &ntot, dims); if (!c->width) yav_opencodec(obj, dims[2], dims[3]); if (dims[0]!=3 || dims[1]!=3 || dims[2]!=c->width || dims[3]!=c->height) y_error("DATA should be an array(char, 3, width, height)"); long npix=dims[2]*dims[3]; const uint8_t *src[4] = {data, 0, 0, 0}; int src_linesizes[4] = {3*c->width,0,0,0}; if (c->pix_fmt != AV_PIX_FMT_RGB24) { /* as we only generate a RGB24 picture, we must convert it to the codec pixel format if needed */ obj->img_convert_ctx = sws_getCachedContext(obj->img_convert_ctx, c->width, c->height, AV_PIX_FMT_RGB24, c->width, c->height, c->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL); if (obj->img_convert_ctx == NULL) y_error("Cannot initialize the conversion context"); av_image_copy(obj->tmp_picture->data, obj->tmp_picture->linesize, src, src_linesizes, AV_PIX_FMT_RGB24, c->width, c->height); sws_scale(obj->img_convert_ctx, (const uint8_t * const*)obj->tmp_picture->data, obj->tmp_picture->linesize, 0, c->height, obj->picture->data, obj->picture->linesize); } else { av_image_copy(obj->picture->data, obj->picture->linesize, src, src_linesizes, AV_PIX_FMT_RGB24, c->width, c->height); } /* encode the image */ if (obj->oc->oformat->flags & AVFMT_RAWPICTURE) y_error("RAW picture not supported"); if (obj->oc->oformat->video_codec == AV_CODEC_ID_H264 || obj->oc->oformat->video_codec == AV_CODEC_ID_THEORA) ++obj->picture->pts; int ret=0; #if (LIBAVCODEC_VERSION_MAJOR > 53) if (obj->oc->oformat->flags & AVFMT_RAWPICTURE) { /* Raw video case - directly store the picture in the packet */ AVPacket pkt; av_init_packet(&pkt); pkt.flags |= AV_PKT_FLAG_KEY; pkt.stream_index = obj->video_st->index; pkt.data= obj->video_outbuf; // pkt.size= out_size; // pkt.data = dst_picture.data[0]; pkt.size = sizeof(AVPicture); ret = av_interleaved_write_frame(obj->oc, &pkt); } else { AVPacket pkt = { 0 }; int got_packet; av_init_packet(&pkt); /* encode the image */ ret = avcodec_encode_video2(c, &pkt, obj->picture, &got_packet); if (ret < 0) { y_errorn("Error encoding video frame: %d", ret); } /* If size is zero, it means the image was buffered. */ if (!ret && got_packet && pkt.size) { pkt.stream_index = obj->video_st->index; /* Write the compressed frame to the media file. */ ret = av_interleaved_write_frame(obj->oc, &pkt); } else { ret = 0; } } #else int out_size = avcodec_encode_video(c, obj->video_outbuf, obj->video_outbuf_size, obj->picture); /* if zero size, it means the image was buffered */ if (out_size > 0) { AVPacket pkt; av_init_packet(&pkt); if (c->coded_frame->pts != AV_NOPTS_VALUE) pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, obj->video_st->time_base); if(c->coded_frame->key_frame) pkt.flags |= AV_PKT_FLAG_KEY; pkt.stream_index= obj->video_st->index; pkt.data= obj->video_outbuf; pkt.size= out_size; /* write the compressed frame in the media file */ ret = av_interleaved_write_frame(obj->oc, &pkt); } #endif if (ret != 0) y_errorn("Error while writing video frame: %d", ret); /* return [] */ ypush_nil(); } /* currently it's just obj = [] void Y_av_close(int argc) { } */ void Y___av_init(int argc) { /* initialize libavcodec, and register all codecs and formats */ av_register_all(); } yorick-av-0.0.4/yav.info000066400000000000000000000013231266300766200151020ustar00rootroot00000000000000Package: yorick-av Kind: plugin Version: 0.0.4 Revision: 1 Description: Support for FFmpeg/LibAV output License: permissive Author: Thibaut Paumard Maintainer: Thibaut Paumard OS: Depends: yorick(>=2.2) Source: Source-MD5: Source-Directory: contrib/yorick-mpeg DocFiles: README Homepage: http://www.maumae.net/yorick/doc/plugins.php DescDetail: << This is a compiled add-on for yorick (an interpreted computer language specialized for numerical and scientific problems). Yorick-mpeg adds support for writing movies in various formats (AVI, OGG, MP4...) using LibAV. It can be used as a replacement for yorick-mpeg which only produces MPEG1 movies. << DescUsage: << - << DescPort: << << yorick-av-0.0.4/yorick-av.keywords000066400000000000000000000000361266300766200171230ustar00rootroot00000000000000codec container mpeg avi divx yorick-av-0.0.4/yorick-av.packinfo000066400000000000000000000002371266300766200170510ustar00rootroot00000000000000:newsubsection yorick-av: write movies in various formats :libav write movies in OGG, MKV, MP4 and other formats :libav-mpeg drop-in replacement for mpeg.i yorick-av-0.0.4/zlibav-auto.i000066400000000000000000000032131266300766200160350ustar00rootroot00000000000000/* * zlibav-auto.i - auto-loads for libav.i * * This file is part of yorick-av, a Yorick plu-ing to write movies * using LibAV/FFmpeg. * * Copyright (c) 2012 Thibaut Paumard * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ autoload, "libav.i"; autoload, "libav.i", libav, av_create, av_write, av_close, av_movie; autoload, "avtest.i"; autoload, "avtest.i", avtest; // be nice to mpeg.i: if autoloads are already in place, don't overide them // this file should be parsed after mpeg, ympeg, yompeg or yorz autoload, "libav-mpeg.i"; if (!is_void(mpeg_create)) autoload, "libav-mpeg.i", mpeg_create, mpeg_write, mpeg_close, mpeg_movie;