Migrate (to HDR FOX-T2)

sceedy

New Member
Migrate is a tool to help migrate non-native transport stream files to HDR-FOX T2 (previous versions are in a thread entitled "Request for information re hrwconv"). The current version is Vn0.6.
  • Windows program for creating HDR-FOX-compatible sidecar files from PVR-9300T recordings [and some TVs with recording to usb ports]
  • Drag-and-drop of single file supported
  • Indexing does not rely on the PTS being correct
  • Attempts to correct problem(s) where a full ffmpeg recode is not necessary
  • Produces TryMe script suggestion if problem(s) not fixed but understood
It indexes files to play on the HDR FOX-T2. Most of the time sidecar will be a better tool to perform this action unless you have a non-standard file. The ReadMe.txt in the release explains the differences. It is like selecting between a ring or open ended spanner, it depends upon the detail of what you wish to achieve.

It is open source, in sections related to the various wikis and standards used to produce the tool, so if you are interested in how indexing is done then it provides "a little light reading". Open source also allows for co-operation and constructive criticism.

Most of the people reading this post will have been brought up on WIMP (Windows, Icons, Mouse & Pointer) systems so CLI (Command Line Interface) will be "scary". Migrate supports drag & drop of the input file onto the executable to produce the 2 index files.

In Windows 10 the CLI is accessed from the executable "C:\Windows\System32\cmd.exe" and is no longer available from Windows Accessories in the start menu (I suggest finding it and sending a shortcut to the desktop). Linux users usually have no problem finding Terminal.

To use a CLI you just need a few "magic incantations". The one the beginner usually gets stuck on is :-
cd <path>
which allows you to change to the folder you wish to work in. Assuming you are dealing with video of family events (i.e. one video and one audio stream) a dvd rip is :-
ffmpeg -i <filename>.mpg -vcodec copy -acodec copy <filename>.m2ts
and a blu-ray rip is :-
ffmpeg -i <filename>.m2ts -vcodec copy -acodec aac <new filename>.m2ts
and a full recode for an unknown video type is :-
ffmpeg -i <filename>.<extension> -vcodec libx264 -color_primaries bt709 -color_trc bt709 -colorspace bt709 -pix_fmt yuv420p -level 4.1 -tune film -bluray-compat 1 -slices 4 -sar 1:1 -acodec aac <new filename>.m2ts
The technical people will tell you the above does not deal with subtitles. In theory this is "-scodec dvbsub" inserted into the above but, even with the latest ffmpeg, this usually results in a premature execution termination or no subtitles.
 

Attachments

Last edited:
OP
S

sceedy

New Member
INDEXING FOR DUMMIES

The HDR-Fox T2 (box) is a very capable media player. If you manage to get a non-native video file onto the box, MOST formats will play, skip and resume. If this is good enough for you then you can stop reading now.

You can see the native files from the "media" button on the remote control or via FileZilla (other FTP clients are available). From the remote control you get a name, via FileZilla you get a 4 (sometimes 3, read on) file set of <name>_<date time>.<extension>. (Windows hides file extensions by default so you may need to do some off topic reading if you don’t know what they are.) The extensions are thm, nts, hmt & ts. The thm is a thumbnail. This is created when the box gets round to it, or when you first play, whichever comes first so may not be present. The ts is the video file. This is encrypted when recorded and decrypted by copying to USB. (Off topic again - the ts extension is conventionally used on pcs for "transport stream" i.e. 188 byte packets. The box uses this for "MPEG2 transport stream" i.e. 192 byte packet which is conventionally m2ts on pcs hence MediaInfo complaining about incorrect file type). The hmt and nts files, commonly referred to as the sidecar files, are the result of indexing the ts file. The hmt file is mainly to do with what is displayed on the box via the "media" button. The nts file gives information about where the video frames are in the ts file.

Indexed ts files can fast forward etc by the box using the nts file to locate the video frames to display. For native files this is the end of it.

This is in the context of migrating files onto the box. If you index a file extension that is not a ts then the sidecar files are ignored. If you index a file that is not a 192 packet ts file then video play stops on the first attempt to fast forward or skip.

