ssize_t SDL_AMediaCodec_FakeFifo_dequeueOutputBuffer(SDL_AMediaCodec_FakeFifo *fifo, SDL_AMediaCodecBufferInfo *info, int64_t timeoutUs)
{
    if (fifo->should_abort)
        return -1;

    int64_t  timeoutMs  = (timeoutUs + 999) / 1000;    
    ssize_t  dequeue_ret = -1;
    uint64_t wait_start = SDL_GetTickHR();
    int64_t  to_wait    = timeoutMs;

    SDL_LockMutex(fifo->mutex);
    while (!fifo->should_abort) {
        if (fifo->size > 0) {
            SDL_AMediaCodec_FakeFrame *fake = &fifo->fakes[fifo->begin];
            *info        = fake->info;
            info->flags |= AMEDIACODEC__BUFFER_FLAG_FAKE_FRAME;
            dequeue_ret  = fake->index;

            FAK_TRACE("%s, [%d]%lld", __func__, fifo->begin, info->presentationTimeUs);

            fifo->begin = (fifo->begin + 1) % FAKE_BUFFER_QUEUE_SIZE;
            fifo->size--;
            SDL_CondSignal(fifo->wakeup_enqueue_cond);
            break;
        }

        SDL_CondWaitTimeout(fifo->wakeup_dequeue_cond, fifo->mutex, to_wait);
        if (to_wait >= 0) {
            uint64_t now = SDL_GetTickHR();
            if (now < wait_start) {
                // tick overflow
                dequeue_ret = -1;
                break;
            } else {
                uint64_t elapsed = now - wait_start;
                if (elapsed >= timeoutMs) {
                    // timeout
                    dequeue_ret = -1;
                    break;
                } else {
                    to_wait = timeoutMs - elapsed;
                }
            }
        }
    }
    SDL_UnlockMutex(fifo->mutex);

    if (fifo->should_abort)
        return -1;

    return dequeue_ret;
}
Ejemplo n.º 2
0
int64_t SDL_ProfilerEnd(SDL_Profiler* profiler)
{
    int64_t delta = SDL_GetTickHR() - profiler->begin_time;

    if (profiler->max_sample > 0) {
        profiler->total_elapsed += delta;
        profiler->total_counter += 1;

        profiler->sample_elapsed += delta;
        profiler->sample_counter  += 1;

        if (profiler->sample_counter > profiler->max_sample) {
            profiler->sample_elapsed -= profiler->average_elapsed;
            profiler->sample_counter -= 1;
        }

        if (profiler->sample_counter > 0) {
            profiler->average_elapsed = profiler->sample_elapsed / profiler->sample_counter;
        }
        if (profiler->sample_elapsed > 0) {
            profiler->sample_per_seconds = profiler->sample_counter * 1000.f / profiler->sample_elapsed;
        }
    }

    return delta;
}
Ejemplo n.º 3
0
float SDL_SpeedSamplerAdd(SDL_SpeedSampler *sampler, int enable_log, const char *log_tag)
{
    Uint64 current = SDL_GetTickHR();
    sampler->samples[sampler->next_index] = current;
    sampler->next_index++;
    sampler->next_index %= sampler->capacity;
    if (sampler->count + 1 >= sampler->capacity) {
        sampler->first_index++;
        sampler->first_index %= sampler->capacity;
    } else {
        sampler->count++;
    }

    if (sampler->count < 2)
        return 0;

    float samples_per_second = 1000.0f * (sampler->count - 1) / (current - sampler->samples[sampler->first_index]);

    if (enable_log && (sampler->last_log_time + 1000 < current || sampler->last_log_time > current)) {
        sampler->last_log_time = current;
        ALOGW("%s: %.2f\n", log_tag ? log_tag : "N/A", samples_per_second);
    }

    return samples_per_second;
}
static int drain_output_buffer_l(JNIEnv *env, IJKFF_Pipenode *node, int64_t timeUs, int *dequeue_count)
{
    IJKFF_Pipenode_Opaque *opaque   = node->opaque;
    FFPlayer              *ffp      = opaque->ffp;
    int                    ret      = 0;
    SDL_AMediaCodecBufferInfo bufferInfo;
    ssize_t                   output_buffer_index = 0;

    if (dequeue_count)
        *dequeue_count = 0;

    if (JNI_OK != SDL_JNI_SetupThreadEnv(&env)) {
        ALOGE("%s:create: SetupThreadEnv failed\n", __func__);
        return -1;
    }

    output_buffer_index = SDL_AMediaCodec_dequeueOutputBuffer(opaque->acodec, &bufferInfo, timeUs);
    if (output_buffer_index == AMEDIACODEC__INFO_OUTPUT_BUFFERS_CHANGED) {
        ALOGI("AMEDIACODEC__INFO_OUTPUT_BUFFERS_CHANGED\n");
        // continue;
    } else if (output_buffer_index == AMEDIACODEC__INFO_OUTPUT_FORMAT_CHANGED) {
        ALOGI("AMEDIACODEC__INFO_OUTPUT_FORMAT_CHANGED\n");
        SDL_AMediaFormat_deleteP(&opaque->output_aformat);
        opaque->output_aformat = SDL_AMediaCodec_getOutputFormat(opaque->acodec);
        if (opaque->output_aformat) {
            int width        = 0;
            int height       = 0;
            int color_format = 0;
            int stride       = 0;
            int slice_height = 0;
            int crop_left    = 0;
            int crop_top     = 0;
            int crop_right   = 0;
            int crop_bottom  = 0;

            SDL_AMediaFormat_getInt32(opaque->output_aformat, "width",          &width);
            SDL_AMediaFormat_getInt32(opaque->output_aformat, "height",         &height);
            SDL_AMediaFormat_getInt32(opaque->output_aformat, "color-format",   &color_format);

            SDL_AMediaFormat_getInt32(opaque->output_aformat, "stride",         &stride);
            SDL_AMediaFormat_getInt32(opaque->output_aformat, "slice-height",   &slice_height);
            SDL_AMediaFormat_getInt32(opaque->output_aformat, "crop-left",      &crop_left);
            SDL_AMediaFormat_getInt32(opaque->output_aformat, "crop-top",       &crop_top);
            SDL_AMediaFormat_getInt32(opaque->output_aformat, "crop-right",     &crop_right);
            SDL_AMediaFormat_getInt32(opaque->output_aformat, "crop-bottom",    &crop_bottom);

            // TI decoder could crash after reconfigure
            // ffp_notify_msg3(ffp, FFP_MSG_VIDEO_SIZE_CHANGED, width, height);
            // opaque->frame_width  = width;
            // opaque->frame_height = height;
            ALOGI(
                "AMEDIACODEC__INFO_OUTPUT_FORMAT_CHANGED\n"
                "    width-height: (%d x %d)\n"
                "    color-format: (%s: 0x%x)\n"
                "    stride:       (%d)\n"
                "    slice-height: (%d)\n"
                "    crop:         (%d, %d, %d, %d)\n"
                ,
                width, height,
                SDL_AMediaCodec_getColorFormatName(color_format), color_format,
                stride,
                slice_height,
                crop_left, crop_top, crop_right, crop_bottom);
        }
        // continue;
    } else if (output_buffer_index == AMEDIACODEC__INFO_TRY_AGAIN_LATER) {
        AMCTRACE("AMEDIACODEC__INFO_TRY_AGAIN_LATER\n");
        // continue;
    } else if (output_buffer_index < 0) {
        // enqueue packet as a fake picture
        PacketQueue *fake_q = &opaque->fake_pictq;
        SDL_LockMutex(fake_q->mutex);
        if (!fake_q->abort_request && fake_q->nb_packets <= 0) {
            SDL_CondWaitTimeout(fake_q->cond, fake_q->mutex, 1000);
        }
        SDL_UnlockMutex(fake_q->mutex);

        if (fake_q->abort_request) {
            ret = -1;
            goto fail;
        } else {
            AVPacket pkt;
            int dequeue_ret = ffp_packet_queue_get(&opaque->fake_pictq, &pkt, 0, &opaque->fake_pictq_serial);
            if (dequeue_ret < 0) {
                ret = -1;
                goto fail;
            } else if (dequeue_ret > 0) {
                if (!ffp_is_flush_packet(&pkt)) {
                    if (dequeue_count)
                        ++*dequeue_count;

                    ret = amc_queue_picture_fake(node, &pkt);
                    av_free_packet(&pkt);
                }
                ret = 0;
                goto fail;
            }
        }
    } else if (output_buffer_index >= 0) {
        ffp->vdps = SDL_SpeedSamplerAdd(&opaque->sampler, FFP_SHOW_VDPS_MEDIACODEC, "vdps[MediaCodec]");

        if (dequeue_count)
            ++*dequeue_count;

#ifdef FFP_SHOW_AMC_VDPS
        {
            if (opaque->benchmark_start_time == 0) {
                opaque->benchmark_start_time   = SDL_GetTickHR();
            }
            opaque->benchmark_frame_count += 1;
            if (0 == (opaque->benchmark_frame_count % 240)) {
                Uint64 diff = SDL_GetTickHR() - opaque->benchmark_start_time;
                double per_frame_ms = ((double) diff) / opaque->benchmark_frame_count;
                double fps          = ((double) opaque->benchmark_frame_count) * 1000 / diff;
                ALOGE("%lf fps, %lf ms/frame, %"PRIu64" frames\n",
                      fps, per_frame_ms, opaque->benchmark_frame_count);
            }
        }
#endif
#ifdef FFP_AMC_DISABLE_OUTPUT
        SDL_AMediaCodec_releaseOutputBuffer(opaque->acodec, output_buffer_index, false);
        goto done;
#endif

        if (opaque->n_buf_out) {
            AMC_Buf_Out *buf_out;

            if (opaque->off_buf_out < opaque->n_buf_out) {
                // ALOGD("filling buffer... %d", opaque->off_buf_out);
                buf_out = &opaque->amc_buf_out[opaque->off_buf_out++];
                buf_out->port = output_buffer_index;
                buf_out->info = bufferInfo;
                buf_out->pts = pts_from_buffer_info(node, &bufferInfo);
                sort_amc_buf_out(opaque->amc_buf_out, opaque->off_buf_out);
            } else {
                double pts;

                pts = pts_from_buffer_info(node, &bufferInfo);
                if (opaque->last_queued_pts != AV_NOPTS_VALUE &&
                    pts < opaque->last_queued_pts) {
                    // ALOGE("early picture, drop!");
                    SDL_AMediaCodec_releaseOutputBuffer(opaque->acodec, output_buffer_index, false);
                    goto done;
                }
                /* already sorted */
                buf_out = &opaque->amc_buf_out[opaque->off_buf_out - 1];
                /* new picture is the most aged, send now */
                if (pts < buf_out->pts) {
                    ret = amc_queue_picture_buffer(node, output_buffer_index, &bufferInfo);
                    opaque->last_queued_pts = pts;
                    // ALOGD("pts = %f", pts);
                } else {
                    int i;

                    /* find one to send */
                    for (i = opaque->off_buf_out - 1; i >= 0; i--) {
                        buf_out = &opaque->amc_buf_out[i];
                        if (pts > buf_out->pts) {
                            ret = amc_queue_picture_buffer(node, buf_out->port, &buf_out->info);
                            opaque->last_queued_pts = buf_out->pts;
                            // ALOGD("pts = %f", buf_out->pts);
                            /* replace for sort later */
                            buf_out->port = output_buffer_index;
                            buf_out->info = bufferInfo;
                            buf_out->pts = pts_from_buffer_info(node, &bufferInfo);
                            sort_amc_buf_out(opaque->amc_buf_out, opaque->n_buf_out);
                            break;
                        }
                    }
                    /* need to discard current buffer */
                    if (i < 0) {
                        // ALOGE("buffer too small, drop picture!");
                        SDL_AMediaCodec_releaseOutputBuffer(opaque->acodec, output_buffer_index, false);
                        goto done;
                    }
                }
            }
        } else {
            ret = amc_queue_picture_buffer(node, output_buffer_index, &bufferInfo);
        }
    }

done:
    ret = 0;
fail:
    return ret;
}
// like ff_ffplay.c: queue_picture()
static int amc_queue_picture(
    IJKFF_Pipenode            *node,
    SDL_AMediaCodec           *acodec,
    int                        output_buffer_index,
    SDL_AMediaCodecBufferInfo *buffer_info,
    double                     pts,
    double                     duration,
    int64_t                    pos,
    int                        serial)
{
    IJKFF_Pipenode_Opaque *opaque = node->opaque;
    FFPlayer              *ffp    = opaque->ffp;
    VideoState            *is     = ffp->is;
    Frame                 *vp;

#if defined(DEBUG_SYNC) && 0
    printf("frame_type=%c pts=%0.3f\n",
           av_get_picture_type_char(src_frame->pict_type), pts);
#endif

    if (!(vp = ffp_frame_queue_peek_writable(&is->pictq)))
        return -1;

    vp->sar.num = 1;
    vp->sar.den = 1;

    /* alloc or resize hardware picture buffer */
    if (!vp->bmp || vp->reallocate || !vp->allocated ||
        vp->width  != opaque->frame_width ||
        vp->height != opaque->frame_height ||
        !SDL_VoutOverlayAMediaCodec_isKindOf(vp->bmp)) {

        if (vp->width != opaque->frame_width || vp->height != opaque->frame_height)
            ffp_notify_msg3(ffp, FFP_MSG_VIDEO_SIZE_CHANGED, opaque->frame_width, opaque->frame_height);

        vp->allocated  = 0;
        vp->reallocate = 0;
        vp->width      = opaque->frame_width;
        vp->height     = opaque->frame_height;

        /* the allocation must be done in the main thread to avoid
           locking problems. */
        amc_alloc_picture(ffp);

        if (is->videoq.abort_request)
            return -1;
    }

    /* if the frame is not skipped, then display it */
    if (vp->bmp) {
        /* get a pointer on the bitmap */
        SDL_VoutLockYUVOverlay(vp->bmp);

        /* get a pointer on the bitmap */
        if (SDL_VoutOverlayAMediaCodec_attachFrame(vp->bmp, opaque->acodec, output_buffer_index) < 0) {
            av_log(NULL, AV_LOG_FATAL, "Cannot initialize the conversion context\n");
            exit(1);
        }
        /* update the bitmap content */
        SDL_VoutUnlockYUVOverlay(vp->bmp);

        vp->pts = pts;
        vp->duration = duration;
        vp->pos = pos;
        vp->serial = serial;
        // ALOGE("vp %lf, %lf, %d, %d", pts, duration, (int)pos, (int)serial);

        /* now we can update the picture count */
        ffp_frame_queue_push(&is->pictq);

        if (!is->viddec.first_frame_decoded) {
            ALOGD("MediaCodec/Video: first frame decoded\n");
            is->viddec.first_frame_decoded_time = SDL_GetTickHR();
            is->viddec.first_frame_decoded = 1;
        }
    }
    return 0;
}
Ejemplo n.º 6
0
void SDL_ProfilerBegin(SDL_Profiler* profiler)
{
    profiler->begin_time = SDL_GetTickHR();
}