Example #1
0
/// @brief Subtract and display time difference from clock_elapesed_begin().
///
/// - Notes: Accuracy is a function of timer resolution, CPU overhead and background tasks.
///
/// @param[in] msg: User message to proceed Time display.
///
/// @return  void
/// @see clock_gettime().
/// @see clock_elapesed_begin().
MEMSPACE
void clock_elapsed_end(char *msg)
{
    ts_t current;

    clock_gettime(0, (ts_t *) &current);

    subtract_timespec((ts_t *) &current, (ts_t *) &__clock_elapsed);

    if(msg && *msg)
        printf("[%s Time:%s]\n", msg, ts_to_str((ts_t *) &current) );
    else
        printf("[Time:%s]\n", ts_to_str((ts_t *) &current) );
}
Example #2
0
void *process_stream (void *args_) {
    // puts("_");
    Thread_param *params = (Thread_param *) args_;

    if (params->delay_ms) {
        assert(params->delay_ms >= 0 && params->delay_ms <= 999);
        // fprinttfn(stderr, "gonna sleep %ims", params->delay_ms);
        timespec_ sleep_time;
        sleep_time.tv_sec = 0;
        sleep_time.tv_nsec = params->delay_ms * 1000000;
        assert(! nanosleep(&sleep_time, NULL));
    }

    fprinttfn(stdout, "@starting_thread %i", params->id);

    // timespec_ start_time;
    // assert(clock_gettime(CLOCK_MONOTONIC, &start_time) == 0);

    AVFormatContext *av_context = NULL;
    // puts("((");
    // fprintf(stderr, "str: %s\n", params->rtmp_string);
    // puts("))");
    // pthread_mutex_lock(&mt);
    // puts("1");
    int err = avformat_open_input(&av_context, params->rtmp_string, NULL, NULL); 
    // puts("2");
    // pthread_mutex_unlock(&mt);
    if (err != 0) {
        av_strerror(err, errbuf, ERRBUF_SZ);
        // fprintf(stderr, "avformat_open_input() failed: %s\n", errbuf);
        fprinttfn(stdout, "@error avformat_open_input() fail: %s", errbuf);
        // exit(EXIT_FAILURE);

        //TODO review
        fprinttfn(stdout, "@stopping_thread failed to open stream");
        // avformat_close_input(&av_context);
        pthread_exit(NULL);
    }

    //***NetStream.Timestamp shows in log here already

    //*** it reads several frames
    // pthread_mutex_lock(&mt);
    err = avformat_find_stream_info(av_context, NULL);
    // pthread_mutex_unlock(&mt);
    if (err < 0) {
        av_strerror(err, errbuf, ERRBUF_SZ);
        fprintf(stderr, "avformat_find_stream_info() failed: %s\n", errbuf);
        exit(EXIT_FAILURE);
    }

    /* Dump information about file onto standard error */
    // av_dump_format(av_context, 0, "t.flv", false);

    int videoStream = get_stream_index(av_context);


    // int buffered_frame_num = 0;
    bool is_first_frame = true;
    counter_thread_param_t cparam;

    AVPacket packet;
    av_init_packet(&packet);

    // timespec_ start_time;
    // assert(clock_gettime(CLOCK_MONOTONIC, &start_time) == 0);

    /*
    So we read the frames, accumulate the numbers and check passed time. When N seconds has passed, we subtract
    FPS * N from accumulated frame number implying a "player" consumes FPS and there should be >= FPS frames in buffer each second
    */

    

    //"For video, the packet contains exactly one frame"
    //"This function returns what is stored in the file, and does not validate that what is there are valid frames for the decoder.
    //It will split what is stored in the file into frames and return one for each call.
    //It will not omit invalid data between valid frames so as to give the decoder the maximum information possible for decoding"
    while ((err = av_read_frame(av_context, &packet)) == 0) {
        if (packet.stream_index == videoStream) {
            if (is_first_frame) {
                is_first_frame = false;

                timespec_ first_frame_time = get_time();
                timespec_ first_frame_latency = subtract_timespec(first_frame_time, connected_time);
                fprinttfn(stdout, "@first_frame %ld %ld", first_frame_latency.tv_sec, first_frame_latency.tv_nsec);

                // if (params->is_live && (! got_timestamp)) {
                //     fprinttfn(stdout, "@error not_live");
                // }


                pthread_t thr;
                pthread_mutex_init(&(cparam.mutex), NULL);
                cparam.frame_num = 0;
                cparam.should_stop = false;
                pthread_attr_t attributes;
                pthread_attr_init(&attributes);
                pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED);
                int r = pthread_create(&thr, &attributes, track_fps, (void *) &cparam);
                if (r) {
                    fprintf(stderr, "failed to create track_fps thread: %i\n", r);
                    exit(EXIT_FAILURE);
                }
                assert(pthread_attr_destroy(&attributes) == 0);
            }

            // timespec_ cur_time;
            // assert(clock_gettime(CLOCK_MONOTONIC, &cur_time) == 0);
            // timespec_ time_passed = subtract_timespec(cur_time, start_time);

            // fprinttfn(stdout, "@frame");
            
            pthread_mutex_lock(&(cparam.mutex));
            cparam.frame_num++;
            pthread_mutex_unlock(&(cparam.mutex));
            // buffered_frame_num++;

            // if (time_passed.tv_sec > 0) {
            //     buffered_frame_num -= time_passed.tv_sec * FPS;
            //     //TODO !!! time_passed.tv_nsec

            //     // fprinttfn(stdout, "@buffered_frame_num %i", buffered_frame_num);

            //     start_time = cur_time;

            //     // if (buffered_frame_num < 0) {
            //     //     fprinttfn(stdout, "@underrun %i", buffered_frame_num);
            //     // }
            // }
        }

        av_free_packet(&packet);
        // av_init_packet(&packet); //? -- there's no call in http://libav.org/doxygen/master/pktdumper_8c_source.html but there is in some snippets
    }

    av_strerror(err, errbuf, ERRBUF_SZ);

    pthread_mutex_lock(&(cparam.mutex));
    cparam.should_stop = true;
    pthread_mutex_unlock(&(cparam.mutex));

    fprinttfn(stdout, "@stopping_thread %s", errbuf);  //timeout in rtmp string leads to "End of file"

    avformat_close_input(&av_context);

    pthread_exit(NULL);
}