diff options
Diffstat (limited to 'demux')
-rw-r--r-- | demux/codec_tags.c | 1 | ||||
-rw-r--r-- | demux/demux.c | 4 | ||||
-rw-r--r-- | demux/demux_mf.c | 209 | ||||
-rw-r--r-- | demux/demux_mkv.c | 5 | ||||
-rw-r--r-- | demux/demux_mng.c | 572 | ||||
-rw-r--r-- | demux/matroska.h | 1 | ||||
-rw-r--r-- | demux/mf.c | 211 | ||||
-rw-r--r-- | demux/mf.h | 19 |
8 files changed, 210 insertions, 812 deletions
diff --git a/demux/codec_tags.c b/demux/codec_tags.c index 66489aae03..dbf384fdbd 100644 --- a/demux/codec_tags.c +++ b/demux/codec_tags.c @@ -132,7 +132,6 @@ static const struct mp_codec_tag mp_audio_codec_tags[] = { {MKTAG('B', 'P', 'C', 'M'), "pcm_bluray"}, {MKTAG('P', 'L', 'X', 'F'), "pcm_lxf"}, {MKTAG('T', 'W', 'I', '2'), "twinvq"}, - {0x20776172, "pcm"}, // demux_mpg.c dvdpcm {0}, }; diff --git a/demux/demux.c b/demux/demux.c index ded0dd895e..da5957efdd 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -56,7 +56,6 @@ extern const demuxer_desc_t demuxer_desc_tv; extern const demuxer_desc_t demuxer_desc_mf; extern const demuxer_desc_t demuxer_desc_matroska; extern const demuxer_desc_t demuxer_desc_lavf; -extern const demuxer_desc_t demuxer_desc_mng; extern const demuxer_desc_t demuxer_desc_libass; extern const demuxer_desc_t demuxer_desc_subreader; extern const demuxer_desc_t demuxer_desc_playlist; @@ -79,9 +78,6 @@ const demuxer_desc_t *const demuxer_list[] = { &demuxer_desc_matroska, &demuxer_desc_lavf, &demuxer_desc_mf, -#if HAVE_MNG - &demuxer_desc_mng, -#endif &demuxer_desc_playlist, // Pretty aggressive, so should be last. &demuxer_desc_subreader, diff --git a/demux/demux_mf.c b/demux/demux_mf.c index 50888f59ad..6042771241 100644 --- a/demux/demux_mf.c +++ b/demux/demux_mf.c @@ -28,35 +28,29 @@ #include "talloc.h" #include "config.h" #include "mpvcore/mp_msg.h" +#include "mpvcore/mp_talloc.h" #include "stream/stream.h" #include "demux.h" #include "stheader.h" #include "mf.h" -#define MF_MAX_FILE_SIZE (1024*1024*256) - -static void free_mf(mf_t *mf) -{ - if (mf) { - for (int n = 0; n < mf->nr_of_files; n++) - free(mf->names[n]); - free(mf->names); - free(mf->streams); - free(mf); - } -} +#define MF_MAX_FILE_SIZE (1024 * 1024 * 256) static void demux_seek_mf(demuxer_t *demuxer, float rel_seek_secs, int flags) { - mf_t * mf = (mf_t *)demuxer->priv; - int newpos = (flags & SEEK_ABSOLUTE)?0:mf->curr_frame - 1; - - if ( flags & SEEK_FACTOR ) newpos+=rel_seek_secs*(mf->nr_of_files - 1); - else newpos+=rel_seek_secs * mf->sh->fps; - if ( newpos < 0 ) newpos=0; - if( newpos >= mf->nr_of_files) newpos=mf->nr_of_files - 1; - mf->curr_frame=newpos; + mf_t *mf = demuxer->priv; + int newpos = (flags & SEEK_ABSOLUTE) ? 0 : mf->curr_frame - 1; + + if (flags & SEEK_FACTOR) + newpos += rel_seek_secs * (mf->nr_of_files - 1); + else + newpos += rel_seek_secs * mf->sh->fps; + if (newpos < 0) + newpos = 0; + if (newpos >= mf->nr_of_files) + newpos = mf->nr_of_files - 1; + mf->curr_frame = newpos; } // return value: @@ -101,52 +95,52 @@ static int demux_mf_fill_buffer(demuxer_t *demuxer) // map file extension/type to a codec name static const struct { - const char *type; - const char *codec; + const char *type; + const char *codec; } type2format[] = { - { "bmp", "bmp" }, - { "dpx", "dpx" }, - { "j2c", "jpeg2000" }, - { "j2k", "jpeg2000" }, - { "jp2", "jpeg2000" }, - { "jpc", "jpeg2000" }, - { "jpeg", "mjpeg" }, - { "jpg", "mjpeg" }, - { "jps", "mjpeg" }, - { "jls", "ljpeg" }, - { "thm", "mjpeg" }, - { "db", "mjpeg" }, - { "pcx", "pcx" }, - { "png", "png" }, - { "pns", "png" }, - { "ptx", "ptx" }, - { "tga", "targa" }, - { "tif", "tiff" }, - { "tiff", "tiff" }, - { "sgi", "sgi" }, - { "sun", "sunrast" }, - { "ras", "sunrast" }, - { "rs", "sunrast" }, - { "ra", "sunrast" }, - { "im1", "sunrast" }, - { "im8", "sunrast" }, - { "im24", "sunrast" }, - { "im32", "sunrast" }, - { "sunras", "sunrast" }, - { "xbm", "xbm" }, - { "pam", "pam" }, - { "pbm", "pbm" }, - { "pgm", "pgm" }, - { "pgmyuv", "pgmyuv" }, - { "ppm", "ppm" }, - { "pnm", "ppm" }, - { "gif", "gif" }, // usually handled by demux_lavf - { "pix", "brender_pix" }, - { "exr", "exr" }, - { "pic", "pictor" }, - { "xface", "xface" }, - { "xwd", "xwd" }, - {0} + { "bmp", "bmp" }, + { "dpx", "dpx" }, + { "j2c", "jpeg2000" }, + { "j2k", "jpeg2000" }, + { "jp2", "jpeg2000" }, + { "jpc", "jpeg2000" }, + { "jpeg", "mjpeg" }, + { "jpg", "mjpeg" }, + { "jps", "mjpeg" }, + { "jls", "ljpeg" }, + { "thm", "mjpeg" }, + { "db", "mjpeg" }, + { "pcx", "pcx" }, + { "png", "png" }, + { "pns", "png" }, + { "ptx", "ptx" }, + { "tga", "targa" }, + { "tif", "tiff" }, + { "tiff", "tiff" }, + { "sgi", "sgi" }, + { "sun", "sunrast" }, + { "ras", "sunrast" }, + { "rs", "sunrast" }, + { "ra", "sunrast" }, + { "im1", "sunrast" }, + { "im8", "sunrast" }, + { "im24", "sunrast" }, + { "im32", "sunrast" }, + { "sunras", "sunrast" }, + { "xbm", "xbm" }, + { "pam", "pam" }, + { "pbm", "pbm" }, + { "pgm", "pgm" }, + { "pgmyuv", "pgmyuv" }, + { "ppm", "ppm" }, + { "pnm", "ppm" }, + { "gif", "gif" }, // usually handled by demux_lavf + { "pix", "brender_pix" }, + { "exr", "exr" }, + { "pic", "pictor" }, + { "xface", "xface" }, + { "xwd", "xwd" }, + {0} }; static const char *probe_format(mf_t *mf, enum demux_check check) @@ -167,7 +161,7 @@ static const char *probe_format(mf_t *mf, enum demux_check check) if (!mf_type) { mp_msg(MSGT_DEMUX, MSGL_ERR, "[demux_mf] file type was not set! (try --mf-type=ext)\n"); - } else { + } else { mp_msg(MSGT_DEMUX, MSGL_ERR, "[demux_mf] --mf-type set to an unknown codec!\n"); } @@ -175,67 +169,64 @@ static const char *probe_format(mf_t *mf, enum demux_check check) return NULL; } -static int demux_open_mf(demuxer_t* demuxer, enum demux_check check) +static int demux_open_mf(demuxer_t *demuxer, enum demux_check check) { - sh_video_t *sh_video = NULL; - mf_t *mf; - - if (strncmp(demuxer->stream->url, "mf://", 5) == 0 && - demuxer->stream->type == STREAMTYPE_MF) - { - mf = open_mf_pattern(demuxer->stream->url + 5); - } else { - mf = open_mf_single(demuxer->stream->url); - mf->streams = calloc(1, sizeof(struct stream *)); - mf->streams[0] = demuxer->stream; - } + sh_video_t *sh_video = NULL; + mf_t *mf; + + if (strncmp(demuxer->stream->url, "mf://", 5) == 0 && + demuxer->stream->type == STREAMTYPE_MF) + mf = open_mf_pattern(demuxer, demuxer->stream->url + 5); + else { + mf = open_mf_single(demuxer, demuxer->stream->url); + int bog = 0; + MP_TARRAY_APPEND(mf, mf->streams, bog, demuxer->stream); + } - if (!mf || mf->nr_of_files < 1) - goto error; + if (!mf || mf->nr_of_files < 1) + goto error; - const char *codec = probe_format(mf, check); - if (!codec) - goto error; + const char *codec = probe_format(mf, check); + if (!codec) + goto error; - mf->curr_frame = 0; + mf->curr_frame = 0; - // create a new video stream header - struct sh_stream *sh = new_sh_stream(demuxer, STREAM_VIDEO); - sh_video = sh->video; + // create a new video stream header + struct sh_stream *sh = new_sh_stream(demuxer, STREAM_VIDEO); + sh_video = sh->video; - sh_video->gsh->codec = codec; - sh_video->disp_w = 0; - sh_video->disp_h = 0; - sh_video->fps = mf_fps; + sh_video->gsh->codec = codec; + sh_video->disp_w = 0; + sh_video->disp_h = 0; + sh_video->fps = mf_fps; - mf->sh = sh_video; - demuxer->priv=(void*)mf; - demuxer->seekable = true; + mf->sh = sh_video; + demuxer->priv = (void *)mf; + demuxer->seekable = true; - return 0; + return 0; error: - free_mf(mf); - return -1; + return -1; } -static void demux_close_mf(demuxer_t* demuxer) { - mf_t *mf = demuxer->priv; - - free_mf(mf); +static void demux_close_mf(demuxer_t *demuxer) +{ } -static int demux_control_mf(demuxer_t *demuxer, int cmd, void *arg) { - mf_t *mf = (mf_t *)demuxer->priv; +static int demux_control_mf(demuxer_t *demuxer, int cmd, void *arg) +{ + mf_t *mf = demuxer->priv; - switch(cmd) { + switch (cmd) { case DEMUXER_CTRL_GET_TIME_LENGTH: - *((double *)arg) = (double)mf->nr_of_files / mf->sh->fps; - return DEMUXER_CTRL_OK; + *((double *)arg) = (double)mf->nr_of_files / mf->sh->fps; + return DEMUXER_CTRL_OK; default: - return DEMUXER_CTRL_NOTIMPL; - } + return DEMUXER_CTRL_NOTIMPL; + } } const demuxer_desc_t demuxer_desc_mf = { diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 7a9aaa0f87..7a30721e66 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -1355,6 +1355,7 @@ static struct mkv_audio_tag { { MKV_A_DTS, 0, 0x2001 }, { MKV_A_PCM, 0, 0x0001 }, { MKV_A_PCM_BE, 0, 0x0001 }, + { MKV_A_PCM_FLT, 0, 0x0003 }, { MKV_A_AAC_2MAIN, 0, MP_FOURCC('M', 'P', '4', 'A') }, { MKV_A_AAC_2LC, 1, MP_FOURCC('M', 'P', '4', 'A') }, { MKV_A_AAC_2SSR, 0, MP_FOURCC('M', 'P', '4', 'A') }, @@ -1464,10 +1465,10 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track) free(sh_a->wf); sh_a->wf = NULL; } else if (track->a_formattag == 0x0001) { /* PCM || PCM_BE */ - sh_a->wf->nAvgBytesPerSec = sh_a->channels.num * sh_a->samplerate * 2; - sh_a->wf->nBlockAlign = sh_a->wf->nAvgBytesPerSec; if (!strcmp(track->codec_id, MKV_A_PCM_BE)) sh_a->format = MP_FOURCC('t', 'w', 'o', 's'); + } else if (track->a_formattag == 0x0003) { /* PCM_FLT */ + /* ok */ } else if (!strcmp(track->codec_id, MKV_A_QDMC) || !strcmp(track->codec_id, MKV_A_QDMC2)) { sh_a->wf->nAvgBytesPerSec = 16000; diff --git a/demux/demux_mng.c b/demux/demux_mng.c deleted file mode 100644 index f408687c1b..0000000000 --- a/demux/demux_mng.c +++ /dev/null @@ -1,572 +0,0 @@ -/* - * MNG file demuxer for MPlayer - * - * Copyright (C) 2008 Stefan Schuermans <stefan blinkenarea org> - * - * 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 <unistd.h> - -#include "config.h" - -#include "mpvcore/mp_msg.h" - -#include "stream/stream.h" -#include "demux.h" -#include "stheader.h" -#include "video/img_fourcc.h" - -#define MNG_SUPPORT_READ -#define MNG_SUPPORT_DISPLAY -#include <libmng.h> - -/** - * \brief private context structure - * - * This structure is used as private data for MPlayer demuxer - * and also as private data for the MNG library. - * - * All members ending in \p _ms are in milliseconds - */ -typedef struct { - stream_t * stream; ///< pointer to MNG data input stream - mng_handle h_mng; ///< MNG library image handle - int header_processed; ///< if MNG image header is processed - mng_uint32 width; ///< MNG image width - mng_uint32 height; ///< MNG image height - int total_time_ms; ///< total MNG animation time - unsigned char * canvas; /**< \brief canvas to draw the image onto - * \details - * \li lines top-down - * \li pixels left-to-right - * \li channels RGB - * \li no padding - * \li NULL if no canvas yet - */ - int displaying; /**< \brief if displaying already, - * i.e. if mng_display has - * already been called - */ - int finished; ///< if animation is finished - int global_time_ms; ///< current global time for MNG library - int anim_cur_time_ms; ///< current frame time in MNG animation - int anim_frame_duration_ms; ///< current frame duration in MNG animation - int show_cur_time_ms; /**< \brief current time in the show process, - * i.e. time of last demux packet - */ - int show_next_time_ms; /**< \brief next time in the show process, - * i.e. time of next demux packet - */ - int timer_ms; /**< \brief number of milliseconds after which - * libmng wants to be called again - */ -} mng_priv_t; - -/** - * \brief MNG library callback: Allocate a new zero-filled memory block. - * \param[in] size memory block size - * \return pointer to new memory block - */ -static mng_ptr demux_mng_alloc(mng_size_t size) -{ - return calloc(1, size); -} - -/** - * \brief MNG library callback: Free memory block. - * \param[in] ptr pointer to memory block - * \param[in] size memory block size - */ -static void demux_mng_free(mng_ptr ptr, mng_size_t size) -{ - free(ptr); -} - -/** - * \brief MNG library callback: Open MNG stream. - * \param[in] h_mng MNG library image handle - * \return \p MNG_TRUE on success, \p MNG_FALSE on error (never happens) - */ -static mng_bool demux_mng_openstream(mng_handle h_mng) -{ - mng_priv_t * mng_priv = mng_get_userdata(h_mng); - stream_t * stream = mng_priv->stream; - - // rewind stream to the beginning - stream_seek(stream, stream->start_pos); - - return MNG_TRUE; -} - -/** - * \brief MNG library callback: Close MNG stream. - * \param[in] h_mng MNG library image handle - * \return \p MNG_TRUE on success, \p MNG_FALSE on error (never happens) - */ -static mng_bool demux_mng_closestream(mng_handle h_mng) -{ - return MNG_TRUE; -} - -/** - * \brief MNG library callback: Read data from stream. - * \param[in] h_mng MNG library image handle - * \param[in] buf pointer to buffer to fill with data - * \param[in] size size of buffer - * \param[out] read number of bytes read from stream - * \return \p MNG_TRUE on success, \p MNG_FALSE on error (never happens) - */ -static mng_bool demux_mng_readdata(mng_handle h_mng, mng_ptr buf, - mng_uint32 size, mng_uint32 * read) -{ - mng_priv_t * mng_priv = mng_get_userdata(h_mng); - stream_t * stream = mng_priv->stream; - - // simply read data from stream and return number of bytes or error - *read = stream_read(stream, buf, size); - - return MNG_TRUE; -} - -/** - * \brief MNG library callback: Header information is processed now. - * \param[in] h_mng MNG library image handle - * \param[in] width image width - * \param[in] height image height - * \return \p MNG_TRUE on success, \p MNG_FALSE on error - */ -static mng_bool demux_mng_processheader(mng_handle h_mng, mng_uint32 width, - mng_uint32 height) -{ - mng_priv_t * mng_priv = mng_get_userdata(h_mng); - - // remember size in private data - mng_priv->header_processed = 1; - mng_priv->width = width; - mng_priv->height = height; - - // get total animation time - mng_priv->total_time_ms = mng_get_playtime(h_mng); - - // allocate canvas - mng_priv->canvas = malloc(height * width * 4); - if (!mng_priv->canvas) { - mp_msg(MSGT_DEMUX, MSGL_ERR, - "demux_mng: could not allocate canvas of size %dx%d\n", - width, height); - return MNG_FALSE; - } - - return MNG_TRUE; -} - -/** - * \brief MNG library callback: Get access to a canvas line. - * \param[in] h_mng MNG library image handle - * \param[in] line y coordinate of line to access - * \return pointer to line on success, \p MNG_NULL on error - */ -static mng_ptr demux_mng_getcanvasline(mng_handle h_mng, mng_uint32 line) -{ - mng_priv_t * mng_priv = mng_get_userdata(h_mng); - - // return pointer to canvas line - if (line < mng_priv->height && mng_priv->canvas) - return (mng_ptr)(mng_priv->canvas + line * mng_priv->width * 4); - else - return (mng_ptr)MNG_NULL; -} - -/** - * \brief MNG library callback: A part of the canvas should be shown. - * - * This function is called by libmng whenever it thinks a - * rectangular part of the display should be updated. This - * can happen multiple times for a frame and/or a single time - * for a frame. Only the the part of the display occupied by - * the rectangle defined by x, y, width, height is to be updated. - * It is possible that some parts of the display are not updated - * for many frames. There is no chance here to find out if the - * current frame is completed with this update or not. - * - * This mechanism does not match MPlayer's demuxer architecture, - * so it will not be used exactly as intended by libmng. - * A new frame is generated in the demux_mng_fill_buffer() function - * whenever libmng tells us to wait for some time. - * - * \param[in] h_mng MNG library image handle - * \param[in] x rectangle's left edge - * \param[in] y rectangle's top edge - * \param[in] width rectangle's width - * \param[in] height rectangle's heigt - * \return \p MNG_TRUE on success, \p MNG_FALSE on error (never happens) - */ -static mng_bool demux_mng_refresh(mng_handle h_mng, mng_uint32 x, mng_uint32 y, - mng_uint32 width, mng_uint32 height) -{ - // nothing to do here, the image data is already on the canvas - return MNG_TRUE; -} - -/** - * \brief MNG library callback: Get how many milliseconds have passed. - * \param[in] h_mng MNG library image handle - * \return global time in milliseconds - */ -static mng_uint32 demux_mng_gettickcount(mng_handle h_mng) -{ - mng_priv_t * mng_priv = mng_get_userdata(h_mng); - - // return current global time - return mng_priv->global_time_ms; -} - -/** - * \brief MNG library callback: Please call again after some milliseconds. - * \param[in] h_mng MNG library image handle - * \param[in] msecs number of milliseconds after which to call again - * \return \p MNG_TRUE on success, \p MNG_FALSE on error (never happens) - */ -static mng_bool demux_mng_settimer(mng_handle h_mng, mng_uint32 msecs) -{ - mng_priv_t * mng_priv = mng_get_userdata(h_mng); - - // Save number of milliseconds after which to call the MNG library again - // in private data. - mng_priv->timer_ms = msecs; - return MNG_TRUE; -} - -/** - * \brief MPlayer callback: Fill buffer from MNG stream. - * \param[in] demuxer demuxer structure - * \return \p 1 on success, \p 0 on error - */ -static int demux_mng_fill_buffer(demuxer_t * demuxer) -{ - mng_priv_t * mng_priv = demuxer->priv; - mng_handle h_mng = mng_priv->h_mng; - mng_retcode mng_ret; - demux_packet_t * dp; - - // exit if animation is finished - if (mng_priv->finished) - return 0; - - // advance animation to requested next show time - while (mng_priv->anim_cur_time_ms + mng_priv->anim_frame_duration_ms - <= mng_priv->show_next_time_ms && !mng_priv->finished) { - - // advance global and animation time - mng_priv->global_time_ms += mng_priv->anim_frame_duration_ms; - mng_priv->anim_cur_time_ms += mng_priv->anim_frame_duration_ms; - - // Clear variable MNG library will write number of milliseconds to - // (via settimer callback). - mng_priv->timer_ms = 0; - - // get next image from MNG library - if (mng_priv->displaying) - mng_ret = mng_display_resume(h_mng); // resume displaying MNG data - // to canvas - else - mng_ret = mng_display(h_mng); // start displaying MNG data to canvas - if (mng_ret && mng_ret != MNG_NEEDTIMERWAIT) { - mp_msg(MSGT_DEMUX, MSGL_ERR, - "demux_mng: could not display MNG data to canvas: " - "mng_retcode %d\n", mng_ret); - return 0; - } - mng_priv->displaying = 1; // mng_display() has been called now - mng_priv->finished = mng_ret == 0; // animation is finished iff - // mng_display() returned 0 - - // save current frame duration - mng_priv->anim_frame_duration_ms = mng_priv->timer_ms < 1 - ? 1 : mng_priv->timer_ms; - - } // while (mng_priv->anim_cur_time_ms + ... - - // create a new demuxer packet - dp = new_demux_packet(mng_priv->height * mng_priv->width * 4); - - // copy image data into demuxer packet - memcpy(dp->buffer, mng_priv->canvas, - mng_priv->height * mng_priv->width * 4); - - // set current show time to requested show time - mng_priv->show_cur_time_ms = mng_priv->show_next_time_ms; - - // get time of next frame to show - mng_priv->show_next_time_ms = mng_priv->anim_cur_time_ms - + mng_priv->anim_frame_duration_ms; - - // Set position and timing information in demuxer video and demuxer packet. - // - Time must be time of next frame and always be > 0 for the variable - // frame time mechanism (GIF, MATROSKA, MNG) in video.c to work. - dp->pts = (float)mng_priv->show_next_time_ms / 1000.0f; - dp->pos = stream_tell(demuxer->stream); - demuxer_add_packet(demuxer, demuxer->streams[0], dp); - - return 1; -} - -static int demux_mng_open(demuxer_t * demuxer, enum demux_check check) -{ - mng_priv_t * mng_priv; - mng_handle h_mng; - mng_retcode mng_ret; - sh_video_t * sh_video; - - if (check > DEMUX_CHECK_REQUEST) - return -1; // check too unsafe - if (check > DEMUX_CHECK_FORCE) { - char buf[4]; - if (stream_read(demuxer->stream, buf, 4) != 4) - return -1; - if (memcmp(buf, "\x8AMNG", 4)) - return -1; - stream_seek(demuxer->stream, demuxer->stream->start_pos); - } - - // create private data structure - mng_priv = calloc(1, sizeof(mng_priv_t)); - - //stream pointer into private data - mng_priv->stream = demuxer->stream; - - // initialize MNG image instance - h_mng = mng_initialize((mng_ptr)mng_priv, demux_mng_alloc, - demux_mng_free, MNG_NULL); - if (!h_mng) { - mp_msg(MSGT_DEMUX, MSGL_ERR, - "demux_mng: could not initialize MNG image instance\n"); - free(mng_priv); - return -1; - } - - // MNG image handle into private data - mng_priv->h_mng = h_mng; - - // set required MNG callbacks - if (mng_setcb_openstream(h_mng, demux_mng_openstream) || - mng_setcb_closestream(h_mng, demux_mng_closestream) || - mng_setcb_readdata(h_mng, demux_mng_readdata) || - mng_setcb_processheader(h_mng, demux_mng_processheader) || - mng_setcb_getcanvasline(h_mng, demux_mng_getcanvasline) || - mng_setcb_refresh(h_mng, demux_mng_refresh) || - mng_setcb_gettickcount(h_mng, demux_mng_gettickcount) || - mng_setcb_settimer(h_mng, demux_mng_settimer) || - mng_set_canvasstyle(h_mng, MNG_CANVAS_RGBA8)) { - mp_msg(MSGT_DEMUX, MSGL_ERR, - "demux_mng: could not set MNG callbacks\n"); - mng_cleanup(&h_mng); - free(mng_priv); - return -1; - } - - // start reading MNG data - mng_ret = mng_read(h_mng); - if (mng_ret) { - mp_msg(MSGT_DEMUX, MSGL_ERR, - "demux_mng: could not start reading MNG data: " - "mng_retcode %d\n", mng_ret); - mng_cleanup(&h_mng); - free(mng_priv); - return -1; - } - - // check that MNG header is processed now - if (!mng_priv->header_processed) { - mp_msg(MSGT_DEMUX, MSGL_ERR, - "demux_mng: internal error: header not processed\n"); - mng_cleanup(&h_mng); - free(mng_priv); - return -1; - } - - // create a new video stream header - struct sh_stream *sh = new_sh_stream(demuxer, STREAM_VIDEO); - sh_video = sh->video; - - // set format of pixels in video packets - sh_video->gsh->codec = "rawvideo"; - sh_video->format = MP_FOURCC_RGB32; - - // set framerate to some value (MNG does not have a fixed framerate) - sh_video->fps = 5.0f; - - // set video frame parameters - sh_video->bih = calloc(1, sizeof(*sh_video->bih)); - sh_video->bih->biCompression = sh_video->format; - sh_video->bih->biWidth = mng_priv->width; - sh_video->bih->biHeight = mng_priv->height; - sh_video->bih->biBitCount = 32; - sh_video->bih->biPlanes = 1; - - // weirdly broken - demuxer->accurate_seek = false; - - // set private data in demuxer and return demuxer - demuxer->priv = mng_priv; - return 0; -} - -/** - * \brief MPlayer callback: Close MNG stream. - * \param[in] demuxer demuxer structure - */ -static void demux_mng_close(demuxer_t* demuxer) -{ - mng_priv_t * mng_priv = demuxer->priv; - - if (mng_priv) { - - // shutdown MNG image instance - if (mng_priv->h_mng) - mng_cleanup(&mng_priv->h_mng); - - // free private data - free(mng_priv->canvas); - - free(mng_priv); - } -} - -/** - * \brief MPlayer callback: Seek in MNG stream. - * \param[in] demuxer demuxer structure - * \param[in] rel_seek_secs relative seek time in seconds - * \param[in] audio_delay unused, MNG does not contain audio - * \param[in] flags bit flags, \p 1: absolute, \p 2: fractional position - */ -static void demux_mng_seek(demuxer_t * demuxer, float rel_seek_secs, int flags) -{ - mng_priv_t * mng_priv = demuxer->priv; - mng_handle h_mng = mng_priv->h_mng; - mng_retcode mng_ret; - int seek_ms, pos_ms; - - // exit if not ready to seek (header not yet read or not yet displaying) - if (!mng_priv->header_processed || !mng_priv->displaying) - return; - - // get number of milliseconds to seek to - if (flags & 2) // seek by fractional position (0.0 ... 1.0) - seek_ms = (int)(rel_seek_secs * (float)mng_priv->total_time_ms); - else // seek by time in seconds - seek_ms = (int)(rel_seek_secs * 1000.0f + 0.5f); - - // get new position in milliseconds - if (flags & 1) // absolute - pos_ms = seek_ms; - else // relative - pos_ms = mng_priv->show_cur_time_ms + seek_ms; - - // fix position - if (pos_ms < 0) - pos_ms = 0; - if (pos_ms > mng_priv->total_time_ms) - pos_ms = mng_priv->total_time_ms; - - // FIXME - // In principle there is a function to seek in MNG: mng_display_gotime(). - // - Using it did not work out (documentation is very brief, - // example code does not exist?). - // - The following code works, but its performance is quite bad. - - // seeking forward - if (pos_ms >= mng_priv->show_cur_time_ms) { - - // Simply advance show time to seek position. - // - Everything else will be handled in demux_mng_fill_buffer(). - mng_priv->show_next_time_ms = pos_ms; - - } // if (pos_ms > mng_priv->show_time_ms) - - // seeking backward - else { // if (pos_ms > mng_priv->show_time_ms) - - // Clear variable MNG library will write number of milliseconds to - // (via settimer callback). - mng_priv->timer_ms = 0; - - // Restart displaying and advance show time to seek position. - // - Everything else will be handled in demux_mng_fill_buffer(). - mng_ret = mng_display_reset(h_mng); - // If a timer wait is needed, fool libmng that requested time - // passed and try again. - if (mng_ret == MNG_NEEDTIMERWAIT) { - mng_priv->global_time_ms += mng_priv->timer_ms; - mng_ret = mng_display_reset(h_mng); - } - if (mng_ret) { - mp_msg(MSGT_DEMUX, MSGL_ERR, - "demux_mng: could not reset MNG display state: " - "mng_retcode %d\n", mng_ret); - return; - } - mng_priv->displaying = 0; - mng_priv->finished = 0; - mng_priv->anim_cur_time_ms = 0; - mng_priv->anim_frame_duration_ms = 0; - mng_priv->show_next_time_ms = pos_ms; - - } // if (pos_ms > mng_priv->show_time_ms) ... else -} - -/** - * \brief MPlayer callback: Control MNG stream. - * \param[in] demuxer demuxer structure - * \param[in] cmd code of control command to perform - * \param[in,out] arg command argument - * \return demuxer control response code - */ -static int demux_mng_control(demuxer_t * demuxer, int cmd, void * arg) -{ - mng_priv_t * mng_priv = demuxer->priv; - - switch(cmd) { - - // get total movie length - case DEMUXER_CTRL_GET_TIME_LENGTH: - if (mng_priv->header_processed) { - *(double *)arg = (double)mng_priv->total_time_ms / 1000.0; - return DEMUXER_CTRL_OK; - } else { - return DEMUXER_CTRL_DONTKNOW; - } - break; - - default: - return DEMUXER_CTRL_NOTIMPL; - - } // switch (cmd) -} - -const demuxer_desc_t demuxer_desc_mng = { - .name = "mng", - .desc = "MNG", - .fill_buffer = demux_mng_fill_buffer, - .open = demux_mng_open, - .close = demux_mng_close, - .seek = demux_mng_seek, - .control = demux_mng_control, -}; diff --git a/demux/matroska.h b/demux/matroska.h index 796f6c24d3..a6be019b2d 100644 --- a/demux/matroska.h +++ b/demux/matroska.h @@ -40,6 +40,7 @@ #define MKV_A_MP3 "A_MPEG/L3" #define MKV_A_PCM "A_PCM/INT/LIT" #define MKV_A_PCM_BE "A_PCM/INT/BIG" +#define MKV_A_PCM_FLT "A_PCM/FLOAT/IEEE" #define MKV_A_VORBIS "A_VORBIS" #define MKV_A_OPUS "A_OPUS" #define MKV_A_OPUS_EXP "A_OPUS/EXPERIMENTAL" diff --git a/demux/mf.c b/demux/mf.c index d1060efc3c..13021aa53a 100644 --- a/demux/mf.c +++ b/demux/mf.c @@ -36,149 +36,132 @@ #include "osdep/glob.h" #endif +#include "talloc.h" #include "mpvcore/mp_msg.h" #include "stream/stream.h" #include "mpvcore/path.h" +#include "mpvcore/mp_talloc.h" #include "mf.h" double mf_fps = 25.0; -char * mf_type = NULL; //"jpg"; +char *mf_type = NULL; //"jpg"; -mf_t* open_mf_pattern(char * filename) +static void mf_add(mf_t *mf, const char *fname) +{ + fname = talloc_strdup(mf, fname); + MP_TARRAY_APPEND(mf, mf->names, mf->nr_of_files, fname); +} + +mf_t *open_mf_pattern(void *talloc_ctx, char *filename) { #if defined(HAVE_GLOB) || defined(__MINGW32__) - glob_t gg; - int i; - char * fname = NULL; - mf_t * mf; - int error_count = 0; - int count = 0; - - mf=calloc( 1,sizeof( mf_t ) ); - - if( filename[0] == '@' ) - { - FILE *lst_f=fopen(filename + 1,"r"); - if ( lst_f ) - { - fname=malloc(MP_PATH_MAX); - while ( fgets( fname,MP_PATH_MAX,lst_f ) ) |