If the file is recorded from another countries broadcast then ac3 (audio standard) can be broadcast with an elementary stream type (one of the fields in a transport stream) of 0x81 (called Dolby Digital Audio in the relevant standard) but it is 0x06 when broadcast in the UK so playback fast forwards etc but is silent. Also H264 (video standard, read on) is never broadcast with ac3 so this combination is always silent irrespective of the elementary stream type.

TV is broadcast in the UK with one of 2 video standards MPEG2 and H264. Part of the MPEG2 standard is that compliant players can play MPEG1 which the box can do. The MPEG2 standard is the oldest of the two. With this compression you always get to the state where it is "cheaper" (in terms of storage size) to have an entire frame rather than differences from previous frames. Thus a correctly indexed MPEG2 will always fast forward (or fast reverse) as the box can always find a full frame close enough to the time it needs.

The H264 standard was conceived to overcome all the "deficiencies" of MPEG2 so does not have to contain any full frames. One of the UK broadcast standards contains a whole appendix on "Encoding Guidelines to Enable Trick Play Support of H.264/AVC Streams". If these guidelines are not followed during encoding the box exits playback on the first attempt to fast forward.
 

Black Hole

May contain traces of nut
I agree. The key point appears to be this:
Migrate supports drag & drop of the input file onto the executable to produce the 2 index files.
...but that nugget is hidden away in masses of text without any form of highlighting.

@sceedy: I'm not criticising your efforts, just your ability to put it over in a digestible way. This is not unlike a comment I made before (but went unanswered):
Thanks for sharing, hopefully it will be useful to somebody... but perhaps a clear summary of what it's for will help.
Please amend post 1 to at least start with some summary bullet points. This thread needs to stand alone without having to follow references to previous work. Something like (and I'm guessing here, don't take as authoritative):
  • Windows program for creating HDR-FOX-compatible sidecar files from PVR-9300T recordings [and what others?]

  • Drag-and-drop supported

  • ...whatever
The title could use some work too!
 

/df

Active Member
Obviously I downloaded this and tried to build it on an HD at hand.

Problem 1: the implementation of realpath() in the Humax uClibc conforms to POSIX:2000 which means it is allowed to (and does) crash on second argument NULL, instead of allocating some memory. Here's a solution, starting with this realpath.c:
Code:
#define _XOPEN_SOURCE 500

#include <limits.h>
#include <stdlib.h>
#include <string.h>
#ifdef TEST
#include <stdio.h>
#endif

char * __real_realpath( const char * path, char * resolved);

char * __wrap_realpath( const char * path, char * resolved) {
    char * out=resolved;
    if (!out) {
        out = (char *)malloc(PATH_MAX);
        resolved = __real_realpath(path, out);
        if (!resolved) 
            free(out); /* supposedly does not change errno */
        else
            resolved = (char *)realloc(out, strlen(out)+1);
        }
    else
        resolved = __real_realpath(path,resolved);
    
    return resolved;
}

#ifdef TEST
int main(int argc, char *argv[]) {

char* tpath = argv[0];
char * outpath = 0;
char * rpath = realpath(tpath, outpath);

printf( "Real path is '%s'\n", rpath);

return 0;
}
#endif
And the corresponding build command:
Code:
gcc -g -Wall -Wl,--defsym=__real_realpath=realpath -Wl,--wrap=realpath -o migrate Migrate.c Mult64.c realpath.c
Problem 2: with my first test file ("imagine: Beware of Mr Baker", from 2015, MP4[H.264 (Main) 704x396, 820 kb/s, 25 fps + aac (LC) 48000Hz, stereo]), there's a crash at line 1216:
Code:
...
               if (Start + PacketLength + PacketLength < LockLength)
               {
                  /* Check for lock */
                  locked = TRUE;

/* line 1216 */   for (strideindex = 0; strideindex < LockLength; strideindex += PacketLength) if (filebuff[Start + strideindex] != Pattern) locked = FALSE; 
               }
               /* Try increasing packet length */
               if ((!(locked))) PacketLength++;
            }                    
...
As written Start + strideindex can (and does) overflow the bounds of filebuff (ie 0..LockLength-1). Also, when setting locked to false, you can break the loop: { locked = FALSE; break; }. The following possible safe revisions of line 1216 both result in "Error: Unable to sync to ..."
Code:
                  for (strideindex = 0; strideindex < LockLength; strideindex += PacketLength) if (filebuff[strideindex] != Pattern) locked = FALSE; 

                  for (strideindex = Start; strideindex < LockLength; strideindex += PacketLength) if (filebuff[strideindex] != Pattern) locked = FALSE;
 
