📄 codec.c
字号:
/* * codec.c - basic codec interface implementation * * Copyright (C) 2001 Stefan Jahn <stefan@lkcc.org> * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * $Id: codec.c,v 1.2 2001/10/08 13:02:54 ela Exp $ * */#if HAVE_CONFIG_H# include <config.h>#endif#define _GNU_SOURCE#include <assert.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include "libserveez/alloc.h"#include "libserveez/util.h"#include "libserveez/array.h"#include "libserveez/socket.h"#include "libserveez/codec/codec.h"/* Include codec headers if any. */#if HAVE_ZLIB#include "libserveez/codec/gzlib.h"#endif/* Collection of available encoder and decoder provided by the libcodec archive or by external (shared) libraries. */static svz_array_t *svz_codecs = NULL;/* Find an appropriate codec for the given @var{description} and @var{type} which can be either @code{SVZ_CODEC_ENCODER} or @code{SVZ_CODEC_DECODER}. The function returns @code{NULL} if there is no such codec registered. */svz_codec_t *svz_codec_get (char *description, int type){ int i; svz_codec_t *codec; if (description == NULL) return NULL; svz_array_foreach (svz_codecs, codec, i) { if (strcmp (description, codec->description) == 0 && type == codec->type) return codec; } return NULL;}/* Prints the text representation of the list of known codecs registered within the core library. This includes all encoder and decoder once ran through @code{svz_codec_register()}. */voidsvz_codec_list (void){ int n; svz_codec_t *codec; fprintf (stderr, "--- list of available codecs ---"); /* Print encoder list. */ fprintf (stderr, "\n\tencoder:"); svz_array_foreach (svz_codecs, codec, n) if (codec->type == SVZ_CODEC_ENCODER) fprintf (stderr, " %s", codec->description); /* Print decoder list. */ fprintf (stderr, "\n\tdecoder:"); svz_array_foreach (svz_codecs, codec, n) if (codec->type == SVZ_CODEC_DECODER) fprintf (stderr, " %s", codec->description); fprintf (stderr, "\n");}/* This routine is called by @code{svz_boot()} and registers the builtin codecs. */intsvz_codec_init (void){#if HAVE_ZLIB svz_codec_register (&zlib_encoder); svz_codec_register (&zlib_decoder);#endif /* HAVE_ZLIB */ return 0;}/* This routine is called by @code{svz_halt()} and destroys the list of known codecs. */intsvz_codec_finalize (void){ if (svz_codecs) { svz_array_destroy (svz_codecs); svz_codecs = NULL; } return 0;}/* Checks the given codec for validity. Return zero on success. */static intsvz_codec_check (svz_codec_t *codec){ if (codec == NULL || codec->description == NULL || (codec->type != SVZ_CODEC_DECODER && codec->type != SVZ_CODEC_ENCODER)) return -1; return 0;}/* Register the given codec @var{codec}. Does not register invalid or duplicate codecs. Returns zero on success, non-zero otherwise. */intsvz_codec_register (svz_codec_t *codec){ svz_codec_t *c; int i; /* Check validity of the codec. */ if (svz_codec_check (codec)) { svz_log (LOG_ERROR, "cannot register invalid codec\n"); return -1; } /* Check for duplicate codecs. */ svz_array_foreach (svz_codecs, c, i) { if (strcmp (c->description, codec->description) == 0 && c->type == codec->type) { svz_log (LOG_ERROR, "cannot register duplicate codec `%s'\n", codec->description); return -1; } } /* Add this codec to the list of known codecs. */ if (svz_codecs == NULL) svz_codecs = svz_array_create (2); svz_array_add (svz_codecs, codec); svz_log (LOG_NOTICE, "registered `%s' %s\n", codec->description, codec->type == SVZ_CODEC_ENCODER ? "encoder" : "decoder"); return 0;}/* Removes the given codec @var{codec} from the list of known codecs. Returns zero if the codec could be successfully removed, non-zero otherwise. */intsvz_codec_unregister (svz_codec_t *codec){ svz_codec_t *c; int i; /* Check validity of the codec. */ if (svz_codec_check (codec)) { svz_log (LOG_ERROR, "cannot unregister invalid codec\n"); return -1; } /* Find codec within the list of known codecs. */ svz_array_foreach (svz_codecs, c, i) { if (strcmp (c->description, codec->description) == 0 && c->type == codec->type) { svz_array_del (svz_codecs, i); svz_log (LOG_NOTICE, "unregistered `%s' %s\n", codec->description, codec->type == SVZ_CODEC_ENCODER ? "encoder" : "decoder"); return 0; } } svz_log (LOG_ERROR, "cannot unregister codec `%s'\n", codec->description); return -1;}/* The following four (4) macros are receive buffer switcher used in order to apply the output buffer of the codec to the receive buffer of a socket structure and to revert these changes. */#define svz_codec_set_recv_buffer(sock, data) \ do { \ sock->recv_buffer = data->out_buffer; \ sock->recv_buffer_size = data->out_size; \ sock->recv_buffer_fill = data->out_fill; \ } while (0)#define svz_codec_unset_recv_buffer(sock, data) \ do { \ data->out_buffer = sock->recv_buffer; \ data->out_size = sock->recv_buffer_size; \ data->out_fill = sock->recv_buffer_fill; \ } while (0)#define svz_codec_save_recv_buffer(sock, data) \ do { \ data->in_buffer = sock->recv_buffer; \ data->in_fill = sock->recv_buffer_fill; \ data->in_size = sock->recv_buffer_size; \ } while (0)#define svz_codec_restore_recv_buffer(sock, data) \ do { \ sock->recv_buffer = data->in_buffer; \ sock->recv_buffer_size = data->in_size; \ sock->recv_buffer_fill = data->in_fill; \ } while (0)/* Reverts the changes made in @code{svz_codec_sock_receive_setup()}. */static voidsvz_codec_sock_recv_revert (svz_socket_t *sock){ svz_codec_data_t *data = (svz_codec_data_t *) sock->recv_codec; svz_codec_restore_recv_buffer (sock, data); sock->check_request = data->check_request; sock->disconnected_socket = data->disconnected_socket; svz_free (data->out_buffer); svz_free (sock->recv_codec); sock->recv_codec = NULL;}/* Setup the given socket structure @var{sock} to decode or encode its receive data via the codec @var{codec}. Therefore you must have setup the @code{check_request} method previously. The function returns zero on success, non-zero otherwise. */intsvz_codec_sock_receive_setup (svz_socket_t *sock, svz_codec_t *codec){ svz_codec_data_t *data; if (sock->recv_codec != NULL) return 0; /* Setup internal codec data. */ data = svz_malloc (sizeof (svz_codec_data_t)); data->codec = codec; data->flag = SVZ_CODEC_INIT; data->config = data->data = NULL; sock->recv_codec = data; /* Save the given sockets receive buffer, @code{check_request} callback and @code{disconnected_socket} callback if necessary. */ svz_codec_save_recv_buffer (sock, data); data->check_request = sock->check_request; sock->check_request = svz_codec_sock_receive; if (sock->disconnected_socket != svz_codec_sock_disconnect) { data->disconnected_socket = sock->disconnected_socket; sock->disconnected_socket = svz_codec_sock_disconnect; } /* Apply new receive buffer which is the output buffer of the codec. */ data->out_fill = 0; data->out_size = sock->recv_buffer_size; data->out_buffer = svz_malloc (data->out_size);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -