2016年1月31日 星期日

A Calculator Supports Parentheses Writtren in C




 The flow chart be:

 Read Input  -> Get Tokens -> Infix To Postfix -> Evaluate -> Output Result



GetToken : Check if there are the known syntaxes or not.

Infix To Postfix: Check if the parentheses are balance or not.

Evaluate: Check if there is the operator or operand being dangle or not.


My Code:

/*
ref :
 http://www.paulgriffiths.net/program/c/calc1.php
 http://openhome.cc/Gossip/AlgorithmGossip/InFixPostfix.htm //tranditional chinese
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <ctype.h>
#include <math.h>

#define _FORCE_FLOATING_ARITHMETIC

#ifndef FALSE
 #define FALSE       (0)
 #define TRUE       (1)
#endif

#define MAX_STR_LEN       (256)

enum TokenType
{
 Unknown,
 ExpressionEnd,
 Operator,
 OperandInteger, OperandFloat
};

enum OperatorType
{
 OP_UNKOWN = 0, OP_PLUS, OP_MINUS, OP_MULTIPLY, OP_DIVIDE,
 OP_POWER, OP_MOD, OP_LPAREN, OP_RPAREN, 
};

typedef struct TokenProperty {
 enum TokenType tokenType;

 union
 {
  long long intValue;
  double floatValue;
  struct
  {
   enum OperatorType operatorType;
   char unknownSymbol;
  };
 };/*union*/
}TokenProperty;


int GetTokenNumber(char *pStr, int bufferSize)
{
 int number;
 char *pMovBuf;

 number = 0;
 pMovBuf = pStr;
 while ((pMovBuf - pStr) < bufferSize)
 {
  char *pTemp;

  if ('\0' == *pMovBuf || '\n' == *pMovBuf || EOF == *pMovBuf)
  {
   number++;
   break;
  }/*if end */

  if (isspace(*pMovBuf))
   pMovBuf++;

  pTemp = pMovBuf;

  strtold(pMovBuf, &pTemp);

  if (pMovBuf == pTemp
   || *pTemp == 'e' || *pTemp == 'E'
#if(0)
   || *pTemp == 'f' || *pTemp == 'F'
#endif
   )
  {
   pTemp++;
  }/*if strtold valid or float suffix*/

  pMovBuf = pTemp;
  number++;
 }/*while 0 < bufferSize*/

 return number;
}/*GetTokenNumber*/


int PrintTokenProperty(int n, struct TokenProperty *pTokens)
{
 int i;

 for (i = 0; i < n; i++) {
  switch (pTokens[i].tokenType)
  {
  case Unknown:
   printf("Unknown\n");
   break;
  case ExpressionEnd:
   printf("ExpressionEnd\n");
   break;
  case Operator:
   printf("Operator, ");
   switch (pTokens[i].operatorType)
   {
   case OP_UNKOWN:
    printf("OP_UNKOWN \n");
    break;

   case OP_PLUS:
    printf("OP_PLUS \n");
    break;
   
   case OP_MINUS:
    printf("OP_MINUS \n");
    break;

   case OP_MULTIPLY:
    printf("OP_MULTIPLY \n");
    break;

   case OP_DIVIDE:
    printf("OP_DIVIDE \n");
    break;

   case OP_POWER:
    printf("OP_POWER \n");
    break;

   case OP_MOD:
    printf("OP_MOD \n");
    break;

   case OP_LPAREN:
    printf("OP_LPAREN \n");
    break;

   case OP_RPAREN:
    printf("OP_RPAREN \n");
    break;

   default:
    return -2;
   }/*switch operatorType*/
   break;
  case OperandInteger:
   printf("OperandInteger, %lld\n", pTokens[i].intValue);
   break;
  case OperandFloat:
   printf("OperandFloat, %f\n", pTokens[i].floatValue);
   break;
  default:
   return -1;
  }/*switch tokenType*/

 }/*for */
 printf("\n");
 return 0;
}/*PrintTokenProperty*/


