
Recherche avancée
Médias (91)
-
Corona Radiata
26 septembre 2011, par
Mis à jour : Septembre 2011
Langue : English
Type : Audio
-
Lights in the Sky
26 septembre 2011, par
Mis à jour : Septembre 2011
Langue : English
Type : Audio
-
Head Down
26 septembre 2011, par
Mis à jour : Septembre 2011
Langue : English
Type : Audio
-
Echoplex
26 septembre 2011, par
Mis à jour : Septembre 2011
Langue : English
Type : Audio
-
Discipline
26 septembre 2011, par
Mis à jour : Septembre 2011
Langue : English
Type : Audio
-
Letting You
26 septembre 2011, par
Mis à jour : Septembre 2011
Langue : English
Type : Audio
Autres articles (85)
-
Personnaliser en ajoutant son logo, sa bannière ou son image de fond
5 septembre 2013, parCertains thèmes prennent en compte trois éléments de personnalisation : l’ajout d’un logo ; l’ajout d’une bannière l’ajout d’une image de fond ;
-
Ecrire une actualité
21 juin 2013, parPrésentez les changements dans votre MédiaSPIP ou les actualités de vos projets sur votre MédiaSPIP grâce à la rubrique actualités.
Dans le thème par défaut spipeo de MédiaSPIP, les actualités sont affichées en bas de la page principale sous les éditoriaux.
Vous pouvez personnaliser le formulaire de création d’une actualité.
Formulaire de création d’une actualité Dans le cas d’un document de type actualité, les champs proposés par défaut sont : Date de publication ( personnaliser la date de publication ) (...) -
Publier sur MédiaSpip
13 juin 2013Puis-je poster des contenus à partir d’une tablette Ipad ?
Oui, si votre Médiaspip installé est à la version 0.2 ou supérieure. Contacter au besoin l’administrateur de votre MédiaSpip pour le savoir
Sur d’autres sites (8313)
-
How to use FFmpeg and GeForce Hardware to decode and encode 4K MKV movie to 1080p [closed]
27 janvier 2023, par slyfox1186I am struggling with the instruction provided to convert a 4k Movie to 1080p so I can run it easier on my plex server.


I have a Geforce 1080Ti and have enable cuda and all the necessary options when building ffmpeg.


I keep getting a weird error and I am stuck at the below point.


Here is my code that I am working on currently


REM @ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
COLOR 0A
TITLE CONVERT 4K TO 1080P USING GEFORCE HW

PUSHD "%~dp0"

SET "FF=C:\MAB\local64\bin-video\ffmpeg.exe"

FOR /R %%G IN (*.mkv) DO (
 "%FF%" -hide_banner -hwaccel cuda -y -i "%%~dpnG.mkv" -c:v h264_nvenc -preset slow -pix_fmts yuv420p10le -vf scale='1920:-1' -c:a copy "%%~dpnG(1080p).mkv"
 )

ECHO.
PAUSE
EXIT




below is the error output I get when running the above command


