/*
* DEMUXER v2.5
*
* This file is part of MPlayer.
*
* MPlayer 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 of the License, or
* (at your option) any later version.
*
* MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "config.h"
#include "options.h"
#include "talloc.h"
#include "mp_msg.h"
#include "m_config.h"
#include "libvo/fastmemcpy.h"
#include "stream/stream.h"
#include "demuxer.h"
#include "stheader.h"
#include "mf.h"
#include "libaf/af_format.h"
#include "libavcodec/avcodec.h"
#if MP_INPUT_BUFFER_PADDING_SIZE < FF_INPUT_BUFFER_PADDING_SIZE
#error MP_INPUT_BUFFER_PADDING_SIZE is too small!
#endif
static void clear_parser(sh_common_t *sh);
// Demuxer list
extern const struct demuxer_desc demuxer_desc_edl;
extern const struct demuxer_desc demuxer_desc_cue;
extern const demuxer_desc_t demuxer_desc_rawaudio;
extern const demuxer_desc_t demuxer_desc_rawvideo;
extern const demuxer_desc_t demuxer_desc_tv;
extern const demuxer_desc_t demuxer_desc_mf;
extern const demuxer_desc_t demuxer_desc_avi;
extern const demuxer_desc_t demuxer_desc_asf;
extern const demuxer_desc_t demuxer_desc_matroska;
extern const demuxer_desc_t demuxer_desc_gif;
extern const demuxer_desc_t demuxer_desc_lavf;
extern const demuxer_desc_t demuxer_desc_lavf_preferred;
extern const demuxer_desc_t demuxer_desc_mng;
/* Please do not add any new demuxers here. If you want to implement a new
* demuxer, add it to libavformat, except for wrappers around external
* libraries and demuxers requiring binary support. */
const demuxer_desc_t *const demuxer_list[] = {
&demuxer_desc_edl,
&demuxer_desc_cue,
&demuxer_desc_rawaudio,
&demuxer_desc_rawvideo,
#ifdef CONFIG_TV
&demuxer_desc_tv,
#endif
&demuxer_desc_mf,
&demuxer_desc_lavf_preferred,
&demuxer_desc_avi,
&demuxer_desc_asf,
&demuxer_desc_matroska,
#ifdef CONFIG_GIF
&demuxer_desc_gif,
#endif
&demuxer_desc_lavf,
#ifdef CONFIG_MNG
&demuxer_desc_mng,
#endif
/* Please do not add any new demuxers here. If you want to implement a new
* demuxer, add it to libavformat, except for wrappers around external
* libraries and demuxers requiring binary support. */
NULL
};
static struct demux_packet *create_packet(size_t len)
{
if (len > 1000000000) {
mp_msg(MSGT_DEMUXER, MSGL_FATAL, "Attempt to allocate demux packet "
"over 1 GB!\n");
abort();
}
struct demux_packet *dp = malloc(sizeof(struct demux_packet));
dp->len = len;
dp->next = NULL;
dp->pts = MP_NOPTS_VALUE;
dp->duration = -1;
dp->stream_pts = MP_NOPTS_VALUE;
dp->pos = 0;
dp->keyframe = false;
dp->refcount = 1;
dp->master = NULL;
dp->buffer = NULL;
dp->avpacket = NULL;
return dp;
}
struct demux_packet *new_demux_packet(size_t len)
{
struct demux_packet *dp = create_packet(len);
dp->buffer = malloc(len + MP_INPUT_BUFFER_PADDING_SIZE);
if (!dp->buffer) {
mp_msg(MSGT_DEMUXER, MSGL_FATAL, "Memory allocation failure!\n");
abort();
}
memset(dp->buffer + len, 0, 8);
return dp;
}
// data must already have suitable padding
struct demux_packet *new_demux_packet_fromdata(void *data, size_t len)
{
struct demux_packet *dp = create_packet(len);
dp->buffer = data;
return dp;
}
void resize_demux_packet(struct demux_packet *dp, size_t len)
{
if (len > 1000000000) {
mp_msg(MSGT_DEMUXER, MSGL_FATAL, "Attempt to realloc demux packet "
"over 1 GB!\n");
abort();
}
dp->buffer = realloc(dp->buffer, len + MP_INPUT_BUFFER_PADDING_SIZE);
if (!dp->buffer) {
mp_msg(MSGT_DEMUXER, MSGL_FATAL, "Memory allocation failure!\n");
abort();
}
memset(dp->buffer + len, 0, 8);
dp->len = len;
}
struct demux_packet *clone_demux_packet(struct demux_packet *pack)
{
struct demux_packet *dp = malloc(sizeof(struct demux_packet));
while (pack->master)
pack = pack->master; // find the master
memcpy(dp, pack, sizeof(struct demux_packet));
dp->next = NULL;
dp->refcount = 0;
dp->master = pack;
pack->refcount++;
return dp;
}
void free_demux_packet(struct demux_packet *dp)
{
if (dp->master == NULL) { //dp is a master packet
dp->refcount--;
if (dp->refcount == 0) {
if (dp->avpacket)
talloc_free(dp->avpacket);
else
free(dp->buffer);
free(dp);
}
return;
}
// dp is a clone:
free_demux_packet(dp->master);
free(dp);
}
static void free_demuxer_stream(struct demux_stream *ds)
{
ds_free_packs(ds);
free(ds);
}
static struct demux_stream *new_demuxer_stream(struct demuxer *demuxer, int id)
{
demux_stream_t *ds = malloc(sizeof(demux_stream_t));
*ds = (demux_stream_t){
.id = id,
.demuxer = demuxer,
.asf_seq = -1,
};
return ds;
}
/**
* Get demuxer description structure for a given demuxer type
*
* @param file_format type of the demuxer
* @return structure for the demuxer, NULL if not found
*/
static const demuxer_desc_t *get_demuxer_desc_from_type(int file_format)
{
int i;
for (i = 0; demuxer_list[i]; i++)
if (file_format == demuxer_list[i]->type)
return demuxer_list[i];
return NULL;
}
demuxer_t *new_demuxer(struct MPOpts *opts, stream_t *stream, int type,
|