int GetNextToken(char *pStr, int strSize, struct TokenProperty *pToken, int *pCostedStrLen)
{
 int tokenLen;
 char *pMovBuf;

 tokenLen = 0;
 pMovBuf = pStr;


 if ('\0' == *pMovBuf || '\n' == *pMovBuf || EOF == *pMovBuf)
 {
  pToken->tokenType = ExpressionEnd;
  pMovBuf++;
  goto Flag_End_GetToken;
 }/*if*/

 while (*pMovBuf && isspace(*pMovBuf))
  pMovBuf++;

 if (FALSE != isdigit(*pMovBuf))
 {
  /*  Token is an operand  */
  int isFloat;
  isFloat = FALSE;

  {
   long long intValue;
   char *pTemp;

   intValue = strtoll(pMovBuf, &pTemp, 0);
   if (*pTemp == '.'
    || *pTemp == 'e' || *pTemp == 'E'
#if(0)
    || *pTemp == 'f' || *pTemp == 'F'
#endif
    )
   {
    isFloat = TRUE;
   }
   else
   {
    pToken->tokenType = OperandInteger;
    pToken->intValue = intValue;
    pMovBuf = pTemp;
   }/*is float*/
  }/*local variable*/

  if (FALSE != isFloat)
  {
   pToken->floatValue = strtod(pMovBuf, &pMovBuf);
   pToken->tokenType = OperandFloat;
#if(0)
   if ('f' == *pMovBuf || 'F' == *pMovBuf)
    pMovBuf++;
#endif
  }/*FALSE == isFloat*/

  goto Flag_End_GetToken;
 }/* operand */


 {
  /*Token is an operator*/  
  char symbol;
  symbol = *pMovBuf;
  pToken->tokenType = Operator;

  switch (symbol)
  {
  case '+':
   pToken->operatorType = OP_PLUS;
   break;
  case '-':
   pToken->operatorType = OP_MINUS;
   break;
  case '*':
   pToken->operatorType = OP_MULTIPLY;
   break;
  case '/':
   pToken->operatorType = OP_DIVIDE;
   break;

  case '^':
   pToken->operatorType = OP_POWER;
   break;
  case '%':
   pToken->operatorType = OP_MOD;
   break;

  case '(':
   pToken->operatorType = OP_LPAREN;
   break;

  case ')':
   pToken->operatorType = OP_RPAREN;
   break;

  default:
   pToken->operatorType = OP_UNKOWN;
   pToken->unknownSymbol = symbol;
   break;
  }/*switch*/

  pToken->tokenType = Operator;
  pMovBuf++;
 }/*operator */

Flag_End_GetToken:

 tokenLen = (int)(pMovBuf - pStr);
 *pCostedStrLen = tokenLen;

 return tokenLen;
}/*GetToken*/


int GetTokens(char *pStr, int strLen, struct TokenProperty *pTokenArray)
{
 int costedSize;
 int k;
 char *pMovBuf; 

 pMovBuf = pStr; 

 k = 0;

 while (0 < strLen)
 {
  GetNextToken(pMovBuf, strLen, &pTokenArray[k], &costedSize);

  pMovBuf += costedSize;
  strLen -= costedSize;
  k++;  
 }/*while 0 < strLen*/


 {/*check if there is unknownSymbol*/
  int i;    
  for (i = 0; i < k; i++)
  {
   if (Operator == pTokenArray[i].tokenType &&
    OP_UNKOWN == pTokenArray[i].operatorType)
   {
    printf("Error : character %c unknown\n",
     pTokenArray[i].unknownSymbol);

    return -1;
   }/*if */

  }/*for i*/
  
 }/*local variable*/

#ifndef _DEBUG
 /*check if there is grammatical error*/
 {
  int i;
  struct TokenProperty previousToken;

  memcpy(&previousToken, &pTokenArray[0],
   sizeof(struct TokenProperty));

  for (i = 1; i < k; i++)
  {   
   switch (pTokenArray[i].tokenType)
   {
   case Operator:
    if (Operator == previousToken.tokenType
     && OP_LPAREN != previousToken.operatorType
     && OP_RPAREN != previousToken.operatorType)
    {
     printf("error : two operator have been"
      " put together !\n");
     return -2;
    }
    break;
   case OperandFloat:
   case OperandInteger:
    if (OperandFloat == previousToken.tokenType
     || OperandInteger == previousToken.tokenType)
    {
     printf("error : two operend have been" 
      " put together !\n");
     return -3;
    }
    break;
   }/*switch*/

   memcpy(&previousToken, &pTokenArray[i],
    sizeof(struct TokenProperty));
  }/*for i*/
 }/*local variable*/ 

#endif /*_DEBUG*/

 return k;
}/*GetTokens*/


int InfixArrayToPostfixStack(int nInfixToken, struct TokenProperty *pTokens)
{
 struct TokenProperty *pTokenInfixArray;
 struct TokenProperty *pTokenPostfixStack;

 struct TokenProperty *pCurrentToken;

 unsigned char precedence[MAX_STR_LEN];
 int i;
 int nPostfixToken;
 int operatorStackTop;

 struct TokenProperty *pOperatorTokenStack;
 
 
 pTokenInfixArray = pTokens;

 if (0 >= nInfixToken)
  return -1;

 { /*initialize the precedence array*/

  memset(&precedence[0], 0, MAX_STR_LEN);
  precedence[OP_PLUS] = 1; precedence[OP_MINUS] = 1;
  precedence[OP_MULTIPLY] = 2; precedence[OP_DIVIDE] = 2;
  precedence[OP_POWER] = 3; precedence[OP_DIVIDE] = 2;

  precedence[OP_LPAREN] = 255; precedence[OP_RPAREN] = 254;
  precedence[OP_UNKOWN] = 0;
 }/*local block*/

 pOperatorTokenStack =
  (struct TokenProperty*)malloc((nInfixToken)*sizeof(struct TokenProperty));
 memset(pOperatorTokenStack, 0, (nInfixToken)*sizeof(struct TokenProperty));

 pTokenPostfixStack =
  (struct TokenProperty*)malloc(nInfixToken*sizeof(struct TokenProperty)); 
 memset(pTokenPostfixStack, 0, nInfixToken*sizeof(struct TokenProperty));

 pCurrentToken = &pTokenInfixArray[0];
 
 operatorStackTop = -1;
 nPostfixToken = 0;

 for (i = 0; i < nInfixToken; i++)
 {
  enum TokenType tokenType;
  tokenType = pCurrentToken->tokenType;

  switch (tokenType)
  {  
  case OperandInteger:
  case OperandFloat:
   memcpy(&pTokenPostfixStack[nPostfixToken],
    pCurrentToken, sizeof(struct TokenProperty));
   nPostfixToken += 1;
   break;
  case Operator:
   switch (pCurrentToken->operatorType)
   {
   case OP_UNKOWN:
    printf("Unknown operator %c\n", pCurrentToken->unknownSymbol);
    return -2;

   case OP_PLUS:
   case OP_MINUS:
   case OP_MULTIPLY:
   case OP_DIVIDE:
   case OP_POWER:
   case OP_MOD:
    if (0 <= operatorStackTop)
    {
     
     /*if there is no parenthesis to force current operator 
      subduing previous operator*/
     if (OP_LPAREN !=
      pOperatorTokenStack[operatorStackTop].operatorType)
     {
      enum OperatorType operatorStackTopType;
      operatorStackTopType 
       = pOperatorTokenStack[operatorStackTop].operatorType;

      /*if previous operator subdues current operator,
      ouput the operatorStackTop one to postfix stack */

      if (precedence[pCurrentToken->operatorType] <
       precedence[operatorStackTopType])
      {

       memcpy(&pTokenPostfixStack[nPostfixToken],
        &pOperatorTokenStack[operatorStackTop],
        sizeof(struct TokenProperty));
       nPostfixToken += 1;
       operatorStackTop -= 1;
      }/*if */
     }/*keep ( in the stack */
    }/*stack is not empty*/

    operatorStackTop += 1;
    memcpy(&pOperatorTokenStack[operatorStackTop], pCurrentToken,
     sizeof(struct TokenProperty));
    break;

   case OP_LPAREN:
    operatorStackTop += 1;
    memcpy(&pOperatorTokenStack[operatorStackTop], pCurrentToken,
     sizeof(struct TokenProperty));
    break;

   case OP_RPAREN:
    while ( OP_LPAREN != 
     pOperatorTokenStack[operatorStackTop].operatorType)
    {
     if (0 > operatorStackTop)
     {
      printf("error : ( could not be found! \n");
      return -3;
     }/*not balance*/

     memcpy(&pTokenPostfixStack[nPostfixToken],
      &pOperatorTokenStack[operatorStackTop],
      sizeof(struct TokenProperty));

     nPostfixToken += 1;
     operatorStackTop -= 1;
    }/*while parenthesis is balance*/

    operatorStackTop -= 1;
    break;

   default:
    break;
   }/*switch*/

   break;
  case Unknown:
   //printf("unknow token type %d");
   return -2;
  }/*switch*/

  pCurrentToken++;
 }/*while ExpressionEnd != pCurrentToken->tokenType*/
 

 /*inverse output to postfix stack*/
 while (0 <= operatorStackTop)
 {
  
  if (OP_LPAREN == pOperatorTokenStack[operatorStackTop].operatorType)
  {
   printf("error : ) could not be found! \n");
   return -3;
  }/*not balance*/
  
  memcpy(&pTokenPostfixStack[nPostfixToken], 
   &pOperatorTokenStack[operatorStackTop], sizeof(struct TokenProperty)); 
  nPostfixToken += 1;
  operatorStackTop -= 1;
 }/*while*/
 
 memcpy(pTokens, pTokenPostfixStack, nPostfixToken*sizeof(struct TokenProperty));

 free(pTokenPostfixStack); pTokenPostfixStack = NULL;

 return nPostfixToken;
}/*TokenArrayInfixToPostfix*/