Guessed Channel Layout for Input Stream #0.1 : 5.1
Input #0, matroska,webm, from 'Mulan_2020.mkv':
 Metadata:
 title : mandtv.net
 encoder : libebml v1.4.0 + libmatroska v1.6.2
 creation_time : 2020-09-10T05:08:02.000000Z
 Duration: 01:55:08.70, start: 0.000000, bitrate: 16704 kb/s
 Stream #0:0(eng): Video: hevc (Main 10), yuv420p10le(tv, bt2020nc/bt2020/smpte2084), 3840x1608 [SAR 1:1 DAR 160:67], 23.98 fps, 23.98 tbr, 1k tbn, 23.98 tbc (default)
 Metadata:
 BPS-eng : 15933746
 DURATION-eng : 01:55:08.652000000
 NUMBER_OF_FRAMES-eng: 165642
 NUMBER_OF_BYTES-eng: 13760089087
 _STATISTICS_WRITING_APP-eng: mkvmerge v50.0.0 ('Awakenings') 64-bit
 _STATISTICS_WRITING_DATE_UTC-eng: 2020-09-10 05:08:02
 _STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
 Stream #0:1(eng): Audio: eac3, 48000 Hz, 5.1, fltp (default) (forced)
 Metadata:
 title : En
 BPS-eng : 768000
 DURATION-eng : 01:55:08.704000000
 NUMBER_OF_FRAMES-eng: 215897
 NUMBER_OF_BYTES-eng: 663235584
 _STATISTICS_WRITING_APP-eng: mkvmerge v50.0.0 ('Awakenings') 64-bit
 _STATISTICS_WRITING_DATE_UTC-eng: 2020-09-10 05:08:02
 _STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
 Stream #0:2(eng): Subtitle: subrip
 Metadata:
 title : English
 BPS-eng : 35
 DURATION-eng : 01:50:28.504000000
 NUMBER_OF_FRAMES-eng: 1150
 NUMBER_OF_BYTES-eng: 29135
 _STATISTICS_WRITING_APP-eng: mkvmerge v50.0.0 ('Awakenings') 64-bit
 _STATISTICS_WRITING_DATE_UTC-eng: 2020-09-10 05:08:02
 _STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
 Stream #0:3(ger): Subtitle: subrip
 Metadata:
 title : de
 BPS-eng : 2
 DURATION-eng : 00:03:07.062000000
 NUMBER_OF_FRAMES-eng: 2
 NUMBER_OF_BYTES-eng: 53
 _STATISTICS_WRITING_APP-eng: mkvmerge v50.0.0 ('Awakenings') 64-bit
 _STATISTICS_WRITING_DATE_UTC-eng: 2020-09-10 05:08:02
 _STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
 Stream #0:4(ger): Subtitle: subrip
 Metadata:
 title : de
 BPS-eng : 27
 DURATION-eng : 01:54:16.482000000
 NUMBER_OF_FRAMES-eng: 933
 NUMBER_OF_BYTES-eng: 23256
 _STATISTICS_WRITING_APP-eng: mkvmerge v50.0.0 ('Awakenings') 64-bit
 _STATISTICS_WRITING_DATE_UTC-eng: 2020-09-10 05:08:02
 _STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
 Stream #0:5(fre): Subtitle: subrip
 Metadata:
 title : fr
 BPS-eng : 0
 DURATION-eng : 01:40:51.510000000
 NUMBER_OF_FRAMES-eng: 21
 NUMBER_OF_BYTES-eng: 380
 _STATISTICS_WRITING_APP-eng: mkvmerge v50.0.0 ('Awakenings') 64-bit
 _STATISTICS_WRITING_DATE_UTC-eng: 2020-09-10 05:08:02
 _STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
 Stream #0:6(fre): Subtitle: subrip
 Metadata:
 title : fr
 BPS-eng : 29
 DURATION-eng : 01:54:19.902000000
 NUMBER_OF_FRAMES-eng: 806
 NUMBER_OF_BYTES-eng: 25098
 _STATISTICS_WRITING_APP-eng: mkvmerge v50.0.0 ('Awakenings') 64-bit
 _STATISTICS_WRITING_DATE_UTC-eng: 2020-09-10 05:08:02
 _STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
 Stream #0:7(spa): Subtitle: subrip
 Metadata:
 title : es
 BPS-eng : 2
 DURATION-eng : 00:03:21.201000000
 NUMBER_OF_FRAMES-eng: 3
 NUMBER_OF_BYTES-eng: 73
 _STATISTICS_WRITING_APP-eng: mkvmerge v50.0.0 ('Awakenings') 64-bit
 _STATISTICS_WRITING_DATE_UTC-eng: 2020-09-10 05:08:02
 _STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
 Stream #0:8(spa): Subtitle: subrip
 Metadata:
 title : es
 BPS-eng : 30
 DURATION-eng : 01:43:53.693000000
 NUMBER_OF_FRAMES-eng: 783
 NUMBER_OF_BYTES-eng: 24134
 _STATISTICS_WRITING_APP-eng: mkvmerge v50.0.0 ('Awakenings') 64-bit
 _STATISTICS_WRITING_DATE_UTC-eng: 2020-09-10 05:08:02
 _STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
 Stream #0:9(ita): Subtitle: subrip
 Metadata:
 title : it
 BPS-eng : 2
 DURATION-eng : 00:03:08.522000000
 NUMBER_OF_FRAMES-eng: 2
 NUMBER_OF_BYTES-eng: 67
 _STATISTICS_WRITING_APP-eng: mkvmerge v50.0.0 ('Awakenings') 64-bit
 _STATISTICS_WRITING_DATE_UTC-eng: 2020-09-10 05:08:02
 _STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
 Stream #0:10(ita): Subtitle: subrip
 Metadata:
 title : it
 BPS-eng : 27
 DURATION-eng : 01:54:16.649000000
 NUMBER_OF_FRAMES-eng: 784
 NUMBER_OF_BYTES-eng: 23506
 _STATISTICS_WRITING_APP-eng: mkvmerge v50.0.0 ('Awakenings') 64-bit
 _STATISTICS_WRITING_DATE_UTC-eng: 2020-09-10 05:08:02
 _STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
 Stream #0:11(por): Subtitle: subrip
 Metadata:
 title : pt
 BPS-eng : 27
 DURATION-eng : 01:54:16.649000000
 NUMBER_OF_FRAMES-eng: 784
 NUMBER_OF_BYTES-eng: 23202
 _STATISTICS_WRITING_APP-eng: mkvmerge v50.0.0 ('Awakenings') 64-bit
 _STATISTICS_WRITING_DATE_UTC-eng: 2020-09-10 05:08:02
 _STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
 Stream #0:12(por): Subtitle: subrip
 Metadata:
 title : pt
 BPS-eng : 2
 DURATION-eng : 00:03:08.522000000
 NUMBER_OF_FRAMES-eng: 2
 NUMBER_OF_BYTES-eng: 61
 _STATISTICS_WRITING_APP-eng: mkvmerge v50.0.0 ('Awakenings') 64-bit
 _STATISTICS_WRITING_DATE_UTC-eng: 2020-09-10 05:08:02
 _STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
 Stream #0:13(rus): Subtitle: subrip (default)
 Metadata:
 title : ru
 BPS-eng : 0
 DURATION-eng : 01:37:43.480000000
 NUMBER_OF_FRAMES-eng: 9
 NUMBER_OF_BYTES-eng: 420
 _STATISTICS_WRITING_APP-eng: mkvmerge v50.0.0 ('Awakenings') 64-bit
 _STATISTICS_WRITING_DATE_UTC-eng: 2020-09-10 05:08:02
 _STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
 Stream #0:14(rus): Subtitle: subrip
 Metadata:
 title : ru
 BPS-eng : 50
 DURATION-eng : 01:44:17.000000000
 NUMBER_OF_FRAMES-eng: 850
 NUMBER_OF_BYTES-eng: 39721
 _STATISTICS_WRITING_APP-eng: mkvmerge v50.0.0 ('Awakenings') 64-bit
 _STATISTICS_WRITING_DATE_UTC-eng: 2020-09-10 05:08:02
 _STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
 Stream #0:15(ukr): Subtitle: subrip
 Metadata:
 title : uk
 BPS-eng : 50
 DURATION-eng : 01:43:53.650000000
 NUMBER_OF_FRAMES-eng: 848
 NUMBER_OF_BYTES-eng: 39165
 _STATISTICS_WRITING_APP-eng: mkvmerge v50.0.0 ('Awakenings') 64-bit
 _STATISTICS_WRITING_DATE_UTC-eng: 2020-09-10 05:08:02
 _STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
