LCOV - code coverage report
Current view: top level - home/magsoft/trunks/SVT-AV1/Source/App/EncApp - EbAppMain.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 108 171 63.2 %
Date: 2019-11-25 17:38:06 Functions: 1 3 33.3 %

          Line data    Source code
       1             : /*
       2             : * Copyright(c) 2019 Intel Corporation
       3             : * SPDX - License - Identifier: BSD - 2 - Clause - Patent
       4             : */
       5             : 
       6             : // main.cpp
       7             : //  -Contructs the following resources needed during the encoding process
       8             : //      -memory
       9             : //      -threads
      10             : //      -semaphores
      11             : //      -semaphores
      12             : //  -Configures the encoder
      13             : //  -Calls the encoder via the API
      14             : //  -Destructs the resources
      15             : 
      16             : /***************************************
      17             :  * Includes
      18             :  ***************************************/
      19             : #include <stdio.h>
      20             : #include <stdlib.h>
      21             : #include <signal.h>
      22             : #include <stdint.h>
      23             : #include "EbAppConfig.h"
      24             : #include "EbAppContext.h"
      25             : #include "EbTime.h"
      26             : #ifdef _WIN32
      27             : #include <Windows.h>
      28             : #include <io.h>     /* _setmode() */
      29             : #include <fcntl.h>  /* _O_BINARY */
      30             : #else
      31             : #include <pthread.h>
      32             : #include <semaphore.h>
      33             : #include <time.h>
      34             : #include <errno.h>
      35             : #endif
      36             : 
      37             : /***************************************
      38             :  * External Functions
      39             :  ***************************************/
      40             : extern AppExitConditionType ProcessInputBuffer(
      41             :     EbConfig             *config,
      42             :     EbAppContext         *appCallBack);
      43             : 
      44             : extern AppExitConditionType ProcessOutputReconBuffer(
      45             :     EbConfig             *config,
      46             :     EbAppContext         *appCallBack);
      47             : 
      48             : extern AppExitConditionType ProcessOutputStreamBuffer(
      49             :     EbConfig             *config,
      50             :     EbAppContext         *appCallBack,
      51             :     uint8_t           pic_send_done);
      52             : 
      53             : volatile int32_t keepRunning = 1;
      54             : 
      55           0 : void EventHandler(int32_t dummy) {
      56             :     (void)dummy;
      57           0 :     keepRunning = 0;
      58             : 
      59             :     // restore default signal handler
      60           0 :     signal(SIGINT, SIG_DFL);
      61           0 : }
      62             : 
      63           0 : void AssignAppThreadGroup(uint8_t target_socket) {
      64             : #ifdef _WIN32
      65             :     if (GetActiveProcessorGroupCount() == 2) {
      66             :         GROUP_AFFINITY           group_affinity;
      67             :         GetThreadGroupAffinity(GetCurrentThread(), &group_affinity);
      68             :         group_affinity.Group = target_socket;
      69             :         SetThreadGroupAffinity(GetCurrentThread(), &group_affinity, NULL);
      70             :     }
      71             : #else
      72             :     (void)target_socket;
      73           0 :     return;
      74             : #endif
      75             : }
      76             : 
      77             : double get_psnr(double sse, double max);
      78             : 
      79             : /***************************************
      80             :  * Encoder App Main
      81             :  ***************************************/
      82           2 : int32_t main(int32_t argc, char* argv[])
      83             : {
      84             : #ifdef _WIN32
      85             :     _setmode(_fileno(stdin), _O_BINARY);
      86             :     _setmode(_fileno(stdout), _O_BINARY);
      87             : #endif
      88             :     // GLOBAL VARIABLES
      89           2 :     EbErrorType            return_error = EB_ErrorNone;            // Error Handling
      90           2 :     AppExitConditionType    exitCondition = APP_ExitConditionNone;    // Processing loop exit condition
      91             : 
      92             :     EbErrorType            return_errors[MAX_CHANNEL_NUMBER];          // Error Handling
      93             :     AppExitConditionType    exitConditions[MAX_CHANNEL_NUMBER];          // Processing loop exit condition
      94             :     AppExitConditionType    exitConditionsOutput[MAX_CHANNEL_NUMBER];         // Processing loop exit condition
      95             :     AppExitConditionType    exitConditionsRecon[MAX_CHANNEL_NUMBER];         // Processing loop exit condition
      96             :     AppExitConditionType    exitConditionsInput[MAX_CHANNEL_NUMBER];          // Processing loop exit condition
      97             : 
      98             :     EbBool                 channelActive[MAX_CHANNEL_NUMBER];
      99             : 
     100             :     EbConfig             *configs[MAX_CHANNEL_NUMBER];        // Encoder Configuration
     101             : 
     102           2 :     uint32_t                num_channels = 0;
     103           2 :     uint32_t                instanceCount=0;
     104             :     EbAppContext         *appCallbacks[MAX_CHANNEL_NUMBER];   // Instances App callback data
     105           2 :     signal(SIGINT, EventHandler);
     106           2 :     printf("-------------------------------------------\n");
     107           2 :     printf("SVT-AV1 Encoder\n");
     108           2 :     if (!get_help(argc, argv)) {
     109             :         // Get num_channels
     110           2 :         num_channels = get_number_of_channels(argc, argv);
     111           2 :         if (num_channels == 0)
     112           0 :             return EB_ErrorBadParameter;
     113             :         // Initialize config
     114           4 :         for (instanceCount = 0; instanceCount < num_channels; ++instanceCount) {
     115           2 :             configs[instanceCount] = (EbConfig*)malloc(sizeof(EbConfig));
     116           2 :             if (!configs[instanceCount]) {
     117           0 :                 while(instanceCount-- > 0)
     118           0 :                     free(configs[instanceCount]);
     119           0 :                 return EB_ErrorInsufficientResources;
     120             :             }
     121           2 :             eb_config_ctor(configs[instanceCount]);
     122           2 :             return_errors[instanceCount] = EB_ErrorNone;
     123             :         }
     124             : 
     125             :         // Initialize appCallback
     126           4 :         for (instanceCount = 0; instanceCount < num_channels; ++instanceCount) {
     127           2 :             appCallbacks[instanceCount] = (EbAppContext*)malloc(sizeof(EbAppContext));
     128           2 :             if (!appCallbacks[instanceCount]) {
     129           0 :                 while(instanceCount-- > 0)
     130           0 :                     free(appCallbacks[instanceCount]);
     131           0 :                 return EB_ErrorInsufficientResources;
     132             :             }
     133             :         }
     134             : 
     135          14 :         for (instanceCount = 0; instanceCount < MAX_CHANNEL_NUMBER; ++instanceCount) {
     136          12 :             exitConditions[instanceCount] = APP_ExitConditionError;         // Processing loop exit condition
     137          12 :             exitConditionsOutput[instanceCount] = APP_ExitConditionError;         // Processing loop exit condition
     138          12 :             exitConditionsRecon[instanceCount] = APP_ExitConditionError;         // Processing loop exit condition
     139          12 :             exitConditionsInput[instanceCount] = APP_ExitConditionError;         // Processing loop exit condition
     140          12 :             channelActive[instanceCount] = EB_FALSE;
     141             :         }
     142             : 
     143             :         // Read all configuration files.
     144           2 :         return_error = read_command_line(argc, argv, configs, num_channels, return_errors);
     145             : 
     146             :         // Process any command line options, including the configuration file
     147             : 
     148           2 :         if (return_error == EB_ErrorNone) {
     149             :             // Set main thread affinity
     150           2 :             if (configs[0]->target_socket != -1)
     151           0 :                 AssignAppThreadGroup(configs[0]->target_socket);
     152             : 
     153             :             // Init the Encoder
     154           4 :             for (instanceCount = 0; instanceCount < num_channels; ++instanceCount) {
     155           2 :                 if (return_errors[instanceCount] == EB_ErrorNone) {
     156           2 :                     configs[instanceCount]->active_channel_count = num_channels;
     157           2 :                     configs[instanceCount]->channel_id = instanceCount;
     158             : 
     159           2 :                     StartTime((uint64_t*)&configs[instanceCount]->performance_context.lib_start_time[0], (uint64_t*)&configs[instanceCount]->performance_context.lib_start_time[1]);
     160             : 
     161           2 :                     return_errors[instanceCount] = init_encoder(configs[instanceCount], appCallbacks[instanceCount], instanceCount);
     162           2 :                     return_error = (EbErrorType)(return_error | return_errors[instanceCount]);
     163             :                 }
     164             :                 else
     165           0 :                     channelActive[instanceCount] = EB_FALSE;
     166             :             }
     167             : 
     168             :             {
     169             :                 // Start the Encoder
     170           4 :                 for (instanceCount = 0; instanceCount < num_channels; ++instanceCount) {
     171           2 :                     if (return_errors[instanceCount] == EB_ErrorNone) {
     172           2 :                         return_error = (EbErrorType)(return_error & return_errors[instanceCount]);
     173           2 :                         exitConditions[instanceCount]       = APP_ExitConditionNone;
     174           2 :                         exitConditionsOutput[instanceCount] = APP_ExitConditionNone;
     175           2 :                         exitConditionsRecon[instanceCount]  = configs[instanceCount]->recon_file ? APP_ExitConditionNone : APP_ExitConditionError;
     176           2 :                         exitConditionsInput[instanceCount]  = APP_ExitConditionNone;
     177           2 :                         channelActive[instanceCount]        = EB_TRUE;
     178           2 :                         StartTime((uint64_t*)&configs[instanceCount]->performance_context.encode_start_time[0], (uint64_t*)&configs[instanceCount]->performance_context.encode_start_time[1]);
     179             :                     }
     180             :                     else {
     181           0 :                         exitConditions[instanceCount]       = APP_ExitConditionError;
     182           0 :                         exitConditionsOutput[instanceCount] = APP_ExitConditionError;
     183           0 :                         exitConditionsRecon[instanceCount]  = APP_ExitConditionError;
     184           0 :                         exitConditionsInput[instanceCount]  = APP_ExitConditionError;
     185             :                     }
     186             : 
     187             : #if DISPLAY_MEMORY
     188             :                     EB_APP_MEMORY();
     189             : #endif
     190             :                 }
     191           2 :                 printf("Encoding          ");
     192           2 :                 fflush(stdout);
     193             : 
     194         240 :                 while (exitCondition == APP_ExitConditionNone) {
     195         238 :                     exitCondition = APP_ExitConditionFinished;
     196         476 :                     for (instanceCount = 0; instanceCount < num_channels; ++instanceCount) {
     197         238 :                         if (channelActive[instanceCount] == EB_TRUE) {
     198         238 :                             if (exitConditionsInput[instanceCount] == APP_ExitConditionNone)
     199         120 :                                 exitConditionsInput[instanceCount] = ProcessInputBuffer(
     200             :                                                                             configs[instanceCount],
     201             :                                                                             appCallbacks[instanceCount]);
     202         238 :                             if (exitConditionsRecon[instanceCount] == APP_ExitConditionNone)
     203           0 :                                 exitConditionsRecon[instanceCount] = ProcessOutputReconBuffer(
     204             :                                                                             configs[instanceCount],
     205             :                                                                             appCallbacks[instanceCount]);
     206         238 :                             if (exitConditionsOutput[instanceCount] == APP_ExitConditionNone)
     207         238 :                                 exitConditionsOutput[instanceCount] = ProcessOutputStreamBuffer(
     208             :                                                                             configs[instanceCount],
     209             :                                                                             appCallbacks[instanceCount],
     210         238 :                                                                             (exitConditionsInput[instanceCount] == APP_ExitConditionNone) || (exitConditionsRecon[instanceCount] == APP_ExitConditionNone)? 0 : 1);
     211         238 :                             if (((exitConditionsRecon[instanceCount] == APP_ExitConditionFinished || !configs[instanceCount]->recon_file)  && exitConditionsOutput[instanceCount] == APP_ExitConditionFinished && exitConditionsInput[instanceCount] == APP_ExitConditionFinished)||
     212         236 :                                 ((exitConditionsRecon[instanceCount] == APP_ExitConditionError && configs[instanceCount]->recon_file) || exitConditionsOutput[instanceCount] == APP_ExitConditionError || exitConditionsInput[instanceCount] == APP_ExitConditionError)){
     213           2 :                                 channelActive[instanceCount] = EB_FALSE;
     214           2 :                                 if (configs[instanceCount]->recon_file)
     215           0 :                                     exitConditions[instanceCount] = (AppExitConditionType)(exitConditionsRecon[instanceCount] | exitConditionsOutput[instanceCount] | exitConditionsInput[instanceCount]);
     216             :                                 else
     217           2 :                                     exitConditions[instanceCount] = (AppExitConditionType)(exitConditionsOutput[instanceCount] | exitConditionsInput[instanceCount]);
     218             :                             }
     219             :                         }
     220             :                     }
     221             :                     // check if all channels are inactive
     222         476 :                     for (instanceCount = 0; instanceCount < num_channels; ++instanceCount) {
     223         238 :                         if (channelActive[instanceCount] == EB_TRUE)
     224         236 :                             exitCondition = APP_ExitConditionNone;
     225             :                     }
     226             :                 }
     227             : 
     228           4 :                 for (instanceCount = 0; instanceCount < num_channels; ++instanceCount) {
     229           2 :                     if (exitConditions[instanceCount] == APP_ExitConditionFinished && return_errors[instanceCount] == EB_ErrorNone) {
     230             :                         double      frame_rate;
     231           2 :                         uint64_t    frame_count = (uint32_t)configs[instanceCount]->performance_context.frame_count;
     232           2 :                         uint32_t    max_luma_value = (configs[instanceCount]->encoder_bit_depth == 8) ? 255 : 1023;
     233           2 :                         double      max_luma_sse = (double)max_luma_value*max_luma_value *
     234           2 :                                     (configs[instanceCount]->source_width*configs[instanceCount]->source_height);
     235           2 :                         double      max_chroma_sse = (double)max_luma_value*max_luma_value *
     236           2 :                             (configs[instanceCount]->source_width/2*configs[instanceCount]->source_height/2);
     237             : 
     238           2 :                         if ((configs[instanceCount]->frame_rate_numerator != 0 && configs[instanceCount]->frame_rate_denominator != 0) || configs[instanceCount]->frame_rate != 0) {
     239           2 :                             if (configs[instanceCount]->frame_rate_numerator && configs[instanceCount]->frame_rate_denominator && (configs[instanceCount]->frame_rate_numerator != 0 && configs[instanceCount]->frame_rate_denominator != 0))
     240           2 :                                 frame_rate = ((double)configs[instanceCount]->frame_rate_numerator) / ((double)configs[instanceCount]->frame_rate_denominator);
     241           0 :                             else if (configs[instanceCount]->frame_rate > 1000) {
     242             :                                 // Correct for 16-bit fixed-point fractional precision
     243           0 :                                 frame_rate = ((double)configs[instanceCount]->frame_rate) / (1 << 16);
     244             :                             }
     245             :                             else
     246           0 :                                 frame_rate = (double)configs[instanceCount]->frame_rate;
     247             : 
     248           2 :                             if (configs[instanceCount]->stat_report) {
     249           0 :                                 if (configs[instanceCount]->stat_file) {
     250           0 :                                     fprintf(configs[instanceCount]->stat_file, "\nSUMMARY ---------------------------------------------------------------------\n");
     251             : 
     252             :                                     // Interlaced Video
     253           0 :                                     if (configs[instanceCount]->interlaced_video || configs[instanceCount]->separate_fields)
     254           0 :                                         fprintf(configs[instanceCount]->stat_file, "Total Fields\tAverage QP  \tY-PSNR   \tU-PSNR   \tV-PSNR   \tBitrate\n");
     255             :                                     else {
     256           0 :                                         fprintf(configs[instanceCount]->stat_file, "\n\t\t\t\t\t\t\tAverage PSNR (using per-frame PSNR)\t\t|\tOverall PSNR (using per-frame MSE)\n");
     257           0 :                                         fprintf(configs[instanceCount]->stat_file, "Total Frames\tAverage QP  \tY-PSNR   \tU-PSNR   \tV-PSNR\t\t| \tY-PSNR   \tU-PSNR   \tV-PSNR   \t|\tBitrate\n");
     258             :                                     }
     259           0 :                                     fprintf(configs[instanceCount]->stat_file, "%10ld  \t   %2.2f    \t%3.2f dB\t%3.2f dB\t%3.2f dB  \t|\t%3.2f dB\t%3.2f dB\t%3.2f dB \t|\t%.2f kbps\n",
     260             :                                          (long int)frame_count,
     261           0 :                                          (float)configs[instanceCount]->performance_context.sum_qp        / frame_count,
     262           0 :                                          (float)configs[instanceCount]->performance_context.sum_luma_psnr / frame_count,
     263           0 :                                          (float)configs[instanceCount]->performance_context.sum_cb_psnr   / frame_count,
     264           0 :                                          (float)configs[instanceCount]->performance_context.sum_cr_psnr   / frame_count,
     265           0 :                                          (float)(get_psnr((configs[instanceCount]->performance_context.sum_luma_sse  / frame_count) , max_luma_sse)),
     266           0 :                                          (float)(get_psnr((configs[instanceCount]->performance_context.sum_cb_sse    / frame_count) , max_chroma_sse)),
     267           0 :                                          (float)(get_psnr((configs[instanceCount]->performance_context.sum_cr_sse    / frame_count) , max_chroma_sse)),
     268           0 :                                         ((double)(configs[instanceCount]->performance_context.byte_count << 3) * frame_rate / (configs[instanceCount]->frames_encoded * 1000)));
     269             :                                 }
     270             :                             }
     271             : 
     272           2 :                             printf("\nSUMMARY --------------------------------- Channel %u  --------------------------------\n", instanceCount + 1);
     273             :                             {
     274           2 :                                 if (configs[instanceCount]->interlaced_video || configs[instanceCount]->separate_fields)
     275           0 :                                     printf("Total Fields\t\tFrame Rate\t\tByte Count\t\tBitrate\n");
     276             :                                 else
     277           2 :                                     printf("Total Frames\t\tFrame Rate\t\tByte Count\t\tBitrate\n");
     278           2 :                                 printf("%12d\t\t%4.2f fps\t\t%10.0f\t\t%5.2f kbps\n",
     279             :                                     (int32_t)frame_count,
     280             :                                     (double)frame_rate,
     281           2 :                                     (double)configs[instanceCount]->performance_context.byte_count,
     282           2 :                                     ((double)(configs[instanceCount]->performance_context.byte_count << 3) * frame_rate / (configs[instanceCount]->frames_encoded * 1000)));
     283             :                             }
     284             : 
     285           2 :                             if (configs[instanceCount]->stat_report) {
     286           0 :                                 printf("\n\t\t\t\tAverage PSNR (using per-frame PSNR)\t\t\t|\t\tOverall PSNR (using per-frame MSE)\n");
     287           0 :                                 printf("Average QP\t\tY-PSNR\t\t\tU-PSNR\t\t\tV-PSNR\t\t|\tY-PSNR\t\t\tU-PSNR\t\t\tV-PSNR\t\n");
     288           0 :                                 printf("%11.2f\t\t%4.2f dB\t\t%4.2f dB\t\t%4.2f dB\t|\t%4.2f dB\t\t%4.2f dB\t\t%4.2f dB\n",
     289           0 :                                     (float)configs[instanceCount]->performance_context.sum_qp / frame_count,
     290           0 :                                     (float)configs[instanceCount]->performance_context.sum_luma_psnr / frame_count,
     291           0 :                                     (float)configs[instanceCount]->performance_context.sum_cb_psnr / frame_count,
     292           0 :                                     (float)configs[instanceCount]->performance_context.sum_cr_psnr / frame_count,
     293           0 :                                     (float)(get_psnr((configs[instanceCount]->performance_context.sum_luma_sse / frame_count), max_luma_sse)),
     294           0 :                                     (float)(get_psnr((configs[instanceCount]->performance_context.sum_cb_sse / frame_count), max_chroma_sse)),
     295           0 :                                     (float)(get_psnr((configs[instanceCount]->performance_context.sum_cr_sse / frame_count), max_chroma_sse)));
     296             :                             }
     297             : 
     298           2 :                             fflush(stdout);
     299             :                         }
     300             :                     }
     301             :                 }
     302           2 :                 printf("\n");
     303           2 :                 fflush(stdout);
     304             :             }
     305           4 :             for (instanceCount = 0; instanceCount < num_channels; ++instanceCount) {
     306           2 :                 if (exitConditions[instanceCount] == APP_ExitConditionFinished && return_errors[instanceCount] == EB_ErrorNone) {
     307           2 :                     if (configs[instanceCount]->stop_encoder == EB_FALSE) {
     308             :                         // Interlaced Video
     309           2 :                         if (configs[instanceCount]->interlaced_video || configs[instanceCount]->separate_fields) {
     310           0 :                             printf("\nChannel %u\nAverage Speed:\t\t%.0f fields per sec\nTotal Encoding Time:\t\t%.0f ms\nTotal Execution Time:\t\t%.2f ms\nAverage Latency:\t%.0f ms\nMax Latency:\t\t%u ms\n",
     311           0 :                                 (uint32_t)(instanceCount + 1),
     312           0 :                                 configs[instanceCount]->performance_context.average_speed,
     313           0 :                                 configs[instanceCount]->performance_context.total_encode_time * 1000,
     314           0 :                                 configs[instanceCount]->performance_context.total_execution_time * 1000,
     315           0 :                                 configs[instanceCount]->performance_context.average_latency,
     316           0 :                                 (uint32_t)(configs[instanceCount]->performance_context.max_latency));
     317             :                         }
     318             :                         else {
     319           2 :                             printf("\nChannel %u\nAverage Speed:\t\t%.3f fps\nTotal Encoding Time:\t%.0f ms\nTotal Execution Time:\t%.0f ms\nAverage Latency:\t%.0f ms\nMax Latency:\t\t%u ms\n",
     320           2 :                                 (uint32_t)(instanceCount + 1),
     321           2 :                                 configs[instanceCount]->performance_context.average_speed,
     322           2 :                                 configs[instanceCount]->performance_context.total_encode_time * 1000,
     323           2 :                                 configs[instanceCount]->performance_context.total_execution_time * 1000,
     324           2 :                                 configs[instanceCount]->performance_context.average_latency,
     325           2 :                                 (uint32_t)(configs[instanceCount]->performance_context.max_latency));
     326             :                         }
     327             :                     }
     328             :                     else
     329           0 :                         printf("\nChannel %u Encoding Interrupted\n", (uint32_t)(instanceCount + 1));
     330             :                 }
     331           0 :                 else if (return_errors[instanceCount] == EB_ErrorInsufficientResources)
     332           0 :                     printf("Could not allocate enough memory for channel %u\n", instanceCount + 1);
     333             :                 else
     334           0 :                     printf("Error encoding at channel %u! Check error log file for more details ... \n", instanceCount + 1);
     335             :             }
     336             :             // DeInit Encoder
     337           4 :             for (instanceCount = num_channels; instanceCount > 0; --instanceCount) {
     338           2 :                 if (return_errors[instanceCount - 1] == EB_ErrorNone)
     339           2 :                     return_errors[instanceCount - 1] = de_init_encoder(appCallbacks[instanceCount - 1], instanceCount - 1);
     340             :             }
     341             :         }
     342             :         else {
     343           0 :             printf("Error in configuration, could not begin encoding! ... \n");
     344           0 :             printf("Run %s -help for a list of options\n", argv[0]);
     345             :         }
     346             :         // Destruct the App memory variables
     347           4 :         for (instanceCount = 0; instanceCount < num_channels; ++instanceCount) {
     348           2 :             eb_config_dtor(configs[instanceCount]);
     349           2 :             if (configs[instanceCount])
     350           2 :                 free(configs[instanceCount]);
     351           2 :             if (appCallbacks[instanceCount])
     352           2 :                 free(appCallbacks[instanceCount]);
     353             :         }
     354             : 
     355           2 :         printf("Encoder finished\n");
     356             :     }
     357             : 
     358           2 :     return (return_error == 0) ? 0 : 1;
     359             : }

Generated by: LCOV version 1.14