long long ipow(int base, int exp)
{
 long long result = 1;

 while (exp)
 {
  if (exp & 1)
   result *= base;
  base *= base;
  exp >>= 1;
 }

 return result;
}/*ipow*/


union evaluateType
{
 long long integerType;
 double floatType;
};


int EvaluatePostfixStack(int nPostfixToken, struct TokenProperty *pTokenPostfixStack,
 int *pIsFloat, union evaluateType *pResult)
{
 int i;
 int isThereFloat;
 isThereFloat = FALSE;
 union evaluateType *pOperandStack;
 int top;

#ifdef _FORCE_FLOATING_ARITHMETIC
 isThereFloat = TRUE;
#else
 for (i = 0; i < nPostfixToken; i++)
 {
  if (OperandFloat == pTokenPostfixArray[i].tokenType)
  {
   isThereFloat = TRUE;
   break;
  }/*if*/  
 }/*for i*/
#endif

 if (FALSE != isThereFloat)
 {
  for (i = 0; i < nPostfixToken; i++)
  {
   if (OperandInteger == pTokenPostfixStack[i].tokenType)
   {
    pTokenPostfixStack[i].tokenType = OperandFloat;
    pTokenPostfixStack[i].floatValue
     = (double)pTokenPostfixStack[i].intValue;
   }/*if */
  }/*for i*/
 }/*if FALSE != isThereFloat*/


 pOperandStack = 
  (union evaluateType*)malloc(nPostfixToken*sizeof(union evaluateType));

 top = -1;
 
 for (i = 0; i < nPostfixToken; i++)
 {
  switch (pTokenPostfixStack[i].tokenType)
  {
  case OperandFloat:
   top += 1;
   pOperandStack[top].floatType
    = pTokenPostfixStack[i].floatValue;
   break;

  case OperandInteger:
   top += 1;
   pOperandStack[top].integerType
    = pTokenPostfixStack[i].intValue;
   break;

  case Operator:
   {
    union evaluateType a, b, c;

    if (OP_RPAREN == pTokenPostfixStack[i].operatorType
     || OP_LPAREN == pTokenPostfixStack[i].operatorType)
    {
     break;
    }/*ingore parenthesis*/

    if (0 > top)
    {
     printf("error,  deficiency of operand!");
     return -4;
    }

    if (FALSE == isThereFloat)
     b.integerType = pOperandStack[top].integerType;
    else
     b.floatType = pOperandStack[top].floatType;

    top -= 1;


    if (0 > top)
    {
     
     printf("error, lacking operand !");
     return -3;
    }
    if (FALSE == isThereFloat)
     a.integerType = pOperandStack[top].integerType;
    else
     a.floatType = pOperandStack[top].floatType;

    top -= 1;

    switch (pTokenPostfixStack[i].operatorType)
    {
    case OP_UNKOWN:
     printf("Unknown operator %c\n", 
      pTokenPostfixStack[i].unknownSymbol);
     return -2;
    
    case OP_PLUS:
     if (FALSE == isThereFloat)
      c.integerType = a.integerType + b.integerType;
     else
      c.floatType = a.floatType + b.floatType;
     break;

    case OP_MINUS:
     if (FALSE == isThereFloat)
      c.integerType = a.integerType - b.integerType;
     else
      c.floatType = a.floatType - b.floatType;
     break;

    case OP_MULTIPLY:
     if (FALSE == isThereFloat)
      c.integerType = a.integerType * b.integerType;
     else
      c.floatType = a.floatType * b.floatType;
     break;

    case OP_DIVIDE:

     if (FALSE == isThereFloat)
      c.integerType = a.integerType / b.integerType;
     else
      c.floatType = a.floatType / b.floatType;
     break;

    case OP_POWER:
     if (FALSE == isThereFloat)
      c.integerType 
      = ipow((int)a.integerType, (int)b.integerType);
     else
      c.floatType = pow(a.floatType, b.floatType);
     break;

    case OP_MOD:
     if (FALSE == isThereFloat)
      c.integerType = a.integerType % b.integerType;
     else
      c.floatType = fmod(a.floatType, b.floatType);
     break;
    
    default:
     break;
    }/*switch (pTokenPostfixArray[i].operatorType)*/

    top += 1;
    pOperandStack[top] = c;
   }/*Operator*/   
   break;

  case Unknown:
   printf("Unknown operator %c\n", pTokenPostfixStack[i].unknownSymbol);
   return -1;
   break;

  case ExpressionEnd:   
   break;
  default:
   break;
  }/*switch*/
    
 }/*for i */
 
 *pIsFloat = isThereFloat;
 *pResult = pOperandStack[0];

 free(pOperandStack); pOperandStack = NULL;

 if (0 != top)
 {
  printf("error, lacking operator between two operands  !");
  return -5;
 }/*if not only top exists*/ 

 return 0;
}/*EvaluatePostfix*/