Stream mapping:
 Stream #0:0 -> #0:0 (hevc (native) -> h264 (h264_nvenc))
 Stream #0:1 -> #0:1 (copy)
 Stream #0:2 -> #0:2 (subrip (srt) -> ass (ssa))
Press [q] to stop, [?] for help
[h264_nvenc @ 000002306685ccc0] 10 bit encode not supported
[h264_nvenc @ 000002306685ccc0] Provided device doesn't support required NVENC features
Error initializing output stream 0:0 -- Error while opening encoder for output stream #0:0 - maybe incorrect parameters such as bit_rate, rate, width or height
Conversion failed!



Can anyone spot what I'm missing ?


-
cuda invalid resource handle when using h264_cuvid decoder to decode video in my C program
29 juillet 2021, par ChrisFisherI try to use GPU acceleration in my ffmpeg decode program, and I check the codecs of ffmpeg by command :
ffmpeg -codecs | grep nv
, and it shows that I can use h264_cuvid decoder(In fact, I have already used ffmpeg command line to encode and decode a test video with hardware acceleration and it turned out everything was all fine), but when I use the decoder in my program

AVCodec *pCodec = avcodec_find_decoder_by_name("h264_cuvid");


here is part of my program


void FFMPEGCodec::initDecoder()
{
 AVCodec *pCodec = avcodec_find_decoder(AV_CODEC_ID_H264);
 if (!pCodec) {
 LOG("Codec decoder not found\n");
 exit(1);
 }

 pCodecCtx = avcodec_alloc_context3(pCodec);
 if (!pCodecCtx) {
 LOG("Could not allocate video codec context\n");
 exit(1);
 }

 pCodecCtx->width = gConfig->totalWidth;
 pCodecCtx->height = gConfig->totalHeight;
 pCodecCtx->has_b_frames = 0;

 if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
 LOG("Could not open codec\n");
 exit(1);
 }

 if(_x264rgb){
 //used to convert GBRP frame to RGB image.
 convertCtx = sws_getContext(gConfig->totalWidth, gConfig->totalHeight, AV_PIX_FMT_GBRP, 
 gConfig->totalWidth, gConfig->totalHeight, AV_PIX_FMT_RGB24, SWS_FAST_BILINEAR, NULL, NULL, NULL); 
 } else {
 //used to convert YUV frame to RGB image.
 convertCtx = sws_getContext(gConfig->totalWidth, gConfig->totalHeight, AV_PIX_FMT_YUV420P, 
 gConfig->totalWidth, gConfig->totalHeight, AV_PIX_FMT_RGB24, SWS_FAST_BILINEAR, NULL, NULL, NULL); 
 }

 if(convertCtx == NULL){
 LOG("Failed to get SwsContext\n");
 exit(1);
 }

 //when using x264rgb, it's actually GBRP frame, 
 //just don't want to define another variable
 yuvFrame = av_frame_alloc();
 if (!yuvFrame) {
 LOG("Failed to allocate yuv frame\n");
 exit(1);
 }

 rgbFrame = av_frame_alloc();
 if (!rgbFrame) {
 LOG("Failed to allocate rgb frame\n");
 exit(1);
 }

 rgbFrame->format = AV_PIX_FMT_RGB24;
 rgbFrame->width = pCodecCtx->width;
 rgbFrame->height = pCodecCtx->height;
 
 int ret = av_image_alloc(rgbFrame->data, rgbFrame->linesize, rgbFrame->width, rgbFrame->height,
 AV_PIX_FMT_RGB24, 32);
 if (ret < 0) {
 LOG("Failed to allocate raw picture buffer\n");
 exit(1);
 }
} 



