aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWolfgang Draxinger <Wolfgang.Draxinger@draxit.de>2011-06-28 12:00:12 +0200
committerWolfgang Draxinger <Wolfgang.Draxinger@draxit.de>2011-06-28 12:00:12 +0200
commit14ad6e0e26569b0d4f461b99721d6aee9b02e8ff (patch)
treecabeb6a1fb2f7b099c7201e605264e915df62153
downloadaveasy-master.tar.gz
aveasy-master.tar.bz2
initial commitHEADmaster
-rw-r--r--README2
-rw-r--r--aveasy.c297
-rw-r--r--aveasy.h45
3 files changed, 344 insertions, 0 deletions
diff --git a/README b/README
new file mode 100644
index 0000000..f32acbe
--- /dev/null
+++ b/README
@@ -0,0 +1,2 @@
+aveasy - a simple wrapper around libavformat, libavdevice and libswscale
+(from FFmpeg) to make accessing video sources less a pain.
diff --git a/aveasy.c b/aveasy.c
new file mode 100644
index 0000000..15645dc
--- /dev/null
+++ b/aveasy.c
@@ -0,0 +1,297 @@
+/* aveasy - a simple wrapper around libavformat, libavdevice and libswscale
+Copyright (C) 2010, 2011 Wolfgang Draxinger <code+aveasy@datenwolf.net>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "aveasy.h"
+
+void describe_AVInputFormat(
+ AVInputFormat const *const iformat )
+{
+ if( !iformat )
+ return;
+
+ fprintf( stderr,
+ "name: %s\n"
+ "long_name: %s\n"
+ "priv_data_size: %d\n"
+ "read_probe: %p\n"
+ "read_header: %p\n" "read_packet: %p\n" "read_close: %p\n"
+#if LIBAVFORMAT_VERSION_MAJOR < 53
+ "read_seek: %p\n"
+#endif
+ "read_timestamp: %p\n"
+ "flags %x\n"
+ "read_play: %p\n"
+ "read_pause: %p\n"
+ "read_seek2: %p\n",
+ iformat->name,
+ iformat->long_name,
+ iformat->priv_data_size,
+ iformat->read_probe,
+ iformat->read_header,
+ iformat->read_packet, iformat->read_close,
+#if LIBAVFORMAT_VERSION_MAJOR < 53
+ iformat->read_seek,
+#endif
+ iformat->read_timestamp,
+ iformat->flags,
+ iformat->read_play, iformat->read_pause, iformat->read_seek2 );
+
+}
+
+struct AVEasyInputContext {
+ AVFormatParameters format_parameters;
+ AVInputFormat *input_format;
+ AVFormatContext *format_context;
+ AVCodecContext *codec_context;
+ AVCodec *codec;
+ AVFrame *encoded_frame;
+ AVFrame *raw_frame;
+ struct SwsContext *sws_context;
+ int video_stream;
+ enum PixelFormat pixel_format;
+ size_t buffer_size;
+ void *buffer;
+};
+
+AVEasyInputContext *aveasy_input_open_v4l2(
+ char const * const path,
+ unsigned short width,
+ unsigned short height,
+ enum CodecID connection_codec,
+ enum PixelFormat pixel_format )
+{
+ AVEasyInputContext *ctx;
+ int i;
+
+ ctx = malloc(sizeof(*ctx));
+ if(!ctx)
+ goto fail_alloc_context;
+
+ ctx->format_context = avformat_alloc_context();
+ if( !ctx->format_context )
+ goto fail_alloc_context;
+ ctx->format_context->video_codec_id = connection_codec;
+
+ memset(&ctx->format_parameters, 0, sizeof(ctx->format_parameters));
+ ctx->format_parameters.prealloced_context = 1;
+ ctx->format_parameters.width = width;
+ ctx->format_parameters.height = height;
+ ctx->input_format = av_find_input_format("video4linux2");
+ if(!ctx->input_format)
+ goto fail_find_input_format;
+
+ if( av_open_input_file( &ctx->format_context,
+ path,
+ ctx->input_format,
+ 0,
+ &ctx->format_parameters ) )
+ goto fail_open_input_file;
+
+ if( av_find_stream_info( ctx->format_context ) < 0 )
+ goto fail_find_stream_info;
+
+ dump_format( ctx->format_context, 0, path, false );
+ ctx->video_stream = -1;
+ for(i = 0; i < ctx->format_context->nb_streams; ++i) {
+ if( ctx->format_context->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO ) {
+ ctx->video_stream = i;
+ break;
+ }
+ }
+ if( ctx->video_stream == -1 )
+ goto fail_find_videostream;
+
+ ctx->codec_context = ctx->format_context->streams[ctx->video_stream]->codec;
+ if( !ctx->codec_context )
+ goto fail_get_codec_context;
+
+ ctx->sws_context = sws_getContext(
+ ctx->codec_context->width,
+ ctx->codec_context->height,
+ ctx->codec_context->pix_fmt,
+ ctx->codec_context->width,
+ ctx->codec_context->height,
+ ctx->pixel_format = pixel_format,
+ SWS_FAST_BILINEAR,
+ 0, 0, 0 );
+ if( !ctx->sws_context )
+ goto fail_get_swscontext;
+
+ ctx->codec = avcodec_find_decoder( ctx->codec_context->codec_id );
+ if(! ctx->codec )
+ goto fail_find_decoder;
+ if( avcodec_open( ctx->codec_context, ctx->codec ) < 0 )
+ goto fail_decoder_open;
+
+ // Fix for some some codecs which report wrong frame rate
+ if( ctx->codec_context->time_base.num > 999 &&
+ ctx->codec_context->time_base.den == 1 )
+ ctx->codec_context->time_base.den = 1000;
+
+ ctx->encoded_frame = avcodec_alloc_frame();
+ if( !ctx->encoded_frame )
+ goto fail_alloc_encoded_frame;
+
+ ctx->raw_frame = avcodec_alloc_frame();
+ if( !ctx->raw_frame )
+ goto fail_alloc_raw_frame;
+
+ ctx->buffer_size = avpicture_get_size(
+ ctx->pixel_format,
+ ctx->codec_context->width,
+ ctx->codec_context->height );
+
+ ctx->buffer = av_malloc( ctx->buffer_size );
+ if( !ctx->buffer )
+ goto fail_alloc_buffer;
+ avpicture_fill( (AVPicture*) ctx->raw_frame,
+ ctx->buffer,
+ ctx->pixel_format,
+ ctx->codec_context->width,
+ ctx->codec_context->height );
+
+
+ return ctx;
+/* ----------------------------------------------- */
+fail_alloc_buffer:
+ av_free(ctx->raw_frame);
+
+fail_alloc_raw_frame:
+ av_free(ctx->encoded_frame);
+
+fail_alloc_encoded_frame:
+fail_decoder_open:
+fail_find_decoder:
+ sws_freeContext(ctx->sws_context);
+
+fail_get_swscontext:
+fail_get_codec_context:
+fail_find_videostream:
+ for(i = 0; i < ctx->format_context->nb_streams; ++i) {
+ if( ctx->format_context->streams[i]->codec ) {
+ avcodec_close(ctx->format_context->streams[i]->codec);
+ }
+ }
+
+fail_find_stream_info:
+ av_close_input_file(ctx->format_context);
+
+fail_open_input_file:
+fail_find_input_format:
+ av_free(ctx->format_context);
+
+fail_alloc_context:
+ return 0;
+}
+
+void aveasy_input_close(AVEasyInputContext * const ctx)
+{
+ int i;
+
+ if(!ctx)
+ return;
+
+ av_free(ctx->raw_frame);
+ av_free(ctx->encoded_frame);
+ sws_freeContext(ctx->sws_context);
+ for(i = 0; i < ctx->format_context->nb_streams; ++i) {
+ if( ctx->format_context->streams[i]->codec ) {
+ avcodec_close(ctx->format_context->streams[i]->codec);
+ }
+ }
+ av_close_input_file(ctx->format_context);
+ av_free(ctx->format_context);
+}
+
+void *aveasy_input_read_frame(AVEasyInputContext * const ctx)
+{
+ AVPacket packet;
+
+ if(!ctx)
+ return 0;
+
+ av_init_packet(&packet);
+ for(;;) {
+ if( av_read_frame(ctx->format_context, &packet) ) {
+ av_free_packet( &packet );
+ return 0;
+ }
+
+
+ if( packet.stream_index == ctx->video_stream ) {
+ int frame_finished = 0;
+ avcodec_decode_video2(
+ ctx->codec_context,
+ ctx->encoded_frame,
+ &frame_finished,
+ &packet);
+
+ if( frame_finished ) {
+ int ret =
+ sws_scale( ctx->sws_context,
+ ctx->encoded_frame->data,
+ ctx->encoded_frame->linesize,
+ 0,
+ ctx->codec_context->height,
+ ctx->raw_frame->data,
+ ctx->raw_frame->linesize );
+ av_free_packet( &packet );
+ return ctx->buffer;
+ }
+ }
+
+ }
+
+ av_free_packet( &packet );
+ return 0;
+}
+
+int aveasy_input_width(AVEasyInputContext const * const ctx)
+{
+ if(!ctx)
+ return 0;
+ return ctx->codec_context->width;
+}
+
+int aveasy_input_height(AVEasyInputContext const * const ctx)
+{
+ if(!ctx)
+ return 0;
+ return ctx->codec_context->height;
+}
+
+size_t aveasy_input_buffer_size(AVEasyInputContext const * const ctx)
+{
+ if(!ctx)
+ return 0;
+ return ctx->buffer_size;
+}
+
+void* aveasy_input_buffer(AVEasyInputContext const * const ctx)
+{
+ if(!ctx)
+ return 0;
+ return ctx->buffer;
+}
+
diff --git a/aveasy.h b/aveasy.h
new file mode 100644
index 0000000..c6d3b17
--- /dev/null
+++ b/aveasy.h
@@ -0,0 +1,45 @@
+/* aveasy - a simple wrapper around libavformat, libavdevice and libswscale
+Copyright (C) 2010, 2011 Wolfgang Draxinger <code+aveasy@datenwolf.net>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <libavcodec/avcodec.h>
+#include <libavformat/avformat.h>
+#include <libswscale/swscale.h>
+#include <libavdevice/avdevice.h>
+#include <libavutil/pixfmt.h>
+
+struct AVEasyInputContext;
+typedef struct AVEasyInputContext AVEasyInputContext;
+
+
+AVEasyInputContext *aveasy_input_open_v4l2(
+ char const * const path,
+ unsigned short width,
+ unsigned short height,
+ enum CodecID connection_codec,
+ enum PixelFormat pixel_format );
+
+
+void aveasy_input_close(AVEasyInputContext * const ctx);
+
+void *aveasy_input_read_frame(AVEasyInputContext * const ctx);
+
+int aveasy_input_width(AVEasyInputContext const * const ctx);
+int aveasy_input_height(AVEasyInputContext const * const ctx);
+size_t aveasy_input_buffer_size(AVEasyInputContext const * const ctx);
+void* aveasy_input_buffer(AVEasyInputContext const * const ctx);
+