#define CONFIRMED_SIZE      (4) // for Expression End


int main(int argc, char *argv)
{
 char inputStr[MAX_STR_LEN];
 int strLen;

 struct TokenProperty *pTokens;
 int nToken;

 int isFloat;
 union evaluateType result;

 memset(&inputStr[0], 0, MAX_STR_LEN);

 printf("input your expression:\n");

 fgets(&inputStr[0], MAX_STR_LEN, stdin);
 strLen = (int)strlen(&inputStr[0]);

 nToken = GetTokenNumber(&inputStr[0], strLen);

 pTokens =
  (struct TokenProperty*)malloc(
   (nToken + CONFIRMED_SIZE)*sizeof(struct TokenProperty));

 memset(pTokens, 0, (nToken + CONFIRMED_SIZE)*sizeof(struct TokenProperty));

 nToken = GetTokens(&inputStr[0], strLen, pTokens);
 if (0 > nToken)
  return -1;

 nToken = InfixArrayToPostfixStack(nToken, pTokens);
 if (0 > nToken)
  return -2;

 PrintTokenProperty(nToken, pTokens);

 if (0 > EvaluatePostfixStack(nToken, pTokens, &isFloat, &result))
   return -3;

 free(pTokens); pTokens = NULL;
 
 if (FALSE == isFloat)
  printf(" = %lld\n", result.integerType);
 else
  printf(" = %f\n", result.floatType);

 return 0;
}/*main*/

Run the code:


input your expression:
(1 +2)^2.5/(2*0.2)
 = 38.971143


Explaination:

The code is straightforward, the postfix stack has been adopted in here:

the concept of postfix stack is :


零.  create a temporary stack to store opeators.

example :

a + b + c :
 


a
b
c


+
+

The combination of the two stack be :


a
b
c
+
+




一. The operator is put more late, the precedence would be more high in nature. It is the general rule to make the postfix stack.


example :

 a + b - c


a
b
c
-
+




二. While precedence  of previous operator is higher than current's, put previous operator into postfix stack.

example :

 a  * b  + c


a
b
*
c
+

Explanation : the precedence  of multiplication is higher that addition. Once while the addition would be put into opation stack, I should move the multiplication (the previous one in the operator stack ) into the postfix stack first.




三. While there is a right parenthesis, move all the opeators from the opeartor stack into the postfix stack until encountering a left parenthesis:

example :

(a^b * c) - d


a
b
^
c
*
d
-