and


int FFMPEGCodec::decode(byte* pktData, int pktSize, byte* imgData)
{
 int ret = 0, got_packet = 0;
 AVPacket pkt;
 av_init_packet(&pkt);
 pkt.data = pktData;
 pkt.size = pktSize;

 // decode video frame
 ret = avcodec_decode_video2(pCodecCtx, yuvFrame, &got_packet, &pkt);
 if (ret < 0) {
 LOG("Error decoding frame\n");
 return -1;
 }

 sws_scale(convertCtx, yuvFrame->data, yuvFrame->linesize, 0, pCodecCtx->height, rgbFrame->data, rgbFrame->linesize);
 
 if (got_packet) {
 int width = pCodecCtx->width, height = pCodecCtx->height;
 int fsize = rgbFrame->linesize[0] * rgbFrame->height;
 int size = 54 + fsize;

 byte bmp_file_header[14] = { 'B', 'M', 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, };
 byte bmp_info_header[40] = { 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 24, 0, };
 byte bmp_pad[3] = { 0, 0, 0 };

 bmp_file_header[2] = (unsigned char)size;
 bmp_file_header[3] = (unsigned char)(size >> 8);
 bmp_file_header[4] = (unsigned char)(size >> 16);
 bmp_file_header[5] = (unsigned char)(size >> 24);

 bmp_info_header[4] = (unsigned char)(width);
 bmp_info_header[5] = (unsigned char)(width >> 8);
 bmp_info_header[6] = (unsigned char)(width >> 16);
 bmp_info_header[7] = (unsigned char)(width >> 24);
 bmp_info_header[8] = (unsigned char)(height);
 bmp_info_header[9] = (unsigned char)(height >> 8);
 bmp_info_header[10] = (unsigned char)(height >> 16);
 bmp_info_header[11] = (unsigned char)(height >> 24);

 memcpy(imgData, bmp_file_header, 14);
 memcpy(imgData + 14, bmp_info_header, 40);
 memcpy(imgData + 54, rgbFrame->data[0], fsize);
 ret = size;
 }
 av_free_packet(&pkt);

 return ret;
}




