diff options
-rw-r--r-- | DOCS/man/en/mplayer.1 | 2 | ||||
-rw-r--r-- | DOCS/man/zh_CN/mplayer.1 | 11 | ||||
-rw-r--r-- | command.c | 68 | ||||
-rw-r--r-- | etc/codecs.conf | 107 | ||||
-rw-r--r-- | libmpcodecs/ad_ffmpeg.c | 15 | ||||
-rw-r--r-- | libmpcodecs/mp_image.h | 4 | ||||
-rw-r--r-- | libmpcodecs/vd_ffmpeg.c | 10 | ||||
-rw-r--r-- | libmpcodecs/vd_vfw.c | 1 | ||||
-rw-r--r-- | libmpcodecs/vf.c | 6 | ||||
-rw-r--r-- | libmpcodecs/vf_palette.c | 2 | ||||
-rw-r--r-- | libmpdemux/aviheader.c | 1 | ||||
-rw-r--r-- | libmpdemux/demux_mpg.c | 1 | ||||
-rw-r--r-- | libmpdemux/demux_ts.c | 1 | ||||
-rw-r--r-- | libmpdemux/demuxer.c | 136 | ||||
-rw-r--r-- | libmpdemux/demuxer.h | 1 | ||||
-rw-r--r-- | libmpdemux/extension.c | 11 | ||||
-rw-r--r-- | libmpdemux/stheader.h | 48 | ||||
-rw-r--r-- | libvo/vo_gl.c | 62 | ||||
-rw-r--r-- | libvo/x11_common.c | 2 | ||||
-rw-r--r-- | libvo/x11_common.h | 2 | ||||
-rw-r--r-- | mplayer.c | 7 | ||||
-rw-r--r-- | vobsub.c | 1754 |
22 files changed, 1248 insertions, 1004 deletions
diff --git a/DOCS/man/en/mplayer.1 b/DOCS/man/en/mplayer.1 index 61d2e36adf..434f12c348 100644 --- a/DOCS/man/en/mplayer.1 +++ b/DOCS/man/en/mplayer.1 @@ -1197,7 +1197,7 @@ amount of memory. Allows a socket to be reused by other processes as soon as it is closed. . .TP -.B \-bandwidth <value> (network only) +.B \-bandwidth <Bytes> (network only) Specify the maximum bandwidth for network streaming (for servers that are able to send content in different bitrates). Useful if you want to watch live streamed media behind a slow connection. diff --git a/DOCS/man/zh_CN/mplayer.1 b/DOCS/man/zh_CN/mplayer.1 index e026e4a002..c2bf86f4f3 100644 --- a/DOCS/man/zh_CN/mplayer.1 +++ b/DOCS/man/zh_CN/mplayer.1 @@ -3581,6 +3581,9 @@ OSD 颜色(默认值是:0x00ffffff,对应不透明的白色)。 此限制帧率到 (水平刷新率 / n)。 需要 GLX_SGI_swap_control 的支持。 某些(大多数/所有?)实现仅工作于全屏模式。 +.IPs ycbcr +使用 GL_MESA_ycbcr_texture 扩展组件将 YUV 转换为 RGB 格式。 +在大多数情况下,该方法很可能比使用软件转换成 RGB 慢。 .IPs yuv=<n> 选择 YUV 到 RGB 转换的类型。 .RSss @@ -3620,9 +3623,6 @@ GL_ARB_fragment_shader!)。至少需要三个纹理单位。提供饱和度 对红, 绿和蓝色, Gamma 也能被独立设置。 速度比其他方法更多地依赖于 GPU 内存带宽。 .RE -.IPs ycbcr -使用 GL_MESA_ycbcr_texture 扩展组件完成 YUV 至 RGB 的转换。 -在大多数情况下,这可能比使用软件方式转换至 RGB 要慢。 .IPs lscale=<n> 选择缩放功能供调节发光性。 仅对 yuv 模式 2, 3, 4 和 6 有效。 @@ -3657,6 +3657,11 @@ GL_ARB_fragment_shader!)。至少需要三个纹理单位。提供饱和度 如果启用(默认), 使用 GL_LINEAR 插值, 否则使用 GL_NEAREST 用于 customtex 纹理。 .IPs (no)customtrect 如果启用, 使用 texture_rectangle 用于 customtex 纹理。默认是停用。 +.IPs (no)mipmapgen +一旦启用,将自动生成视频的贴图。该选项与 customprog 和 TXB 一起使用 +有助于实现一个具有大影响半径的模糊滤镜。 +对于大多数 OpenGL 的实现产品来说,该选项作用于任何非 RGB 的格式都很慢。 +默认值为禁用。 .RE .sp 1 .RS @@ -824,23 +824,22 @@ static int mp_property_audio(m_option_t *prop, int action, void *arg, MPContext *mpctx) { struct MPOpts *opts = &mpctx->opts; - int current_id = -1, tmp; + int current_id, tmp; + if (!mpctx->demuxer || !mpctx->demuxer->audio) + return M_PROPERTY_UNAVAILABLE; + current_id = mpctx->demuxer->audio->id; switch (action) { case M_PROPERTY_GET: - if (!mpctx->sh_audio) - return M_PROPERTY_UNAVAILABLE; if (!arg) return M_PROPERTY_ERROR; - *(int *) arg = opts->audio_id; + *(int *) arg = current_id; return M_PROPERTY_OK; case M_PROPERTY_PRINT: - if (!mpctx->sh_audio) - return M_PROPERTY_UNAVAILABLE; if (!arg) return M_PROPERTY_ERROR; - if (opts->audio_id < 0) + if (current_id < 0) *(char **) arg = strdup(_("disabled")); else { char lang[40] = _("unknown"); @@ -849,7 +848,7 @@ static int mp_property_audio(m_option_t *prop, int action, void *arg, av_strlcpy(lang, sh->lang, 40); #ifdef CONFIG_DVDREAD else if (mpctx->stream->type == STREAMTYPE_DVD) { - int code = dvd_lang_from_aid(mpctx->stream, opts->audio_id); + int code = dvd_lang_from_aid(mpctx->stream, current_id); if (code) { lang[0] = code >> 8; lang[1] = code; @@ -860,22 +859,19 @@ static int mp_property_audio(m_option_t *prop, int action, void *arg, #ifdef CONFIG_DVDNAV else if (mpctx->stream->type == STREAMTYPE_DVDNAV) - mp_dvdnav_lang_from_aid(mpctx->stream, opts->audio_id, lang); + mp_dvdnav_lang_from_aid(mpctx->stream, current_id, lang); #endif *(char **) arg = malloc(64); - snprintf(*(char **) arg, 64, "(%d) %s", opts->audio_id, lang); + snprintf(*(char **) arg, 64, "(%d) %s", current_id, lang); } return M_PROPERTY_OK; case M_PROPERTY_STEP_UP: case M_PROPERTY_SET: - if (!mpctx->demuxer) - return M_PROPERTY_UNAVAILABLE; if (action == M_PROPERTY_SET && arg) tmp = *((int *) arg); else tmp = -1; - current_id = mpctx->demuxer->audio->id; opts->audio_id = demuxer_switch_audio(mpctx->demuxer, tmp); if (opts->audio_id == -2 || (opts->audio_id > -1 @@ -903,34 +899,32 @@ static int mp_property_video(m_option_t *prop, int action, void *arg, MPContext *mpctx) { struct MPOpts *opts = &mpctx->opts; - int current_id = -1, tmp; + int current_id, tmp; + if (!mpctx->demuxer || !mpctx->demuxer->video) + return M_PROPERTY_UNAVAILABLE; + current_id = mpctx->demuxer->video->id; switch (action) { case M_PROPERTY_GET: - if (!mpctx->sh_video) - return M_PROPERTY_UNAVAILABLE; if (!arg) return M_PROPERTY_ERROR; - *(int *) arg = opts->video_id; + *(int *) arg = current_id; return M_PROPERTY_OK; case M_PROPERTY_PRINT: - if (!mpctx->sh_video) - return M_PROPERTY_UNAVAILABLE; if (!arg) return M_PROPERTY_ERROR; - if (opts->video_id < 0) + if (current_id < 0) *(char **) arg = strdup(_("disabled")); else { char lang[40] = _("unknown"); *(char **) arg = malloc(64); - snprintf(*(char **) arg, 64, "(%d) %s", opts->video_id, lang); + snprintf(*(char **) arg, 64, "(%d) %s", current_id, lang); } return M_PROPERTY_OK; case M_PROPERTY_STEP_UP: case M_PROPERTY_SET: - current_id = mpctx->demuxer->video->id; if (action == M_PROPERTY_SET && arg) tmp = *((int *) arg); else @@ -1363,9 +1357,6 @@ static int mp_property_aspect(m_option_t *prop, int action, void *arg, static int mp_property_sub_pos(m_option_t *prop, int action, void *arg, MPContext *mpctx) { - if (!mpctx->sh_video) - return M_PROPERTY_UNAVAILABLE; - switch (action) { case M_PROPERTY_SET: if (!arg) @@ -2479,6 +2470,23 @@ static const struct { }; #endif +static const char *property_error_string(int error_value) +{ + switch (error_value) { + case M_PROPERTY_ERROR: + return "ERROR"; + case M_PROPERTY_UNAVAILABLE: + return "PROPERTY_UNAVAILABLE"; + case M_PROPERTY_NOT_IMPLEMENTED: + return "NOT_IMPLEMENTED"; + case M_PROPERTY_UNKNOWN: + return "PROPERTY_UNKNOWN"; + case M_PROPERTY_DISABLED: + return "DISABLED"; + } + return "UNKNOWN"; +} + void run_command(MPContext *mpctx, mp_cmd_t *cmd) { struct MPOpts *opts = &mpctx->opts; @@ -2527,6 +2535,8 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd) cmd->args[0].v.s, cmd->args[1].v.s); else if (case_fallthrough_hack) show_property_osd(mpctx, cmd->args[0].v.s); + if (r <= 0) + mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_ERROR=%s\n", property_error_string(r)); } break; @@ -2573,16 +2583,20 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd) cmd->args[0].v.s, cmd->args[1].v.f); else if (case_fallthrough_hack) show_property_osd(mpctx, cmd->args[0].v.s); + if (r <= 0) + mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_ERROR=%s\n", property_error_string(r)); } break; case MP_CMD_GET_PROPERTY:{ char *tmp; - if (mp_property_do(cmd->args[0].v.s, M_PROPERTY_TO_STRING, - &tmp, mpctx) <= 0) { + int r = mp_property_do(cmd->args[0].v.s, M_PROPERTY_TO_STRING, + &tmp, mpctx); + if (r <= 0) { mp_msg(MSGT_CPLAYER, MSGL_WARN, "Failed to get value of property '%s'.\n", cmd->args[0].v.s); + mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_ERROR=%s\n", property_error_string(r)); break; } mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_%s=%s\n", diff --git a/etc/codecs.conf b/etc/codecs.conf index 8f05bf9203..5f22c31a2d 100644 --- a/etc/codecs.conf +++ b/etc/codecs.conf @@ -2891,7 +2891,7 @@ videocodec ffinterplay fourcc INPV ; internal MPlayer FourCC driver ffmpeg dll "interplayvideo" - out BGR8 + out BGR8,BGR15 videocodec ffvqa info "FFmpeg VQA Video" @@ -3161,6 +3161,111 @@ videocodec rawy800 fourcc y800,Y800 out Y800,Y8 +;lavc raw codecs + +videocodec ffrawyuy2 + info "RAW YUY2" + status working + format 0x0 + format 0x20776172 + fourcc yuy2,YUY2 + fourcc V422,v422 + fourcc YUNV,yunv + fourcc VYUY,vyuy + fourcc yuvs,YUVS + driver ffmpeg + dll rawvideo + out YUY2 + +videocodec ffrawyuv2 + info "RAW YUV2" + status working + format 0x0 + format 0x20776172 + fourcc yuv2,YUV2 + driver ffmpeg + dll rawvideo + out YUY2 + +videocodec ffrawuyvy + info "RAW UYVY" + status working + format 0x0 + format 0x20776172 + fourcc uyvy,UYVY + fourcc HDYC,hdyc + fourcc UYNV,uynv + fourcc UYNY,uyny + fourcc uyv1,UYV1 + fourcc 2Vu1,2vu1,2VU1 + fourcc 2Vuy,2vuy,2VUY + driver ffmpeg + dll rawvideo + out UYVY + +videocodec ffraw444P + info "RAW 444P" + status working + format 0x0 + format 0x20776172 + fourcc 444p,444P + driver ffmpeg + dll rawvideo + out 444P + +videocodec ffraw422P + info "RAW 422P" + status working + format 0x0 + format 0x20776172 + fourcc 422p,422P + fourcc P422,p422 + fourcc Y42B,y42b + driver ffmpeg + dll rawvideo + out 422P + +videocodec ffrawyv12 + info "RAW YV12" + status working + format 0x0 + format 0x20776172 + fourcc yv12,YV12 + driver ffmpeg + dll rawvideo + out YV12 + +videocodec ffrawi420 + info "RAW I420" + status working + format 0x0 + format 0x20776172 + fourcc i420,I420 + fourcc IYUV,iyuv + driver ffmpeg + dll rawvideo + out I420,IYUV + +videocodec ffrawyvu9 + info "RAW YVU9" + status working + format 0x0 + format 0x20776172 + fourcc yvu9,YVU9 + driver ffmpeg + dll rawvideo + out YVU9 + +videocodec ffrawy800 + info "RAW Y8/Y800" + status working + format 0x0 + format 0x20203859 ; "Y8 " + fourcc y800,Y800 + driver ffmpeg + dll rawvideo + out Y800,Y8 + ; NULL codec - for testing. videocodec null diff --git a/libmpcodecs/ad_ffmpeg.c b/libmpcodecs/ad_ffmpeg.c index 12bd6aef6a..217ec25ff1 100644 --- a/libmpcodecs/ad_ffmpeg.c +++ b/libmpcodecs/ad_ffmpeg.c @@ -167,7 +167,17 @@ static int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int m int len2=maxlen; double pts; int x=ds_get_packet_pts(sh_audio->ds,&start, &pts); - if(x<=0) break; // error + if(x<=0) { + start = NULL; + x = 0; + ds_parse(sh_audio->ds, &start, &x, MP_NOPTS_VALUE, 0); + if (x <= 0) + break; // error + } else { + int in_size = x; + int consumed = ds_parse(sh_audio->ds, &start, &x, pts, 0); + sh_audio->ds->buffer_pos -= in_size - consumed; + } av_init_packet(&pkt); pkt.data = start; pkt.size = x; @@ -178,7 +188,8 @@ static int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int m y=avcodec_decode_audio3(sh_audio->context,(int16_t*)buf,&len2,&pkt); //printf("return:%d samples_out:%d bitstream_in:%d sample_sum:%d\n", y, len2, x, len); fflush(stdout); if(y<0){ mp_msg(MSGT_DECAUDIO,MSGL_V,"lavc_audio: error\n");break; } - if(y<x) sh_audio->ds->buffer_pos+=y-x; // put back data (HACK!) + if(!sh_audio->needs_parsing && y<x) + sh_audio->ds->buffer_pos+=y-x; // put back data (HACK!) if(len2>0){ if (((AVCodecContext *)sh_audio->context)->channels >= 5) { int samplesize = av_get_bits_per_sample_format(((AVCodecContext *) diff --git a/libmpcodecs/mp_image.h b/libmpcodecs/mp_image.h index 77ce04102a..a62f403e27 100644 --- a/libmpcodecs/mp_image.h +++ b/libmpcodecs/mp_image.h @@ -38,7 +38,7 @@ #define MP_IMGFLAG_YUV 0x200 // set if it's swapped (BGR or YVU) plane/byteorder #define MP_IMGFLAG_SWAPPED 0x400 -// using palette for RGB data +// set if you want memory for palette allocated and managed by vf_get_image etc. #define MP_IMGFLAG_RGB_PALETTE 0x800 #define MP_IMGFLAGMASK_COLORS 0xF00 @@ -223,6 +223,8 @@ static inline void free_mp_image(mp_image_t* mpi){ if(mpi->flags&MP_IMGFLAG_ALLOCATED){ /* becouse we allocate the whole image in once */ if(mpi->planes[0]) free(mpi->planes[0]); + if (mpi->flags & MP_IMGFLAG_RGB_PALETTE) + free(mpi->planes[1]); } free(mpi); } diff --git a/libmpcodecs/vd_ffmpeg.c b/libmpcodecs/vd_ffmpeg.c index 52e11623db..a89e0a4dbe 100644 --- a/libmpcodecs/vd_ffmpeg.c +++ b/libmpcodecs/vd_ffmpeg.c @@ -29,6 +29,10 @@ static const vd_info_t info = { #include "libavcodec/avcodec.h" +#if AVPALETTE_SIZE > 1024 +#error palette too large, adapt libmpcodecs/vf.c:vf_get_image +#endif + #if CONFIG_XVMC #include "libavcodec/xvmc.h" #endif @@ -533,6 +537,8 @@ static int get_buffer(AVCodecContext *avctx, AVFrame *pic){ mp_msg(MSGT_DECVIDEO, MSGL_DBG2, type== MP_IMGTYPE_IPB ? "using IPB\n" : "using IP\n"); } + if (ctx->best_csp == IMGFMT_RGB8 || ctx->best_csp == IMGFMT_BGR8) + flags |= MP_IMGFLAG_RGB_PALETTE; mpi= mpcodecs_get_image(sh, type, flags, width, height); if (!mpi) return -1; @@ -570,10 +576,6 @@ static int get_buffer(AVCodecContext *avctx, AVFrame *pic){ } #endif - // Palette support: libavcodec copies palette to *data[1] - if (mpi->bpp == 8) - mpi->planes[1] = av_malloc(AVPALETTE_SIZE); - pic->data[0]= mpi->planes[0]; pic->data[1]= mpi->planes[1]; pic->data[2]= mpi->planes[2]; diff --git a/libmpcodecs/vd_vfw.c b/libmpcodecs/vd_vfw.c index 197ead6bae..99b1cbeeb8 100644 --- a/libmpcodecs/vd_vfw.c +++ b/libmpcodecs/vd_vfw.c @@ -333,7 +333,6 @@ static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){ if (priv->palette) { mpi->planes[1] = priv->palette; - mpi->flags |= MP_IMGFLAG_RGB_PALETTE; mp_dbg(MSGT_DECVIDEO, MSGL_DBG2, "Found and copied palette\n"); } else diff --git a/libmpcodecs/vf.c b/libmpcodecs/vf.c index 5e7d1b4768..3c1c5e9538 100644 --- a/libmpcodecs/vf.c +++ b/libmpcodecs/vf.c @@ -329,8 +329,8 @@ mp_image_t* vf_get_image(vf_instance_t* vf, unsigned int outfmt, int mp_imgtype, // keep buffer allocation status & color flags only: // mpi->flags&=~(MP_IMGFLAG_PRESERVE|MP_IMGFLAG_READABLE|MP_IMGFLAG_DIRECT); mpi->flags&=MP_IMGFLAG_ALLOCATED|MP_IMGFLAG_TYPE_DISPLAYED|MP_IMGFLAGMASK_COLORS; - // accept restrictions & draw_slice flags only: - mpi->flags|=mp_imgflag&(MP_IMGFLAGMASK_RESTRICTIONS|MP_IMGFLAG_DRAW_CALLBACK); + // accept restrictions, draw_slice and palette flags only: + mpi->flags|=mp_imgflag&(MP_IMGFLAGMASK_RESTRICTIONS|MP_IMGFLAG_DRAW_CALLBACK|MP_IMGFLAG_RGB_PALETTE); if(!vf->draw_slice) mpi->flags&=~MP_IMGFLAG_DRAW_CALLBACK; if(mpi->width!=w2 || mpi->height!=h){ // printf("vf.c: MPI parameters changed! %dx%d -> %dx%d \n", mpi->width,mpi->height,w2,h); @@ -413,6 +413,8 @@ mp_image_t* vf_get_image(vf_instance_t* vf, unsigned int outfmt, int mp_imgtype, } else { //if(!mpi->stride[0]) mpi->stride[0]=mpi->width*mpi->bpp/8; + if (mpi->flags & MP_IMGFLAG_RGB_PALETTE) + mpi->planes[1] = memalign(64, 1024); } // printf("clearing img!\n"); vf_mpi_clear(mpi,0,0,mpi->width,mpi->height); diff --git a/libmpcodecs/vf_palette.c b/libmpcodecs/vf_palette.c index a867a4ce44..197a772dc9 100644 --- a/libmpcodecs/vf_palette.c +++ b/libmpcodecs/vf_palette.c @@ -76,6 +76,7 @@ static int config(struct vf_instance* vf, static int put_image(struct vf_instance* vf, mp_image_t *mpi, double pts){ mp_image_t *dmpi; + uint8_t *old_palette = mpi->planes[1]; // hope we'll get DR buffer: dmpi=vf_get_image(vf->next,vf->priv->fmt, @@ -152,6 +153,7 @@ static int put_image(struct vf_instance* vf, mp_image_t *mpi, double pts){ } } } + mpi->planes[1] = old_palette; return vf_next_put_image(vf,dmpi, pts); } diff --git a/libmpdemux/aviheader.c b/libmpdemux/aviheader.c index 230e769fe0..a57f55997e 100644 --- a/libmpdemux/aviheader.c +++ b/libmpdemux/aviheader.c @@ -219,6 +219,7 @@ while(1){ mp_tmsg(MSGT_DEMUX, MSGL_INFO, "[%s] Audio stream found, -aid %d\n", "aviheader", stream_id); memcpy(&sh_audio->audio,&h,sizeof(h)); sh_audio->stream_delay = (float)sh_audio->audio.dwStart * sh_audio->audio.dwScale/sh_audio->audio.dwRate; + sh_audio->needs_parsing = 1; } last_fccType=h.fccType; last_fccHandler=h.fccHandler; diff --git a/libmpdemux/demux_mpg.c b/libmpdemux/demux_mpg.c index 3d74a0592b..8f6220be8f 100644 --- a/libmpdemux/demux_mpg.c +++ b/libmpdemux/demux_mpg.c @@ -270,6 +270,7 @@ static void new_audio_stream(demuxer_t *demux, int aid){ sh_audio_t* sh_a; new_sh_audio(demux,aid); sh_a = (sh_audio_t*)demux->a_streams[aid]; + sh_a->needs_parsing = 1; switch(aid & 0xE0){ // 1110 0000 b (high 3 bit: type low 5: id) case 0x00: sh_a->format=0x50;break; // mpeg case 0xA0: sh_a->format=0x10001;break; // dvd pcm diff --git a/libmpdemux/demux_ts.c b/libmpdemux/demux_ts.c index c7966da9ba..af9e2109f4 100644 --- a/libmpdemux/demux_ts.c +++ b/libmpdemux/demux_ts.c @@ -305,6 +305,7 @@ static void ts_add_stream(demuxer_t * demuxer, ES_stream_t *es) if(sh) { const char *lang = pid_lang_from_pmt(priv, es->pid); + sh->needs_parsing = 1; sh->format = IS_AUDIO(es->type) ? es->type : es->subtype; sh->ds = demuxer->audio; diff --git a/libmpdemux/demuxer.c b/libmpdemux/demuxer.c index 564655609f..78c18e7640 100644 --- a/libmpdemux/demuxer.c +++ b/libmpdemux/demuxer.c @@ -52,6 +52,13 @@ #endif #endif +// This is quite experimental, in particular it will mess up the pts values +// in the queue - on the other hand it might fix some issues like generating +// broken files with mencoder and stream copy. +// Better leave it disabled for now, if we find no use for it this code should +// just be removed again. +#define PARSE_ON_ADD 0 + void resync_video_stream(sh_video_t *sh_video); void resync_audio_stream(sh_audio_t *sh_audio); @@ -276,6 +283,10 @@ static void free_sh_sub(sh_sub_t *sh) ass_free_track(sh->ass_track); #endif free(sh->lang); +#ifdef CONFIG_LIBAVCODEC + av_parser_close(sh->parser); + av_freep(&sh->avctx); +#endif free(sh); } @@ -314,6 +325,10 @@ void free_sh_audio(demuxer_t *demuxer, int id) free(sh->wf); free(sh->codecdata); free(sh->lang); +#ifdef CONFIG_LIBAVCODEC + av_parser_close(sh->parser); + av_freep(&sh->avctx); +#endif free(sh); } @@ -343,6 +358,10 @@ void free_sh_video(sh_video_t *sh) { mp_msg(MSGT_DEMUXER, MSGL_DBG2, "DEMUXER: freeing sh_video at %p\n", sh); free(sh->bih); +#ifdef CONFIG_LIBAVCODEC + av_parser_close(sh->parser); + av_freep(&sh->avctx); +#endif free(sh); } @@ -396,7 +415,7 @@ void free_demuxer(demuxer_t *demuxer) } -void ds_add_packet(demux_stream_t *ds, demux_packet_t *dp) +static void ds_add_packet_internal(demux_stream_t *ds, demux_packet_t *dp) { // append packet to DS stream: ++ds->packs; @@ -416,6 +435,109 @@ void ds_add_packet(demux_stream_t *ds, demux_packet_t *dp) ds->demuxer->video->packs); } +#ifdef CONFIG_LIBAVCODEC +static void allocate_parser(AVCodecContext **avctx, AVCodecParserContext **parser, unsigned format) +{ + enum CodecID codec_id = CODEC_ID_NONE; + extern int avcodec_initialized; + if (!avcodec_initialized) { + avcodec_init(); + avcodec_register_all(); + avcodec_initialized = 1; + } + switch (format) { + case 0x2000: + case 0x332D6361: + case 0x332D4341: + case MKTAG('d', 'n', 'e', 't'): + case MKTAG('s', 'a', 'c', '3'): + codec_id = CODEC_ID_AC3; + break; + case MKTAG('E', 'A', 'C', '3'): + codec_id = CODEC_ID_EAC3; + break; + case 0x2001: + case 0x86: + codec_id = CODEC_ID_DTS; + break; + case 0x55: + case 0x5500736d: + case MKTAG('.', 'm', 'p', '3'): + case MKTAG('M', 'P', 'E', ' '): + case MKTAG('L', 'A', 'M', 'E'): + codec_id = CODEC_ID_MP3; + break; + case 0x50: + case MKTAG('.', 'm', 'p', '2'): + case MKTAG('.', 'm', 'p', '1'): + codec_id = CODEC_ID_MP2; + break; + } + if (codec_id != CODEC_ID_NONE) { + *avctx = avcodec_alloc_context(); + if (!*avctx) + return; + *parser = av_parser_init(codec_id); + if (!*parser) + av_freep(avctx); + } +} + +static void get_parser(sh_common_t *sh, AVCodecContext **avctx, AVCodecParserContext **parser) +{ + *avctx = NULL; + *parser = NULL; + + if (!sh || !sh->needs_parsing) + return; + + *avctx = sh->avctx; + *parser = sh->parser; + if (*parser) + return; + + allocate_parser(avctx, parser, sh->format); + sh->avctx = *avctx; + sh->parser = *parser; +} + +int ds_parse(demux_stream_t *ds, uint8_t **buffer, int *len, double pts, off_t pos) +{ + AVCodecContext *avctx; + AVCodecParserContext *parser; + get_parser(ds->sh, &avctx, &parser); + if (!parser) + return *len; + return av_parser_parse2(parser, avctx, buffer, len, *buffer, *len, pts, pts, pos); +} +#endif + +void ds_add_packet(demux_stream_t *ds, demux_packet_t *dp) +{ +#if PARSE_ON_ADD && defined(CONFIG_LIBAVCODEC) + int len = dp->len; + int pos = 0; + while (len > 0) { + uint8_t *parsed_start = dp->buffer + pos; + int parsed_len = len; + int consumed = ds_parse(ds->sh, &parsed_start, &parsed_len, dp->pts, dp->pos); + pos += consumed; + len -= consumed; + if (parsed_start == dp->buffer && parsed_len == dp->len) { + ds_add_packet_internal(ds, dp); + } else if (parsed_len) { + demux_packet_t *dp2 = new_demux_packet(parsed_len); + dp2->pos = dp->pos; + dp2->pts = dp->pts; // should be parser->pts but that works badly + memcpy(dp2->buffer, parsed_start, parsed_len); + ds_add_packet_internal(ds, dp2); + } + } +#else + ds_add_packet_internal(ds, dp); +#endif +} + void ds_read_packet(demux_stream_t *ds, stream_t *stream, int len, double pts, off_t pos, int flags) { @@ -526,6 +648,18 @@ int ds_fill_buffer(demux_stream_t *ds) break; } if (!demux_fill_buffer(demux, ds)) { +#if PARSE_ON_ADD && defined(CONFIG_LIBAVCODEC) + uint8_t *parsed_start = NULL; + int parsed_len = 0; + ds_parse(ds->sh, &parsed_start, &parsed_len, MP_NOPTS_VALUE, 0); + if (parsed_len) { + demux_packet_t *dp2 = new_demux_packet(parsed_len); + dp2->pts = MP_NOPTS_VALUE; + memcpy(dp2->buffer, parsed_start, parsed_len); + ds_add_packet_internal(ds, dp2); + continue; + } +#endif mp_dbg(MSGT_DEMUXER, MSGL_DBG2, "ds_fill_buffer()->demux_fill_buffer() failed\n"); break; // EOF diff --git a/libmpdemux/demuxer.h b/libmpdemux/demuxer.h index 44cd642ed3..5da35efa03 100644 --- a/libmpdemux/demuxer.h +++ b/libmpdemux/demuxer.h @@ -400,6 +400,7 @@ int ds_get_packet(demux_stream_t *ds,unsigned char **start); int ds_get_packet_pts(demux_stream_t *ds, unsigned char **start, double *pts); int ds_get_packet_sub(demux_stream_t *ds,unsigned char **start); double ds_get_next_pts(demux_stream_t *ds); +int ds_parse(demux_stream_t *sh, uint8_t **buffer, int *len, double pts, off_t pos); // This is defined here because demux_stream_t ins't defined in stream.h stream_t* new_ds_stream(demux_stream_t *ds); diff --git a/libmpdemux/extension.c b/libmpdemux/extension.c index 59d242e4dd..1d2ffb832e 100644 --- a/libmpdemux/extension.c +++ b/libmpdemux/extension.c @@ -27,6 +27,12 @@ /* * An autodetection based on the extension is not a good idea, but we don't care ;-) + * + * You should not add anything here where autodetection can be easily fixed except in + * order to speed up auto-detection, in particular for formats that are often streamed. + * In particular you should not normally add any DEMUXER_TYPE_LAVF, adding the + * format to preferred_list in libmpdemux/demuxer_lavf.c will usually achieve + * the same effect in a much more reliable way. */ static struct { const char *extension; @@ -38,9 +44,6 @@ static struct { { "vob", DEMUXER_TYPE_MPEG_PS }, { "m2v", DEMUXER_TYPE_MPEG_PS }, { "avi", DEMUXER_TYPE_AVI }, - { "mp4", DEMUXER_TYPE_LAVF }, - { "mov", DEMUXER_TYPE_LAVF }, - { "qt", DEMUXER_TYPE_LAVF }, { "asx", DEMUXER_TYPE_ASF }, { "asf", DEMUXER_TYPE_ASF }, { "wmv", DEMUXER_TYPE_ASF }, @@ -65,7 +68,6 @@ static struct { { "it", DEMUXER_TYPE_XMMS }, { "mid", DEMUXER_TYPE_XMMS }, { "midi", DEMUXER_TYPE_XMMS }, - { "vqf", DEMUXER_TYPE_LAVF }, { "nsv", DEMUXER_TYPE_NSV }, { "nsa", DEMUXER_TYPE_NSV }, { "mpc", DEMUXER_TYPE_MPC }, @@ -81,6 +83,7 @@ static struct { { "eac3",DEMUXER_TYPE_LAVF }, { "mac", DEMUXER_TYPE_LAVF }, { "str", DEMUXER_TYPE_LAVF }, + { "cdg", DEMUXER_TYPE_LAVF }, // At least the following are hacks against broken autodetection // that should not be there diff --git a/libmpdemux/stheader.h b/libmpdemux/stheader.h index 9b43f21dfd..b11b886ce1 100644 --- a/libmpdemux/stheader.h +++ b/libmpdemux/stheader.h @@ -26,14 +26,32 @@ struct demuxer; // Stream headers: +#define SH_COMMON \ + struct MPOpts *opts; \ + struct demux_stream *ds; \ + struct codecs *codec; \ + unsigned int format; \ + int initialized; \ + float stream_delay; /* number of seconds stream should be delayed (according to dwStart or similar) */ \ + /* things needed for parsing */ \ + int needs_parsing; \ + struct AVCodecContext *avctx; \ + struct AVCodecParserContext *parser; \ + /* audio: last known pts value in output from decoder \ + * video: predicted/interpolated PTS of the current frame */ \ + double pts; \ + /* codec-specific: */ \ + void* context; /* codec-specific stuff (usually HANDLE or struct pointer) */ \ + char* lang; /* track language */ \ + int default_track; \ + +typedef struct sh_common { + SH_COMMON +} sh_common_t; + typedef struct sh_audio { - struct MPOpts *opts; + SH_COMMON int aid; - struct demux_stream *ds; - struct codecs *codec; - unsigned int format; - int initialized; - float stream_delay; // number of seconds stream should be delayed (according to dwStart or similar) // output format: int sample_format; int samplerate; @@ -65,29 +83,19 @@ typedef struct sh_audio { AVIStreamHeader audio; WAVEFORMATEX* wf; // codec-specific: - void* context; // codec-specific stuff (usually HANDLE or struct pointer) unsigned char* codecdata; // extra header data passed from demuxer to codec int codecdata_len; - double pts; // last known pts value in output from decoder int pts_bytes; // bytes output by decoder after last known pts - char* lang; // track language - int default_track; } sh_audio_t; typedef struct sh_video { - struct MPOpts *opts; + SH_COMMON int vid; |