Explanation : The power opeator would be put in the postfix stack in first by the rule 二, and the multiplication would be store in the operator stack for further processing; Once the rght  parenthesis has been enoutered, the multiplication would be move into the postfix stack from the operator stack.


Above is my  cognition of postfix stack algorithm, I hope it is useful for you.




2016年1月23日 星期六

Build FFmpeg Libraries in Windows via MinGW



  It is trite, but I note how to build the ffmpeg in this article.




   Set up your MinGW environment, you could download 32/64 bit installation file from here 

 you could select which compiler you would like to install. The necessary is mingwg-developer-toolkit, mingw32-base and mingw32-gcc-g++:



After your installation done, open the MinGW shell (on YourMigwPATH\msys\1.0\msys.bat ) to check if the gcc works or not:


Gaiger@i5-4570 ~
$ gcc
sh: gcc: command not found



If the gcc be not existing, move all the folder besides msys inYourMigwPATH  into the folder

YourMigwPATH\msys\1.0

Currently, the gcc would be work in the MinGW environment.


Gaiger@i5-4570 ~
$ gcc
gcc.exe: fatal error: no input files
compilation terminated.

Gaiger@i5-4570 ~
$



一.

   Download the FFmpeg source code,  choose which version you like. Warning : HEVC (h264) supporting after verion 2.0.

   Uncompress the tar ball file and move the source folder into the folder YourMigwPATH\32\msys\1.0\home\YourUserName .

二.

   Go into the ffmpeg source folder on the MinGW shell,  my configure be :


./configure --enable-memalign-hack --arch=x86 --target-os=mingw32 --enable-cross-compile --enable-w32threads --cross-prefix=$PWD --prefix=/built

NOTE : I want the static libraries only, if you want the shared ones(to avoid GPL), you should add :


enable-shared

In your configuring parameter.

The configuring time in MinGW costs time more than it in linux, Do not be suspicious  the MingW hanging and wait it done.


三.

   Open the file ffmpegSourceRootRoot\libavformat\os_support.h, add the 2 line, about line number 32:


#include "config.h"

#if defined(__MINGW32__) && !defined(__MINGW32CE__)
#define WIN32_LEAN_AND_MEAN
#  include <windows.h>
#  include <fcntl.h>
#  define lseek(f,p,w) _lseeki64((f), (p), (w))
#  define stat _stati64
#  define fstat(f,s) _fstati64((f), (s))
#endif /* defined(__MINGW32__) && !defined(__MINGW32CE__) */



  And Check the file ffmpegSourceRootRoot\cmdutils.c added the code or not , about line number 172:


#if defined(_WIN32) && !defined(__MINGW32CE__)
#include <windows.h>
#include <shellapi.h>
/* Will be leaked on exit */
static char** win32_argv_utf8 = NULL;
static int win32_argc = 0;


If it is not being added, complement that. Or you could add the parameter in the configuring :


CFLAGS="-Wno-implicit-function-declaration"


四:

   All preparations have been done , type "make" to build it.

  After the build done, type "make install" , the portable binaries and  libraries would be under folder ffmpegSourceRootRoot\built.

五.
   Goto the folder ffmpegSourceRootRoot\built\bin in the MinGW shell, to check if the ffmpeg has been built successfully or not:


Gaiger@i5-4570 ~/ffmpeg/2.4.12/built/bin
$ ./ffmpeg.exe
ffmpeg version 2.4.12 Copyright (c) 2000-2015 the FFmpeg developers
  built on Jan 22 2016 05:35:45 with gcc 4.8.1 (GCC)
  configuration: --enable-memalign-hack --arch=x86 --target-os=mingw32 --cross-p
refix= --prefix=/home/Gaiger/ffmpeg/2.4.12/built --enable-cross-compile --enable
-w32threads
  libavutil      54.  7.100 / 54.  7.100
  libavcodec     56.  1.100 / 56.  1.100
  libavformat    56.  4.101 / 56.  4.101
  libavdevice    56.  0.100 / 56.  0.100
  libavfilter     5.  1.100 /  5.  1.100
  libswscale      3.  0.100 /  3.  0.100
  libswresample   1.  1.100 /  1.  1.100
Hyper fast Audio and Video encoder
usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfi
le}...

Use -h to get full help or, even better, run 'man ffmpeg'

Gaiger@i5-4570 ~/ffmpeg/2.4.12/built/bin
$