Mercurial > mplayer.hg
view m_property.c @ 24589:9118be6575da
demux_audio.c: Fix timestamp handling
The code calculated the pts values of audio packets by adding the length
of the current packet to the pts of the previous one. The length of the
previous packet should be added instead. This broke WAV timestamps near
the end of the stream where a short packet occurs.
Change the code to store the pts of the next packet instead of the last
one. This fixes the WAV timestamps and allows some simplifications.
MP3 timestamps are not affected as packets are always treated as
constant decoded length, and FLAC timestamps still have worse problems
(FLAC is treated as as if it was constant bitrate even though it isn't).
Also store the timestamps as double instead of float.
author | uau |
---|---|
date | Mon, 24 Sep 2007 21:49:56 +0000 |
parents | ae4237717601 |
children | 3086b6d39052 |
line wrap: on
line source
/// \file /// \ingroup Properties #include "config.h" #include <stdlib.h> #include <stdio.h> #include <string.h> #include <inttypes.h> #include <unistd.h> #include "m_option.h" #include "m_property.h" #include "mp_msg.h" #include "help_mp.h" #define ROUND(x) ((int)((x)<0 ? (x)-0.5 : (x)+0.5)) static int do_action(m_option_t* prop_list, const char* name, int action, void* arg, void *ctx) { const char* sep; m_option_t* prop; m_property_action_t ka; int r; if((sep = strchr(name,'/')) && sep[1]) { int len = sep-name; char base[len+1]; memcpy(base,name,len); base[len] = 0; prop = m_option_list_find(prop_list, base); ka.key = sep+1; ka.action = action; ka.arg = arg; action = M_PROPERTY_KEY_ACTION; arg = &ka; } else prop = m_option_list_find(prop_list, name); if(!prop) return M_PROPERTY_UNKNOWN; r = ((m_property_ctrl_f)prop->p)(prop,action,arg,ctx); if(action == M_PROPERTY_GET_TYPE && r < 0) { if(!arg) return M_PROPERTY_ERROR; *(m_option_t**)arg = prop; return M_PROPERTY_OK; } return r; } int m_property_do(m_option_t* prop_list, const char* name, int action, void* arg, void *ctx) { m_option_t* opt; void* val; char* str; int r; switch(action) { case M_PROPERTY_PRINT: if((r = do_action(prop_list,name,M_PROPERTY_PRINT,arg,ctx)) >= 0) return r; // fallback on the default print for this type case M_PROPERTY_TO_STRING: if((r = do_action(prop_list,name,M_PROPERTY_TO_STRING,arg,ctx)) != M_PROPERTY_NOT_IMPLEMENTED) return r; // fallback on the options API. Get the type, value and print. if((r = do_action(prop_list,name,M_PROPERTY_GET_TYPE,&opt,ctx)) <= 0) return r; val = calloc(1,opt->type->size); if((r = do_action(prop_list,name,M_PROPERTY_GET,val,ctx)) <= 0) { free(val); return r; } if(!arg) return M_PROPERTY_ERROR; str = m_option_print(opt,val); free(val); *(char**)arg = str == (char*)-1 ? NULL : str; return str != (char*)-1; case M_PROPERTY_PARSE: // try the property own parsing func if((r = do_action(prop_list,name,M_PROPERTY_PARSE,arg,ctx)) != M_PROPERTY_NOT_IMPLEMENTED) return r; // fallback on the options API, get the type and parse. if((r = do_action(prop_list,name,M_PROPERTY_GET_TYPE,&opt,ctx)) <= 0) return r; if(!arg) return M_PROPERTY_ERROR; val = calloc(1,opt->type->size); if((r = m_option_parse(opt,opt->name,arg,val,M_CONFIG_FILE)) <= 0) { free(val); return r; } r = do_action(prop_list,name,M_PROPERTY_SET,val,ctx); m_option_free(opt,val); free(val); return r; } return do_action(prop_list,name,action,arg,ctx); } char* m_properties_expand_string(m_option_t* prop_list,char* str, void *ctx) { int l,fr=0,pos=0,size=strlen(str)+512; char *p = NULL,*e,*ret = malloc(size), num_val; int skip = 0, lvl = 0, skip_lvl = 0; while(str[0]) { if(str[0] == '\\') { int sl = 1; switch(str[1]) { case 'e': p = "\x1b", l = 1; break; case 'n': p = "\n", l = 1; break; case 'r': p = "\r", l = 1; break; case 't': p = "\t", l = 1; break; case 'x': if(str[2]) { char num[3] = { str[2], str[3], 0 }; char* end = num; num_val = strtol(num,&end,16); sl = end-num; l = 1; p = &num_val; } else l = 0; break; default: p = str+1, l = 1; } str+=1+sl; } else if(lvl > 0 && str[0] == ')') { if(skip && lvl <= skip_lvl) skip = 0; lvl--, str++, l = 0; } else if(str[0] == '$' && str[1] == '{' && (e = strchr(str+2,'}'))) { int pl = e-str-2; char pname[pl+1]; memcpy(pname,str+2,pl); pname[pl] = 0; if(m_property_do(prop_list, pname, M_PROPERTY_PRINT, &p, ctx) >= 0 && p) l = strlen(p), fr = 1; else l = 0; str = e+1; } else if(str[0] == '?' && str[1] == '(' && (e = strchr(str+2,':'))) { int pl = e-str-2; char pname[pl+1]; lvl++; if(!skip) { memcpy(pname,str+2,pl); pname[pl] = 0; if(m_property_do(prop_list,pname,M_PROPERTY_GET,NULL,ctx) < 0) skip = 1, skip_lvl = lvl; } str = e+1, l = 0; } else p = str, l = 1, str++; if(skip || l <= 0) continue; if(pos+l+1 > size) { size = pos+l+512; ret = realloc(ret,size); } memcpy(ret+pos,p,l); pos += l; if(fr) free(p), fr = 0; } ret[pos] = 0; return ret; } void m_properties_print_help_list(m_option_t* list) { char min[50],max[50]; int i,count = 0; mp_msg(MSGT_CFGPARSER, MSGL_INFO, MSGTR_PropertyListHeader); for(i = 0 ; list[i].name ; i++) { m_option_t* opt = &list[i]; if(opt->flags & M_OPT_MIN) sprintf(min,"%-8.0f",opt->min); else strcpy(min,"No"); if(opt->flags & M_OPT_MAX) sprintf(max,"%-8.0f",opt->max); else strcpy(max,"No"); mp_msg(MSGT_CFGPARSER, MSGL_INFO, " %-20.20s %-15.15s %-10.10s %-10.10s\n", opt->name, opt->type->name, min, max); count++; } mp_msg(MSGT_CFGPARSER, MSGL_INFO, MSGTR_TotalProperties, count); } // Some generic property implementations int m_property_int_ro(m_option_t* prop,int action, void* arg,int var) { switch(action) { case M_PROPERTY_GET: if(!arg) return 0; *(int*)arg = var; return 1; } return M_PROPERTY_NOT_IMPLEMENTED; } int m_property_int_range(m_option_t* prop,int action, void* arg,int* var) { switch(action) { case M_PROPERTY_SET: if(!arg) return 0; M_PROPERTY_CLAMP(prop,*(int*)arg); *var = *(int*)arg; return 1; case M_PROPERTY_STEP_UP: case M_PROPERTY_STEP_DOWN: *var += (arg ? *(int*)arg : 1) * (action == M_PROPERTY_STEP_DOWN ? -1 : 1); M_PROPERTY_CLAMP(prop,*var); return 1; } return m_property_int_ro(prop,action,arg,*var); } int m_property_choice(m_option_t* prop,int action, void* arg,int* var) { switch(action) { case M_PROPERTY_STEP_UP: case M_PROPERTY_STEP_DOWN: *var += action == M_PROPERTY_STEP_UP ? 1 : prop->max; *var %= (int)prop->max+1; return 1; } return m_property_int_range(prop,action,arg,var); } int m_property_flag(m_option_t* prop,int action, void* arg,int* var) { switch(action) { case M_PROPERTY_STEP_UP: case M_PROPERTY_STEP_DOWN: *var = *var == prop->min ? prop->max : prop->min; return 1; case M_PROPERTY_PRINT: if(!arg) return 0; *(char**)arg = strdup((*var > prop->min) ? MSGTR_Enabled : MSGTR_Disabled); return 1; } return m_property_int_range(prop,action,arg,var); } int m_property_float_ro(m_option_t* prop,int action, void* arg,float var) { switch(action) { case M_PROPERTY_GET: if(!arg) return 0; *(float*)arg = var; return 1; case M_PROPERTY_PRINT: if(!arg) return 0; *(char**)arg = malloc(20); sprintf(*(char**)arg,"%.2f",var); return 1; } return M_PROPERTY_NOT_IMPLEMENTED; } int m_property_float_range(m_option_t* prop,int action, void* arg,float* var) { switch(action) { case M_PROPERTY_SET: if(!arg) return 0; M_PROPERTY_CLAMP(prop,*(float*)arg); *var = *(float*)arg; return 1; case M_PROPERTY_STEP_UP: case M_PROPERTY_STEP_DOWN: *var += (arg ? *(float*)arg : 0.1) * (action == M_PROPERTY_STEP_DOWN ? -1 : 1); M_PROPERTY_CLAMP(prop,*var); return 1; } return m_property_float_ro(prop,action,arg,*var); } int m_property_delay(m_option_t* prop,int action, void* arg,float* var) { switch(action) { case M_PROPERTY_PRINT: if(!arg) return 0; *(char**)arg = malloc(20); sprintf(*(char**)arg,"%d ms",ROUND((*var)*1000)); return 1; default: return m_property_float_range(prop,action,arg,var); } } int m_property_double_ro(m_option_t* prop,int action, void* arg,double var) { switch(action) { case M_PROPERTY_GET: if(!arg) return 0; *(double*)arg = var; return 1; case M_PROPERTY_PRINT: if(!arg) return 0; *(char**)arg = malloc(20); sprintf(*(char**)arg,"%.2f",var); return 1; } return M_PROPERTY_NOT_IMPLEMENTED; } int m_property_time_ro(m_option_t* prop,int action, void* arg,double var) { switch(action) { case M_PROPERTY_PRINT: if (!arg) return M_PROPERTY_ERROR; else { int h, m, s = var; h = s / 3600; s -= h * 3600; m = s / 60; s -= m * 60; *(char **) arg = malloc(20); if (h > 0) sprintf(*(char **) arg, "%d:%02d:%02d", h, m, s); else if (m > 0) sprintf(*(char **) arg, "%d:%02d", m, s); else sprintf(*(char **) arg, "%d", s); return M_PROPERTY_OK; } } return m_property_double_ro(prop,action,arg,var); } int m_property_string_ro(m_option_t* prop,int action,void* arg,char* str) { switch(action) { case M_PROPERTY_GET: if(!arg) return 0; *(char**)arg = str; return 1; case M_PROPERTY_PRINT: if(!arg) return 0; *(char**)arg = str ? strdup(str) : NULL; return 1; } return M_PROPERTY_NOT_IMPLEMENTED; } int m_property_bitrate(m_option_t* prop,int action,void* arg,int rate) { switch(action) { case M_PROPERTY_PRINT: if (!arg) return M_PROPERTY_ERROR; *(char**)arg = malloc (16); sprintf(*(char**)arg, "%d kbps", rate*8/1000); return M_PROPERTY_OK; } return m_property_int_ro(prop, action, arg, rate); }