Last edited:
OP
S

sceedy

New Member
Black Hole – I thought I had replied with this thread, but I have never claimed to be good at human factors. At work I kept 3 technical authors busy editing my manuals.

/df – Thanks for the feedback. Problem 1 : consider me executed. Problem 2 : did occur with my test cases but did not result in any exceptions. This should have been caught when tidying up from the proof of concept build, a second pair of eyes definitely helped in this case ! Fixes for both problems are in the Vn0.7 development source.

Compiling for Humax is on my to-do list but quite a long way down (I want to use it as a time server on my non-internet connected network – 64 port gigabit switch with all IP addresses set manually). Does Mult64.c work on the Humax without resorting to hand editing the assembler output? If it does not return a non-truncated 64 result the calculated indices are incorrect and the C standards I have read say the compiler should truncate the result to 32 bits.
 

Black Hole

May contain traces of nut
Black Hole – I thought I had replied with this thread, but I have never claimed to be good at human factors. At work I kept 3 technical authors busy editing my manuals.
Well, I congratulate you for trying, but as we are unable to mind-read you have to be your own technical author here. What you write dives straight into the technical detail with hardly so much as a by-your-leave. I see you have made some updates, but basic questions anybody would ask remain unanswered:

Title: "Migrate (to HDR FOX-T2)" - Migrate what to HDR-FOX T2? Nobody should have to read the detail of the thread to find out if it applies to them, the title needs to give at least that much basic info. Also, note it's HDR-FOX T2 not "HDR FOX-T2" - you might think that's trivial, and obviously we understand what you mean, but little details like that create uncertainty in less experienced readers and it is essential to be consistent for clarity.

Bullet points: Not just what it does, but why you need to. What you need to do to get a file out of the 9300 in the first place. What happens if you simply import a 9300 recording directly into a HDR-FOX. If you mean a recording made by a capable TV, say so (plenty of TVs have USB ports without recording capability).

Most of the time sidecar will be a better tool to perform this action.
Under what circumstances is it better to use Migrate? You can't make a statement like that and leave it hanging.
 

Black Hole

May contain traces of nut
If it does not return a non-truncated 64 result the calculated indices are incorrect and the C standards I have read say the compiler should truncate the result to 32 bits.
So, what are you saying then: you've not adhered to C standards but expect your code to be portable? Nonetheless, it sounds peculiar if a 64-bit multiply routine doesn't output at least a 64-bit result (if it takes 64-bit inputs, the result should be 128-bit).
 

/df

Active Member
... Thanks for the feedback. Problem 1 : consider me executed.
It's sort of thing that can happen if you take code back to a platform that was defined 10 years or more ago.
... Does Mult64.c work on the Humax without resorting to hand editing the assembler output? If it does not return a non-truncated 64 result the calculated indices are incorrect and the C standards I have read say the compiler should truncate the result to 32 bits.
So you should meet <inttypes.h>, which is in C99 (and so in MSVC2010+, I believe).

For instance, this code:
Code:
#include <inttypes.h>
#include <stdio.h>

uint_fast64_t Mult64 (uint_fast32_t num1, uint_fast32_t num2)
{
   return (uint_fast64_t)num1 * (uint_fast64_t)num2;
}

int main(int argc, char*argv[]) {
    uint_fast32_t n1 = UINT32_C(4294967295); /* 2^32 - 1 = -1 mod 2^32 */
    uint_fast32_t n2 = UINT32_C(2147483651); /* 2^31 + 3 */

    uint_fast64_t n = Mult64(n1,n2);
    /* these PRI things are the format string codes: in this case u, u, llu */
    printf( "%" PRIuFAST32 "*%" PRIuFAST32 " = %" PRIuFAST64 "\n", n1,n2,n);
    return 0;
}
gives this output (which appears to be correct: 2^63 +5*2^31 - 3)
Code:
humax# ./a.out
4294967295*2147483651 = 9223372047592194045
humax#
 
Last edited:
OP
S

sceedy