after compiling, I ran the program, and the decoder throw me a error :


ctx->cvdl->cuvidDecodePicture(ctx->cudecoder, picparams) failed -> CUDA_ERROR_INVALID_HANDLE: invalid resource handle

when calling the functionavcodec_decode_video2


I don't know why this error occurred, by the way, I use a GTX1060 6G(Sorry I'm not a native English speaker)


-
cuda invalid resource handle when using h264_cuvid decoder in my C program [closed]
29 juillet 2021, par ChrisFisherI try to use GPU acceleration in my ffmpeg decode program, and I check the codecs of ffmpeg by command :
ffmpeg -codecs | grep nv
, and it shows that I can use h264_cuvid decoder(In fact, I have already used ffmpeg command line to encode and decode a test video with hardware acceleration and it turned out everything was all fine), but when I use the decoder in my program

AVCodec *pCodec = avcodec_find_decoder_by_name("h264_cuvid");


here is part of my program


void FFMPEGCodec::initDecoder()
{
 AVCodec *pCodec = avcodec_find_decoder(AV_CODEC_ID_H264);
 if (!pCodec) {
 LOG("Codec decoder not found\n");
 exit(1);
 }

 pCodecCtx = avcodec_alloc_context3(pCodec);
 if (!pCodecCtx) {
 LOG("Could not allocate video codec context\n");
 exit(1);
 }

 pCodecCtx->width = gConfig->totalWidth;
 pCodecCtx->height = gConfig->totalHeight;
 pCodecCtx->has_b_frames = 0;

 if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
 LOG("Could not open codec\n");
 exit(1);
 }

 if(_x264rgb){
 //used to convert GBRP frame to RGB image.
 convertCtx = sws_getContext(gConfig->totalWidth, gConfig->totalHeight, AV_PIX_FMT_GBRP, 
 gConfig->totalWidth, gConfig->totalHeight, AV_PIX_FMT_RGB24, SWS_FAST_BILINEAR, NULL, NULL, NULL); 
 } else {
 //used to convert YUV frame to RGB image.
 convertCtx = sws_getContext(gConfig->totalWidth, gConfig->totalHeight, AV_PIX_FMT_YUV420P, 
 gConfig->totalWidth, gConfig->totalHeight, AV_PIX_FMT_RGB24, SWS_FAST_BILINEAR, NULL, NULL, NULL); 
 }

 if(convertCtx == NULL){
 LOG("Failed to get SwsContext\n");
 exit(1);
 }

 //when using x264rgb, it's actually GBRP frame, 
 //just don't want to define another variable
 yuvFrame = av_frame_alloc();
 if (!yuvFrame) {
 LOG("Failed to allocate yuv frame\n");
 exit(1);
 }

 rgbFrame = av_frame_alloc();
 if (!rgbFrame) {
 LOG("Failed to allocate rgb frame\n");
 exit(1);
 }

 rgbFrame->format = AV_PIX_FMT_RGB24;
 rgbFrame->width = pCodecCtx->width;
 rgbFrame->height = pCodecCtx->height;
 
 int ret = av_image_alloc(rgbFrame->data, rgbFrame->linesize, rgbFrame->width, rgbFrame->height,
 AV_PIX_FMT_RGB24, 32);
 if (ret < 0) {
 LOG("Failed to allocate raw picture buffer\n");
 exit(1);
 }
} 



