mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
Merge commit '36ac9a16a19a365ce58cc871484c20cffe9b6401'
* commit '36ac9a16a19a365ce58cc871484c20cffe9b6401': fate: dependencies for seek tests fate: handle lavf test dependencies entirely in make Conflicts: configure tests/Makefile Merged-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
commit
9317b73f11
48
configure
vendored
48
configure
vendored
@ -1965,54 +1965,12 @@ doc_deps_any="manpages htmlpages podpages txtpages"
|
||||
# tests
|
||||
colormatrix1_test_deps="colormatrix_filter"
|
||||
colormatrix2_test_deps="colormatrix_filter"
|
||||
mpg_test_deps="mpeg1system_muxer mpegps_demuxer"
|
||||
png_test_deps="zlib"
|
||||
pp_test_deps="mp_filter"
|
||||
pp2_test_deps="mp_filter"
|
||||
pp3_test_deps="mp_filter"
|
||||
pp4_test_deps="mp_filter"
|
||||
pp5_test_deps="mp_filter"
|
||||
pp6_test_deps="mp_filter"
|
||||
seek_flashsv_flv_test_deps="zlib"
|
||||
seek_lavf_mxf_d10_test_deps="mxf_d10_test"
|
||||
|
||||
test_deps(){
|
||||
suf1=$1
|
||||
suf2=$2
|
||||
shift 2
|
||||
for v; do
|
||||
dep=${v%=*}
|
||||
tests=${v#*=}
|
||||
for name in ${tests}; do
|
||||
append ${name}_test_deps ${dep}$suf1 ${dep}$suf2
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
test_deps _muxer _demuxer \
|
||||
aiff \
|
||||
pcm_alaw=alaw \
|
||||
asf \
|
||||
au \
|
||||
avi \
|
||||
dv=dv_fmt \
|
||||
ffm \
|
||||
flv=flv_fmt \
|
||||
gxf \
|
||||
matroska=mkv \
|
||||
mmf \
|
||||
mov="mov ismv" \
|
||||
pcm_mulaw=mulaw \
|
||||
mxf="mxf mxf_d10" \
|
||||
nut \
|
||||
ogg="ogg ogg_vp3" \
|
||||
rawvideo=pixfmt \
|
||||
rm \
|
||||
swf \
|
||||
mpegts=ts \
|
||||
voc \
|
||||
wav \
|
||||
yuv4mpegpipe=yuv4mpeg \
|
||||
|
||||
# default parameters
|
||||
|
||||
@ -2184,11 +2142,9 @@ find_tests(){
|
||||
}
|
||||
|
||||
LAVF_FATE_TESTS=$(find_tests lavf-fate)
|
||||
LAVF_TESTS=$(find_tests lavf)
|
||||
LAVFI_TESTS=$(find_tests lavfi)
|
||||
SEEK_TESTS=$(find_tests seek seek_)
|
||||
|
||||
ALL_TESTS="$LAVF_FATE_TESTS $LAVF_TESTS $LAVFI_TESTS $SEEK_TESTS"
|
||||
ALL_TESTS="$LAVF_FATE_TESTS $LAVFI_TESTS"
|
||||
|
||||
for n in $COMPONENT_LIST; do
|
||||
v=$(toupper ${n%s})_LIST
|
||||
@ -4336,9 +4292,7 @@ print_config CONFIG_ "$config_files" $CONFIG_LIST \
|
||||
|
||||
cat >>config.mak <<EOF
|
||||
LAVF_FATE_TESTS=$(print_enabled -n _test $LAVF_FATE_TESTS)
|
||||
LAVF_TESTS=$(print_enabled -n _test $LAVF_TESTS)
|
||||
LAVFI_TESTS=$(print_enabled -n _test $LAVFI_TESTS)
|
||||
SEEK_TESTS=$(print_enabled -n _test $SEEK_TESTS)
|
||||
EOF
|
||||
|
||||
echo "#endif /* FFMPEG_CONFIG_H */" >> $TMPH
|
||||
|
@ -56,6 +56,8 @@ ENCDEC2 = $(call ALLYES, $(firstword $(1))_ENCODER $(lastword $(1))_DECODER \
|
||||
|
||||
include $(SRC_PATH)/tests/fate/acodec.mak
|
||||
include $(SRC_PATH)/tests/fate/vcodec.mak
|
||||
include $(SRC_PATH)/tests/fate/avformat.mak
|
||||
include $(SRC_PATH)/tests/fate/seek.mak
|
||||
|
||||
include $(SRC_PATH)/tests/fate/aac.mak
|
||||
include $(SRC_PATH)/tests/fate/ac3.mak
|
||||
@ -109,13 +111,9 @@ include $(SRC_PATH)/tests/fate/wavpack.mak
|
||||
include $(SRC_PATH)/tests/fate/wma.mak
|
||||
|
||||
FATE_LAVF_FATE = $(LAVF_FATE_TESTS:%=fate-lavf-fate-%)
|
||||
FATE_LAVF = $(LAVF_TESTS:%=fate-lavf-%)
|
||||
FATE_LAVFI = $(LAVFI_TESTS:%=fate-lavfi-%)
|
||||
FATE_SEEK = $(SEEK_TESTS:seek_%=fate-seek-%)
|
||||
|
||||
FATE_AVCONV += $(FATE_LAVF) \
|
||||
$(FATE_LAVFI) \
|
||||
$(FATE_SEEK) \
|
||||
FATE_AVCONV += $(FATE_LAVFI) \
|
||||
|
||||
FATE_FFMPEG += $(FATE_FFMPEG-yes) $(FATE_AVCONV) $(FATE_AVCONV-yes)
|
||||
FATE-$(CONFIG_FFMPEG) += $(FATE_FFMPEG)
|
||||
@ -134,19 +132,13 @@ $(FATE_FFMPEG) $(FATE_LAVF_FATE) $(FATE_SAMPLES_AVCONV) $(FATE_SAMPLES_FFMPEG):
|
||||
|
||||
$(FATE_FFPROBE): ffprobe$(EXESUF)
|
||||
|
||||
$(FATE_LAVF): $(AREF) $(VREF)
|
||||
$(FATE_LAVFI): $(VREF) libavfilter/filtfmts-test$(EXESUF)
|
||||
$(FATE_SEEK): fate-acodec fate-vsynth2 fate-lavf libavformat/seek-test$(EXESUF)
|
||||
|
||||
$(FATE_LAVF_FATE): CMD = lavffatetest
|
||||
$(FATE_LAVF): CMD = lavftest
|
||||
$(FATE_LAVFI): CMD = lavfitest
|
||||
$(FATE_SEEK): CMD = seektest
|
||||
|
||||
fate-lavf-fate: $(FATE_LAVF_FATE)
|
||||
fate-lavf: $(FATE_LAVF)
|
||||
fate-lavfi: $(FATE_LAVFI)
|
||||
fate-seek: $(FATE_SEEK)
|
||||
|
||||
ifdef SAMPLES
|
||||
FATE += $(FATE_LAVF_FATE)
|
||||
|
57
tests/fate/avformat.mak
Normal file
57
tests/fate/avformat.mak
Normal file
@ -0,0 +1,57 @@
|
||||
FATE_LAVF-$(call ENCDEC, PCM_S16BE, AIFF) += aiff
|
||||
FATE_LAVF-$(call ENCDEC, PCM_ALAW, PCM_ALAW) += alaw
|
||||
FATE_LAVF-$(call ENCDEC2, MSMPEG4V3, MP2, ASF) += asf
|
||||
FATE_LAVF-$(call ENCDEC, PCM_S16BE, AU) += au
|
||||
FATE_LAVF-$(call ENCDEC2, MPEG4, MP2, AVI) += avi
|
||||
FATE_LAVF-$(call ENCDEC, BMP, IMAGE2) += bmp
|
||||
FATE_LAVF-$(call ENCDEC, PCM_S16BE, CAF) += caf
|
||||
FATE_LAVF-$(call ENCDEC, DPX, IMAGE2) += dpx
|
||||
FATE_LAVF-$(call ENCDEC2, DVVIDEO, PCM_S16LE, AVI) += dv_fmt
|
||||
FATE_LAVF-$(call ENCDEC2, MPEG1VIDEO, MP2, FFM) += ffm
|
||||
FATE_LAVF-$(call ENCDEC, FLV, FLV) += flv_fmt
|
||||
FATE_LAVF-$(call ENCDEC, GIF, IMAGE2) += gif
|
||||
FATE_LAVF-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, GXF) += gxf
|
||||
FATE_LAVF-$(call ENCDEC, MJPEG, IMAGE2) += jpg
|
||||
FATE_LAVF-$(call ENCDEC2, MPEG4, MP2, MATROSKA) += mkv
|
||||
FATE_LAVF-$(call ENCDEC, ADPCM_YAMAHA, MMF) += mmf
|
||||
FATE_LAVF-$(call ENCDEC2, MPEG4, PCM_ALAW, MOV) += mov ismv
|
||||
FATE_LAVF-$(call ENCDEC2, MPEG1VIDEO, MP2, MPEG1SYSTEM MPEGPS) += mpg
|
||||
FATE_LAVF-$(call ENCDEC, PCM_MULAW, PCM_MULAW) += mulaw
|
||||
FATE_LAVF-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, MXF) += mxf
|
||||
FATE_LAVF-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, MXF_D10 MXF) += mxf_d10
|
||||
FATE_LAVF-$(call ENCDEC2, MPEG4, MP2, NUT) += nut
|
||||
FATE_LAVF-$(call ENCDEC, FLAC, OGG) += ogg
|
||||
FATE_LAVF-$(call ENCDEC, VP3, OGG) += ogg_vp3
|
||||
FATE_LAVF-$(call ENCDEC, PAM, IMAGE2) += pam
|
||||
FATE_LAVF-$(call ENCDEC, PBM, IMAGE2PIPE) += pbmpipe
|
||||
FATE_LAVF-$(call ENCDEC, PCX, IMAGE2) += pcx
|
||||
FATE_LAVF-$(call ENCDEC, PGM, IMAGE2) += pgm
|
||||
FATE_LAVF-$(call ENCDEC, PGM, IMAGE2PIPE) += pgmpipe
|
||||
FATE_LAVF-$(call ENCDEC, PNG, IMAGE2) += png
|
||||
FATE_LAVF-$(call ENCDEC, PPM, IMAGE2) += ppm
|
||||
FATE_LAVF-$(call ENCDEC, PPM, IMAGE2PIPE) += ppmpipe
|
||||
FATE_LAVF-$(call ALLYES, RV10_ENCODER AC3_FIXED_ENCODER RM_MUXER) += rm
|
||||
FATE_LAVF-$(call ENCDEC, PCM_U8, RSO) += rso
|
||||
FATE_LAVF-$(call ENCDEC, SGI, IMAGE2) += sgi
|
||||
FATE_LAVF-$(call ENCDEC, PCM_S16LE, SOX) += sox
|
||||
FATE_LAVF-$(call ENCDEC, SUNRAST, IMAGE2) += sunrast
|
||||
FATE_LAVF-$(call ENCDEC, FLV, SWF) += swf
|
||||
FATE_LAVF-$(call ENCDEC, TARGA, IMAGE2) += tga
|
||||
FATE_LAVF-$(call ENCDEC, TIFF, IMAGE2) += tiff
|
||||
FATE_LAVF-$(call ENCDEC2, MPEG2VIDEO, MP2, MPEGTS) += ts
|
||||
FATE_LAVF-$(call ENCDEC, PCM_U8, VOC) += voc
|
||||
FATE_LAVF-$(call ENCDEC, PCM_S16LE, VOC) += voc_s16
|
||||
FATE_LAVF-$(call ENCDEC, PCM_S16LE, WAV) += wav
|
||||
FATE_LAVF-$(call ENCDEC, MP2, WTV) += wtv
|
||||
FATE_LAVF-$(call ENCDEC, XBM, IMAGE2) += xbm
|
||||
FATE_LAVF-$(call ENCDEC, XWD, IMAGE2) += xwd
|
||||
FATE_LAVF-$(CONFIG_YUV4MPEGPIPE_MUXER) += yuv4mpeg
|
||||
|
||||
FATE_LAVF += $(FATE_LAVF-yes:%=fate-lavf-%)
|
||||
FATE_LAVF += fate-lavf-pixfmt
|
||||
|
||||
$(FATE_LAVF): $(AREF) $(VREF)
|
||||
$(FATE_LAVF): CMD = lavftest
|
||||
|
||||
FATE_AVCONV += $(FATE_LAVF)
|
||||
fate-lavf: $(FATE_LAVF)
|
120
tests/fate/seek.mak
Normal file
120
tests/fate/seek.mak
Normal file
@ -0,0 +1,120 @@
|
||||
# files from fate-acodec
|
||||
|
||||
FATE_SEEK-$(call ENCDEC, PCM_ALAW, WAV) += pcm_alaw_wav
|
||||
FATE_SEEK-$(call ENCDEC, PCM_MULAW, WAV) += pcm_mulaw_wav
|
||||
FATE_SEEK-$(call ENCDEC, PCM_S8, MOV) += pcm_s8_mov
|
||||
FATE_SEEK-$(call ENCDEC, PCM_U8, WAV) += pcm_u8_wav
|
||||
FATE_SEEK-$(call ENCDEC, PCM_S16BE, MOV) += pcm_s16be_mov
|
||||
FATE_SEEK-$(call ENCDEC, PCM_S16LE, WAV) += pcm_s16le_wav
|
||||
FATE_SEEK-$(call ENCDEC, PCM_S24BE, MOV) += pcm_s24be_mov
|
||||
FATE_SEEK-$(call ENCDEC, PCM_S24LE, WAV) += pcm_s24le_wav
|
||||
FATE_SEEK-$(call ENCDEC, PCM_S32BE, MOV) += pcm_s32be_mov
|
||||
FATE_SEEK-$(call ENCDEC, PCM_S32LE, WAV) += pcm_s32le_wav
|
||||
FATE_SEEK-$(call ENCDEC, PCM_F32BE, AU) += pcm_f32be_au
|
||||
FATE_SEEK-$(call ENCDEC, PCM_F32LE, WAV) += pcm_f32le_wav
|
||||
FATE_SEEK-$(call ENCDEC, PCM_F64BE, AU) += pcm_f64be_au
|
||||
FATE_SEEK-$(call ENCDEC, PCM_F64LE, WAV) += pcm_f64le_wav
|
||||
FATE_SEEK-$(call ENCDEC, ADPCM_IMA_QT, AIFF) += adpcm_ima_qt_aiff
|
||||
FATE_SEEK-$(call ENCDEC, ADPCM_IMA_WAV, WAV) += adpcm_ima_wav_wav
|
||||
FATE_SEEK-$(call ENCDEC, ADPCM_MS, WAV) += adpcm_ms_wav
|
||||
FATE_SEEK-$(call ENCDEC, ADPCM_SWF, FLV) += adpcm_swf_flv
|
||||
FATE_SEEK-$(call ENCDEC, ADPCM_YAMAHA, WAV) += adpcm_yamaha_wav
|
||||
FATE_SEEK-$(call ENCDEC, ALAC, MOV) += alac_mov
|
||||
FATE_SEEK-$(call ENCDEC, FLAC, FLAC) += flac_flac
|
||||
FATE_SEEK-$(call ENCDEC, MP2, MP2 MP3) += mp2_mp2
|
||||
|
||||
# files from fate-vsynth2
|
||||
|
||||
FATE_SEEK-$(call ENCDEC, ASV1, AVI) += asv1_avi
|
||||
FATE_SEEK-$(call ENCDEC, ASV2, AVI) += asv2_avi
|
||||
FATE_SEEK-$(call ENCDEC, DNXHD, DNXHD) += dnxhd_720p_dnxhd
|
||||
FATE_SEEK-$(call ENCDEC, DNXHD, DNXHD) += dnxhd_720p_rd_dnxhd
|
||||
FATE_SEEK-$(call ENCDEC, DNXHD, MOV) += dnxhd_1080i_mov
|
||||
FATE_SEEK-$(call ENCDEC, DVVIDEO, DV) += dv_dv
|
||||
FATE_SEEK-$(call ENCDEC, DVVIDEO, DV) += dv_411_dv
|
||||
FATE_SEEK-$(call ENCDEC, DVVIDEO, DV) += dv_50_dv
|
||||
FATE_SEEK-$(call ENCDEC, FFV1, AVI) += ffv1_avi
|
||||
FATE_SEEK-$(call ENCDEC, FLASHSV, FLV) += flashsv_flv
|
||||
FATE_SEEK-$(call ENCDEC, FLV, FLV) += flv_flv
|
||||
FATE_SEEK-$(call ENCDEC, H261, AVI) += h261_avi
|
||||
FATE_SEEK-$(call ENCDEC, H263, AVI) += h263_avi
|
||||
FATE_SEEK-$(call ENCDEC, H263, AVI) += h263p_avi
|
||||
FATE_SEEK-$(call ENCDEC, HUFFYUV, AVI) += huffyuv_avi
|
||||
FATE_SEEK-$(call ENCDEC, JPEGLS, AVI) += jpegls_avi
|
||||
FATE_SEEK-$(call ENCDEC, LJPEG MJPEG, AVI) += ljpeg_avi
|
||||
FATE_SEEK-$(call ENCDEC, MJPEG, AVI) += mjpeg_avi
|
||||
|
||||
FATE_SEEK-$(call ENCDEC, MPEG1VIDEO, MPEG1VIDEO MPEGVIDEO) += \
|
||||
mpeg1_mpeg1video \
|
||||
mpeg1b_mpeg1video
|
||||
|
||||
FATE_SEEK-$(call ENCDEC, MPEG2VIDEO, MPEG2VIDEO MPEGVIDEO) += \
|
||||
mpeg2_422_mpeg2video \
|
||||
mpeg2_idct_int_mpeg2video \
|
||||
mpeg2_ilace_mpeg2video \
|
||||
mpeg2_ivlc_qprd_mpeg2video \
|
||||
mpeg2_thread_mpeg2video \
|
||||
mpeg2_thread_ivlc_mpeg2video
|
||||
|
||||
FATE_SEEK-$(call ENCDEC, MPEG4, MP4 MOV) += mpeg4_mp4
|
||||
FATE_SEEK-$(call ENCDEC, MPEG4, AVI) += $(subst -,_,$(FATE_MPEG4_AVI:%=%_avi))
|
||||
FATE_SEEK-$(call ENCDEC, MSMPEG4V3, AVI) += msmpeg4_avi
|
||||
FATE_SEEK-$(call ENCDEC, MSMPEG4V2, AVI) += msmpeg4v2_avi
|
||||
FATE_SEEK-$(call ENCDEC, RAWVIDEO, AVI) += rgb_avi
|
||||
FATE_SEEK-$(call ENCDEC, ROQ, ROQ) += roqvideo_roq
|
||||
FATE_SEEK-$(call ENCDEC, RV10, RM) += rv10_rm
|
||||
FATE_SEEK-$(call ENCDEC, RV20, RM) += rv20_rm
|
||||
FATE_SEEK-$(call ENCDEC, SNOW, AVI) += snow_avi
|
||||
FATE_SEEK-$(call ENCDEC, SNOW, AVI) += snow_ll_avi
|
||||
FATE_SEEK-$(call ENCDEC, SVQ1, MOV) += svq1_mov
|
||||
FATE_SEEK-$(call ENCDEC, WMV1, AVI) += wmv1_avi
|
||||
FATE_SEEK-$(call ENCDEC, WMV2, AVI) += wmv2_avi
|
||||
FATE_SEEK-$(call ENCDEC, RAWVIDEO, AVI) += yuv_avi
|
||||
|
||||
# files from fate-lavf
|
||||
|
||||
FATE_SEEK-$(call ENCDEC, PCM_S16BE, AIFF) += lavf_aif
|
||||
FATE_SEEK-$(call ENCDEC, PCM_ALAW, PCM_ALAW) += lavf_al
|
||||
FATE_SEEK-$(call ENCDEC2, MSMPEG4V3, MP2, ASF) += lavf_asf
|
||||
FATE_SEEK-$(call ENCDEC, PCM_S16BE, AU) += lavf_au
|
||||
FATE_SEEK-$(call ENCDEC2, MPEG4, MP2, AVI) += lavf_avi
|
||||
FATE_SEEK-$(call ENCDEC, BMP, IMAGE2) += image_bmp
|
||||
FATE_SEEK-$(call ENCDEC2, DVVIDEO, PCM_S16LE, AVI) += lavf_dv
|
||||
FATE_SEEK-$(call ENCDEC2, MPEG1VIDEO, MP2, FFM) += lavf_ffm
|
||||
FATE_SEEK-$(call ENCDEC, FLV, FLV) += lavf_flv
|
||||
FATE_SEEK-$(call ENCDEC, GIF, IMAGE2) += lavf_gif
|
||||
FATE_SEEK-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, GXF) += lavf_gxf
|
||||
FATE_SEEK-$(call ENCDEC, MJPEG, IMAGE2) += image_jpg
|
||||
FATE_SEEK-$(call ENCDEC2, MPEG4, MP2, MATROSKA) += lavf_mkv
|
||||
FATE_SEEK-$(call ENCDEC, ADPCM_YAMAHA, MMF) += lavf_mmf
|
||||
FATE_SEEK-$(call ENCDEC2, MPEG4, PCM_ALAW, MOV) += lavf_mov
|
||||
FATE_SEEK-$(call ENCDEC2, MPEG1VIDEO, MP2, MPEG1SYSTEM MPEGPS) += lavf_mpg
|
||||
FATE_SEEK-$(call ENCDEC, PCM_MULAW, PCM_MULAW) += lavf_ul
|
||||
FATE_SEEK-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, MXF) += lavf_mxf
|
||||
FATE_SEEK-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, MXF_D10 MXF) += lavf_mxf_d10
|
||||
FATE_SEEK-$(call ENCDEC2, MPEG4, MP2, NUT) += lavf_nut
|
||||
FATE_SEEK-$(call ENCDEC, FLAC, OGG) += lavf_ogg
|
||||
FATE_SEEK-$(call ENCDEC, PBM, IMAGE2PIPE) += pbmpipe_pbm
|
||||
FATE_SEEK-$(call ENCDEC, PCX, IMAGE2) += image_pcx
|
||||
FATE_SEEK-$(call ENCDEC, PGM, IMAGE2) += image_pgm
|
||||
FATE_SEEK-$(call ENCDEC, PGM, IMAGE2PIPE) += pgmpipe_pgm
|
||||
FATE_SEEK-$(call ENCDEC, PPM, IMAGE2) += image_ppm
|
||||
FATE_SEEK-$(call ENCDEC, PPM, IMAGE2PIPE) += ppmpipe_ppm
|
||||
FATE_SEEK-$(call ALLYES, RV10_ENCODER AC3_FIXED_ENCODER RM_MUXER) += lavf_rm
|
||||
FATE_SEEK-$(call ENCDEC, SGI, IMAGE2) += image_sgi
|
||||
FATE_SEEK-$(call ENCDEC, FLV, SWF) += lavf_swf
|
||||
FATE_SEEK-$(call ENCDEC, TARGA, IMAGE2) += image_tga
|
||||
FATE_SEEK-$(call ENCDEC, TIFF, IMAGE2) += image_tiff
|
||||
FATE_SEEK-$(call ENCDEC2, MPEG2VIDEO, MP2, MPEGTS) += lavf_ts
|
||||
FATE_SEEK-$(call ENCDEC, PCM_U8, VOC) += lavf_voc
|
||||
FATE_SEEK-$(call ENCDEC, PCM_S16LE, WAV) += lavf_wav
|
||||
FATE_SEEK-$(call ENCDEC, MP2, WTV) += lavf_wtv
|
||||
FATE_SEEK-$(CONFIG_YUV4MPEGPIPE_MUXER) += lavf_y4m
|
||||
|
||||
FATE_SEEK += $(FATE_SEEK-yes:%=fate-seek-%)
|
||||
|
||||
$(FATE_SEEK): fate-acodec fate-vsynth2 fate-lavf libavformat/seek-test$(EXESUF)
|
||||
$(FATE_SEEK): CMD = seektest
|
||||
|
||||
FATE_AVCONV += $(FATE_SEEK)
|
||||
fate-seek: $(FATE_SEEK)
|
Loading…
Reference in New Issue
Block a user