New Member
Black Hole - How do I edit the thread title to correct the title ? I have made a snapshot of the first post to work on (with help)

/df - thanks for the pointer. I will look into it when I next have time. My visitors have arrived.
 
OP
S

sceedy

New Member
The strict answer to Black Hole’s question on 2 February 2020 16:43 is, that at Vn 0.6 and earlier, the source requires x86 32 bit ecosystem to compile to intended function. Vn 0.6.1 (attached) onwards requires a compiler configured with int as 32 bits or greater. Hopefully this will /df as well. I do not own the hardware to development test all the code changes so I had to "subcontract" some to former work colleagues. I have just come in and read my e-mails to find the trickiest development test has finally passed:)

When I needed to do something different, I have re-written the initial post. So far I have had 4 attempts and my former colleges tell me they are no better! Perhaps I should attempt something easier like herding cats when I need a change.
 

Attachments

Black Hole

May contain traces of nut
I have re-written the initial post. So far I have had 4 attempts and my former colleges tell me they are no better!
Thanks! At least you've tried. The difficulty would-be technical authors have to overcome is that what may be obvious to them (and therefore not need explaining) isn't obvious to everyone else (and therefore does have to be spelled out in a digestible form).

You have to put yourself in the position of somebody else with a need for the information you are trying to convey. I agree the reader should require some prior knowledge... but how much? The minimum, I suggest, is how to determine whether the information is going to be relevant - which is why you often see an introductory paragraph or section which carefully spells out who the paper is meant to be relevant to, and what prior knowledge is required to understand it (so if somebody really needs to, they can go away and bone up).
 
Last edited:

/df

Active Member
OK, now that it's clear the program is meant to work on TS containers, I built the 6.1 version which produced no errors or warnings. A left-over fixed_frame_rate_flag (l.3689) needs to be renamed for debug builds to work.
Code:
# gcc -g -Wall Mult64.c CLIonly.c Migrate.c -o Migrate
However I didn't manage to find a test file that could be processed.

For instance, take Rita Rudner (3/29/89) from YT downloaded in this format:
Code:
# ffprobe -hide_banner  Rita_Rudner_3_29_89.mp4 
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'Rita_Rudner_3_29_89.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isommp42
    creation_time   : 2019-03-20T05:10:17.000000Z
  Duration: 00:28:19.75, start: 0.000000, bitrate: 428 kb/s
    Stream #0:0(und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p(tv, smpte170m/smpte170m/bt709), 480x360 [SAR 1:1 DAR 4:3], 329 kb/s, 29.97 fps, 29.97 tbr, 30k tbn, 59.94 tbc (default)
    Metadata:
      creation_time   : 2019-03-20T05:10:17.000000Z
      handler_name    : ISO Media file produced by Google Inc. Created on: 03/19/2019.
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 95 kb/s (default)
    Metadata:
      creation_time   : 2019-03-20T05:10:17.000000Z
      handler_name    : ISO Media file produced by Google Inc. Created on: 03/19/2019.
Then made into M2TS (no subtitles involved):
Code:
# ffmpeg -i "Rita_Rudner_3_29_89.mp4" -vcodec copy -acodec copy Rita_Rudner_3_29_89.ts.m2ts"
# mv "Rita_Rudner_3_29_89.ts.m2ts" "Rita_Rudner_3_29_89.ts"
The resulting file plays on the HDR (as the mp4 did). It can be processed by sidecar -n -h, but some problem causes the audio to be lost when played.
Code:
# sidecar -n -h -i Rita_Rudner_3_29_89

