Skip to content
Snippets Groups Projects
utils.c 85.5 KiB
Newer Older
Fabrice Bellard's avatar
Fabrice Bellard committed
/*
 * Various utilities for ffmpeg system
 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
Fabrice Bellard's avatar
Fabrice Bellard committed
 *
 * 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 of the License, or (at your option) any later version.
Fabrice Bellard's avatar
Fabrice Bellard committed
 *
 * This library is distributed in the hope that it will be useful,
Fabrice Bellard's avatar
Fabrice Bellard committed
 * 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.
Fabrice Bellard's avatar
Fabrice Bellard committed
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Fabrice Bellard's avatar
Fabrice Bellard committed
 */
Fabrice Bellard's avatar
Fabrice Bellard committed
#include "avformat.h"
#undef NDEBUG
#include <assert.h>

AVInputFormat *first_iformat = NULL;
AVOutputFormat *first_oformat = NULL;
AVImageFormat *first_image_format = NULL;
Fabrice Bellard's avatar
Fabrice Bellard committed

void av_register_input_format(AVInputFormat *format)
Fabrice Bellard's avatar
Fabrice Bellard committed
{
    AVInputFormat **p;
    p = &first_iformat;
    while (*p != NULL) p = &(*p)->next;
    *p = format;
    format->next = NULL;
}

void av_register_output_format(AVOutputFormat *format)
{
    AVOutputFormat **p;
    p = &first_oformat;
Fabrice Bellard's avatar
Fabrice Bellard committed
    while (*p != NULL) p = &(*p)->next;
    *p = format;
    format->next = NULL;
}

int match_ext(const char *filename, const char *extensions)
Fabrice Bellard's avatar
Fabrice Bellard committed
{
    const char *ext, *p;
    char ext1[32], *q;

Michael Niedermayer's avatar
Michael Niedermayer committed
    if(!filename)
        return 0;
    
Fabrice Bellard's avatar
Fabrice Bellard committed
    ext = strrchr(filename, '.');
    if (ext) {
        ext++;
        p = extensions;
        for(;;) {
            q = ext1;
            while (*p != '\0' && *p != ',') 
                *q++ = *p++;
            *q = '\0';
            if (!strcasecmp(ext1, ext)) 
                return 1;
            if (*p == '\0') 
                break;
            p++;
        }
    }
    return 0;
}

AVOutputFormat *guess_format(const char *short_name, const char *filename, 
                             const char *mime_type)
Fabrice Bellard's avatar
Fabrice Bellard committed
{
Fabrice Bellard's avatar
Fabrice Bellard committed
    int score_max, score;

    /* specific test for image sequences */
    if (!short_name && filename && 
        filename_number_test(filename) >= 0 &&
        av_guess_image2_codec(filename) != CODEC_ID_NONE) {
        return guess_format("image2", NULL, NULL);
    }
    if (!short_name && filename && 
        filename_number_test(filename) >= 0 &&
        guess_image_format(filename)) {
        return guess_format("image", NULL, NULL);
    }

Fabrice Bellard's avatar
Fabrice Bellard committed
    /* find the proper file type */
    fmt_found = NULL;
    score_max = 0;
Fabrice Bellard's avatar
Fabrice Bellard committed
    while (fmt != NULL) {
        score = 0;
        if (fmt->name && short_name && !strcmp(fmt->name, short_name))
            score += 100;
        if (fmt->mime_type && mime_type && !strcmp(fmt->mime_type, mime_type))
            score += 10;
        if (filename && fmt->extensions && 
            match_ext(filename, fmt->extensions)) {
            score += 5;
        }
        if (score > score_max) {
            score_max = score;
            fmt_found = fmt;
        }
        fmt = fmt->next;
    }
    return fmt_found;
}   

AVOutputFormat *guess_stream_format(const char *short_name, const char *filename, 
                             const char *mime_type)
{
    AVOutputFormat *fmt = guess_format(short_name, filename, mime_type);

    if (fmt) {
        AVOutputFormat *stream_fmt;
        char stream_format_name[64];

        snprintf(stream_format_name, sizeof(stream_format_name), "%s_stream", fmt->name);
        stream_fmt = guess_format(stream_format_name, NULL, NULL);

        if (stream_fmt)
            fmt = stream_fmt;
    }

    return fmt;
}

/**
 * guesses the codec id based upon muxer and filename.
 */
enum CodecID av_guess_codec(AVOutputFormat *fmt, const char *short_name, 
                            const char *filename, const char *mime_type, enum CodecType type){
    if(type == CODEC_TYPE_VIDEO){
        enum CodecID codec_id= CODEC_ID_NONE;

        if(!strcmp(fmt->name, "image2") || !strcmp(fmt->name, "image2pipe")){
            codec_id= av_guess_image2_codec(filename);
        }
        if(codec_id == CODEC_ID_NONE)
            codec_id= fmt->video_codec;
        return codec_id;
    }else if(type == CODEC_TYPE_AUDIO)
        return fmt->audio_codec;
    else
        return CODEC_ID_NONE;
}

AVInputFormat *av_find_input_format(const char *short_name)
{
    AVInputFormat *fmt;
    for(fmt = first_iformat; fmt != NULL; fmt = fmt->next) {
        if (!strcmp(fmt->name, short_name))
            return fmt;
    }
    return NULL;
}

Fabrice Bellard's avatar
Fabrice Bellard committed
/* memory handling */

/**
 * Default packet destructor 
 */
static void av_destruct_packet(AVPacket *pkt)
{
    av_free(pkt->data);
    pkt->data = NULL; pkt->size = 0;
}

/**
 * Allocate the payload of a packet and intialized its fields to default values.
 *
 * @param pkt packet
 * @param size wanted payload size
 * @return 0 if OK. AVERROR_xxx otherwise.
 */
Fabrice Bellard's avatar
Fabrice Bellard committed
int av_new_packet(AVPacket *pkt, int size)
{
    void *data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
    if (!data)
    memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
    av_init_packet(pkt);
    pkt->data = data; 
    pkt->size = size;
    pkt->destruct = av_destruct_packet;
Fabrice Bellard's avatar
Fabrice Bellard committed
    return 0;
}

/* This is a hack - the packet memory allocation stuff is broken. The
   packet is allocated if it was not really allocated */
int av_dup_packet(AVPacket *pkt)
{
    if (pkt->destruct != av_destruct_packet) {
        uint8_t *data;
Loading
Loading full blame...