and


int FFMPEGCodec::decode(byte* pktData, int pktSize, byte* imgData)
{
 int ret = 0, got_packet = 0;
 AVPacket pkt;
 av_init_packet(&pkt);
 pkt.data = pktData;
 pkt.size = pktSize;

 // decode video frame
 ret = avcodec_decode_video2(pCodecCtx, yuvFrame, &got_packet, &pkt);
 if (ret < 0) {
 LOG("Error decoding frame\n");
 return -1;
 }

 sws_scale(convertCtx, yuvFrame->data, yuvFrame->linesize, 0, pCodecCtx->height, rgbFrame->data, rgbFrame->linesize);
 
 if (got_packet) {
 int width = pCodecCtx->width, height = pCodecCtx->height;
 int fsize = rgbFrame->linesize[0] * rgbFrame->height;
 int size = 54 + fsize;

 byte bmp_file_header[14] = { 'B', 'M', 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, };
 byte bmp_info_header[40] = { 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 24, 0, };
 byte bmp_pad[3] = { 0, 0, 0 };

 bmp_file_header[2] = (unsigned char)size;
 bmp_file_header[3] = (unsigned char)(size >> 8);
 bmp_file_header[4] = (unsigned char)(size >> 16);
 bmp_file_header[5] = (unsigned char)(size >> 24);

 bmp_info_header[4] = (unsigned char)(width);
 bmp_info_header[5] = (unsigned char)(width >> 8);
 bmp_info_header[6] = (unsigned char)(width >> 16);
 bmp_info_header[7] = (unsigned char)(width >> 24);
 bmp_info_header[8] = (unsigned char)(height);
 bmp_info_header[9] = (unsigned char)(height >> 8);
 bmp_info_header[10] = (unsigned char)(height >> 16);
 bmp_info_header[11] = (unsigned char)(height >> 24);

 memcpy(imgData, bmp_file_header, 14);
 memcpy(imgData + 14, bmp_info_header, 40);
 memcpy(imgData + 54, rgbFrame->data[0], fsize);
 ret = size;
 }
 av_free_packet(&pkt);

 return ret;
}




after compiling, I ran the program, and the decoder throw me a error :


ctx->cvdl->cuvidDecodePicture(ctx->cudecoder, picparams) failed -> CUDA_ERROR_INVALID_HANDLE: invalid resource handle

when calling the functionavcodec_decode_video2


I don't know why this error occurred, by the way, I use a GTX1060 6G(Sorry I'm not a native English speaker)