Rita_Rudner_3_29_89.ts
Duration 1698 seconds.
Format SD H264, 480 x 720i.
Video ID $0100.
Audio ID $0101, Type AAC.
Audio Desc ID $0000, not present.
Sub-titles ID $0000, not present.
PMT ID $1000.
Prog ID $0001.
No EPG information available.
Updating existing HMT file.
Creating new NTS file.
Analyzing source video.
Writing NTS file entries.
42 NTS entries written.
NTS file creation task completed in 0 mins 27 secs.
As sidecar loses (and some obvious manual tweaks of the resulting .hmt don't bring the sound back), Migrate should do it. But the file can't be Migrated either (this is using the -Ddebug version):
Code:
# ./Migrate -s "Rita_Rudner_3_29_89.ts"
expandedpath = '/mnt/hd2/mod/src/migrate'
workingdirectory = '/mnt/hd2/mod/src/migrate'
InputFileInformation.InputFileInWorkingDirectory = 1
The filename supplied is 'Rita_Rudner_3_29_89.ts'
Basename is 'Rita_Rudner_3_29_89'
FileExtension is 'ts'
DateString is ''
TimeString is ''
Daylight savings is 0
RecordingName is 'Rita_Rudner_3_29_89'
ClearNTSFileEntry called, size (should be 64) = 64
... ditto ...
WriteStructure called, length = 3
ClearNTSFileEntry called, size (should be 64) = 64
... above line repeated 10 further times ...
locked = 0 Start = 4 PacketLength = 192
locked = 1 Start = 4 PacketLength = 192
sizeof(InputFileStatistics.st_size) = 8 PacketLength = 192
NumberOfPackets = 559490
ThisPacket = &0x0042d16c StructurePointer = &0x0042d170
PacketIndex = 34000 PIDCount = 7
PID 0x0001 found
PID 0x0040 found
PID 0x0041 found
PID 0x0050 found
PID 0x0101 found
PID 0x0141 found
PID 0x1140 found
hmtfile opened
ThisPacket = &0x0042d16c StructurePointer = &0x0042d170
... above line repeated 34244 further times ...
Warning: Audio will be silent - No audio stream detected
Error: File 'Rita_Rudner_3_29_89.ts' has insufficient information for indexing
The TryMe script has the wrong folder separators for Linux and should presumably be made executable. Should it expect to find ffmpeg and sidecar in the working directory rather than the path? Here are some diffs:
Code:
--- New/Migrate.c       2020-02-21 21:03:03.000000000 +0000
+++ Migrate.c   2020-02-22 13:49:31.000000000 +0000
@@ -3686,7 +3686,7 @@
          time_scale = H264u(32);
          AccurateFrameRate = H264u(1); // fixed_frame_rate_flag
 #ifdef debug
-         printf("num_units_in_tick = %d time_scale = %d fixed_frame_rate_flag = %d\n",num_units_in_tick,time_scale,fixed_frame_rate_flag);
+         printf("num_units_in_tick = %d time_scale = %d fixed_frame_rate_flag = %d\n",num_units_in_tick,time_scale,AccurateFrameRate);
 #endif
       }
 #ifdef fulldecode
@@ -4753,6 +4753,13 @@
 
 void CheckFormat(unsigned int CanBeIndexed, int IndexFailed)
 {
+#ifdef WIN32
+   #define EXE_EXT ".exe" 
+   #define BAT_EXT ".bat" 
+#else
+   #define EXE_EXT 
+   #define BAT_EXT 
+#endif
    char FileName[256];
    FILE *batfile = NULL;
    char *vcodec[] = {
@@ -4768,31 +4775,31 @@
       "Migrate",
       "sidecar -hn"
 #else
-      ".\\Migrate",
-      ".\\sidecar -hn"
+      "./Migrate",
+      "sidecar -hn"
 #endif
    };
+#ifdef WIN32
    struct __stat64 FileStatistics;
+   #define stat(x,y) _stat64((x),(y))
+#else
+   struct stat FileStatistics;
+#endif
 
    /* Check if input file exists and needs correction */
    strcpy(FileName, InputFileInformation.InputName);
    if (!(InputFileInformation.InputNameHasFileExtension))
    {
-      strcat(FileName, ".");
-      strcat(FileName, InputFileInformation.FileExtension);
+      sprintf(FileName, ".%s", InputFileInformation.FileExtension);
    }
    if (((((!(CanBeIndexed)) || (IndexFailed) || ((VideoType == H264) && (AudioType == AC3)) || (!(PartialETSI_TS_101_154Compliance))) &&
-         (_stat64(FileName, &FileStatistics) == 0)) ||
+         (stat(FileName, &FileStatistics) == 0)) ||
          ((VideoType == H264) &&
           (!((DSM_trick_mode_flag) ||
           ((SEIpayloadTypes[SEIbuffering_period]) && (SEIpayloadTypes[SEIpic_timing])) ||
           (SEIpayloadTypes[SEIdec_ref_pic_marking_repetition])))) ||
          (IntermediateName[0])) &&
-#ifdef WIN32
-       ((batfile = fopen("TryMe.bat", "w")) != NULL))
-#else
-       ((batfile = fopen("TryMe", "w")) != NULL))
-#endif
+       ((batfile = fopen("TryMe" BAT_EXT, "w")) != NULL))
    {
 
 #ifndef WIN32
@@ -4808,23 +4815,16 @@
       {
 
          /* Check if preferred ffmpeg output name exists in the working directory */
-         strcpy(IntermediateName, InputFileInformation.Basename);
-         strcat(IntermediateName, ".ts.m2ts");
-         if (_stat64(IntermediateName, &FileStatistics) == 0)
+         sprintf(IntermediateName, "%s.ts.m2ts", InputFileInformation.Basename);
+         if (stat(IntermediateName, &FileStatistics) == 0)
          {
             /* Calculate alternative ffmpeg output name */
-            strcpy(IntermediateName, InputFileInformation.Basename);
-            strcat(IntermediateName, ".");
-            strcat(IntermediateName, InputFileInformation.FileExtension);
-            strcat(IntermediateName, ".ts.m2ts");
+            sprintf(IntermediateName, "%s.%s.ts.m2ts", 
+                InputFileInformation.Basename, InputFileInformation.FileExtension);
          }
 
          /* ffmpeg command */
-#ifdef WIN32
          fprintf(batfile,"ffmpeg -i \"%s\" -vcodec %s -acodec %s \"%s\"\n",
-#else
-         fprintf(batfile,".\\ffmpeg -i \"%s\" -vcodec %s -acodec %s \"%s\"\n",
-#endif
                  FileName,vcodec[(PartialETSI_TS_101_154Compliance && CanBeIndexed &&
                                  (!((VideoType == H264) &&
                                    (!((DSM_trick_mode_flag) ||
@@ -4834,13 +4834,15 @@
       }
 
       /* Check if final file exists */
-      strcpy(FileName, InputFileInformation.Basename);
-      strcat(FileName, ".ts");
+      sprintf(FileName, "%s.ts", InputFileInformation.Basename);
+      if (stat(FileName, &FileStatistics) == 0) 
+          fprintf(batfile,
 #ifdef WIN32
-      if ((_stat64(FileName, &FileStatistics) == 0)) fprintf(batfile,"ren \"%s\" \"%s.org\"\n",FileName,FileName);
+              "ren \"%s\" \"%s.org\"\n",
 #else
-      if ((_stat64(FileName, &FileStatistics) == 0)) fprintf(batfile,"mv \"%s\" \"%s.org\"\n",FileName,FileName);
+              "mv \"%s\" \"%s.org\"\n",
 #endif
+              FileName,FileName);
 
       /* Rename to final file */
 #ifdef WIN32
@@ -4850,14 +4852,18 @@
 #endif
 
       /* Index final file */
-#ifdef WIN32
-      fprintf(batfile,"%s \"%s\"\n",index[(_stat64("sidecar.exe", &FileStatistics) == 0)],InputFileInformation.Basename);
-#else
-      fprintf(batfile,"%s \"%s\"\n",index[(_stat64("sidecar", &FileStatistics) == 0)],InputFileInformation.Basename);
-#endif
+      fprintf(batfile,"%s \"%s\"\n",index[(stat("sidecar" EXE_EXT, &FileStatistics) == 0)],InputFileInformation.Basename);
 
    }
 
+#ifndef WIN32
+   /* Convince Linux this is an executable text file (part 2)*/
+   do {
+       int batfd = fileno(batfile);
+       if ((-1 != batfd) && (0 == fstat(batfd, &FileStatistics)))
+           fchmod(batfd, FileStatistics.st_mode|S_IXUSR|S_IXGRP|S_IXOTH );
+      } while (false);
+#endif
    /* Close output file */
    if (batfile != NULL) fclose(batfile);
Counted string functions should be used (eg, snprintf() vs sprintf()) unless there's a very good reason. In fact I'd expect MSVC to get a right strop on with all the strcpy()s, etc. I didn't do that above. Also there's probably a lot more scope to eliminate platform-specific code, especially using /D_CRT_NONSTDC_NO_WARNINGS with MSVC.
 
Top