示例#1
0
static int demuxer_ffmpeg_read_frame (demuxer_wrapper_t * wrapper, dt_av_frame_t * frame)
{
    dtdemuxer_context_t *dem_ctx = (dtdemuxer_context_t *) wrapper->parent;
    dt_media_info_t *media_info = &dem_ctx->media_info;

    int has_audio = (media_info->no_audio) ? 0 : media_info->has_audio;
    int has_video = (media_info->no_video) ? 0 : media_info->has_video;
    int has_sub = (media_info->no_sub) ? 0 : media_info->has_sub;

    int cur_aidx = (has_audio) ? media_info->astreams[media_info->cur_ast_index]->index : -1;
    int cur_vidx = (has_video) ? media_info->vstreams[media_info->cur_vst_index]->index : -1;
    int cur_sidx = (has_sub) ? media_info->sstreams[media_info->cur_sst_index]->index : -1;

    AVFormatContext *ic = (AVFormatContext *) wrapper->demuxer_priv;
    AVPacket avpkt;
    int ret = av_read_frame (ic, &avpkt);
    if (ret < 0)
    {
        if (AVERROR (EAGAIN) != ret)
        {
            /*if the return is EAGAIN,we need to try more times */
            dt_warning (TAG, "[%s:%d]av_read_frame return (%d)\n", __FUNCTION__, __LINE__, ret);

            if (AVERROR_EOF != ret)
                return DTERROR_READ_FAILED;
            else
                return DTERROR_READ_EOF;
        }
        return DTERROR_READ_AGAIN;
    }
    //read frame ok
    if (has_video && cur_vidx == avpkt.stream_index)
        frame->type = AVMEDIA_TYPE_VIDEO;
    else if (has_audio && cur_aidx == avpkt.stream_index)
        frame->type = AVMEDIA_TYPE_AUDIO;
    else if (has_sub && cur_sidx == avpkt.stream_index)
        frame->type = AVMEDIA_TYPE_SUBTITLE;
    else
    {
        frame->type = AVMEDIA_TYPE_UNKNOWN;
        av_free_packet (&avpkt);
        return DTERROR_READ_AGAIN; // need to read again
    }

    //setup frame
    frame->data = avpkt.data;
    frame->size = avpkt.size;
    frame->pts = pts_exchange (&avpkt, media_info);
    frame->dts = avpkt.dts;
    frame->duration = avpkt.duration;
    dt_debug (TAG, "read ok,frame size:%d %02x %02x %02x %02x addr:%p\n", frame->size, frame->data[0], frame->data[1], frame->data[2], frame->data[3], frame->data);
    dt_debug (TAG, "SIDE_DATA_ELEMENT:%d \n", avpkt.side_data_elems);

    return DTERROR_NONE;
}
static void *audio_decode_loop (void *arg)
{
    int ret;
    dtaudio_decoder_t *decoder = (dtaudio_decoder_t *) arg;
    dtaudio_para_t *para = &decoder->aparam;
    dt_av_frame_t frame;
    ad_wrapper_t *wrapper = decoder->wrapper;
    dtaudio_context_t *actx = (dtaudio_context_t *) decoder->parent;
    dt_buffer_t *out = &actx->audio_decoded_buf;
    int declen, fill_size;
    
    //for some type audio, can not read completly frame 
    uint8_t *frame_data = NULL; // point to frame start
    uint8_t *rest_data = NULL;
    int frame_size = 0;
    int rest_size = 0;

    int used;                   // used size after every decode ops

    adec_ctrl_t *pinfo = &decoder->info;
    memset(pinfo,0,sizeof(*pinfo));
    pinfo->channels = para->channels;
    pinfo->samplerate = para->samplerate;
    pinfo->outptr = malloc(MAX_ONE_FRAME_OUT_SIZE);
    pinfo->outsize = MAX_ONE_FRAME_OUT_SIZE;

    dt_info (TAG, "[%s:%d] AUDIO DECODE START \n", __FUNCTION__, __LINE__);
    do
    {
        //maybe receive exit cmd in idle status, so exit prior to idle
        if (decoder->status == ADEC_STATUS_EXIT) 
        {
            dt_debug (TAG, "[%s:%d] receive decode loop exit cmd \n", __FUNCTION__, __LINE__);
            if (frame_data)
                free (frame_data);
            if (rest_data)
                free (rest_data);
            break;
        }

        if (decoder->status == ADEC_STATUS_IDLE)
        {
            dt_info (TAG, "[%s:%d] Idle status ,please wait \n", __FUNCTION__, __LINE__);
            usleep (100);
            continue;
        }

        /*read frame */
        if (!decoder->parent)
        {
            usleep (10000);
            dt_info (TAG, "[%s:%d] decoder parent is NULL \n", __FUNCTION__, __LINE__);
            continue;
        }
        ret = audio_read_frame (decoder->parent, &frame);
        if (ret < 0 || frame.size <= 0)
        {
            usleep (1000);
            dt_debug (TAG, "[%s:%d] dtaudio decoder loop read frame failed \n", __FUNCTION__, __LINE__);
            continue;
        }
        //read ok,update current pts, clear the buffer size
        if (frame.pts >= 0)
        {
            if (decoder->pts_first == -1)
            {
                if(frame.pts == DT_NOPTS_VALUE)
                    frame.pts = 0;
                decoder->pts_first = pts_exchange (decoder, frame.pts);
                dt_info (TAG, "first frame pts:%lld dts:%lld duration:%d size:%d\n", decoder->pts_first, frame.dts, frame.duration, frame.size);
            }
            decoder->pts_current = pts_exchange (decoder, frame.pts);
            dt_debug (TAG, "pkt pts:%lld current:%lld duration:%d pts_s:%lld dts:%lld buf_size:%d \n", frame.pts, decoder->pts_current, frame.duration, frame.pts / 90000, frame.dts, decoder->pts_buffer_size);
            decoder->pts_last_valid = decoder->pts_current;
            decoder->pts_buffer_size = 0;
        }
        //repack the frame
        if (frame_data)
        {
            free (frame_data);
            frame_data = NULL;
            frame_size = 0;
        }
        if (rest_size)
            frame_data = malloc (frame.size + rest_size);
        else
            frame_data = frame.data;
        if (!frame_data)
        {
            dt_error (TAG, "malloc audio frame failed ,we will lost one frame\n");
            if (rest_data)
                free (rest_data);
            rest_size = 0;
            continue;
        }

        if (rest_size)          // no rest data
        {
            dt_debug (TAG, "left %d byet last time\n", rest_size);
            memcpy (frame_data, rest_data, rest_size);
            free (rest_data);
            rest_data = NULL;
            memcpy (frame_data + rest_size, frame.data, frame.size);
        }

        frame_size = frame.size + rest_size;
        rest_size = 0;
        used = 0;
        declen = 0;

        pinfo->inptr = frame_data;
        pinfo->inlen = frame_size;
        pinfo->outlen = 0; 

        //free pkt
        frame.data = NULL;
        frame.size = 0;

      DECODE_LOOP:
        if (decoder->status == ADEC_STATUS_EXIT)
        {
            dt_info (TAG, "[%s:%d] receive decode loop exit cmd \n", __FUNCTION__, __LINE__);
            if (frame_data)
                free (frame_data);
            break;
        }
        /*decode frame */
        pinfo->consume = declen;
        used = wrapper->decode_frame (wrapper, pinfo);
        if (used < 0)
        {
            decoder->decode_err_cnt++;
            /*
             * if decoder is ffmpeg,do not restore data if decode failed
             * if decoder is not ffmpeg, restore raw stream packet if decode failed
             * */
            if (!strcmp (wrapper->name, "ffmpeg audio decoder"))
            {
                dt_error (TAG, "[%s:%d] ffmpeg failed to decode this frame, just break\n", __FUNCTION__, __LINE__);
                decoder->decode_offset += pinfo->inlen;
            }
            continue;
        }
        else if (used == 0 && pinfo->outlen == 0) // used == 0 && out == 0 means need more data
        {
            //maybe need more data
            rest_data = malloc (pinfo->inlen);
            if (rest_data == NULL)
            {
                dt_error ("[%s:%d] rest_data malloc failed\n", __FUNCTION__, __LINE__);
                rest_size = 0;  //skip this frame
                continue;
            }
            memcpy (rest_data, pinfo->inptr, pinfo->inlen);
            rest_size = pinfo->inlen;
            dt_info (TAG, "Maybe we need more data\n");
            continue;
        }
        declen += used;
        pinfo->inlen -= used;
        decoder->decode_offset += used;
        decoder->pts_cache_size = pinfo->outlen;
        decoder->pts_buffer_size += pinfo->outlen;
        if (pinfo->outlen == 0)      //get no data, maybe first time for init
            dt_info (TAG, "GET NO PCM DECODED OUT,used:%d \n",used);

        fill_size = 0;
      REFILL_BUFFER:
        if (decoder->status == ADEC_STATUS_EXIT)
            goto EXIT;
        /*write pcm */
        if (buf_space (out) < pinfo->outlen)
        {
            dt_debug (TAG, "[%s:%d] output buffer do not left enough space ,space=%d level:%d outsie:%d \n", __FUNCTION__, __LINE__, buf_space (out), buf_level (out), pinfo->outlen);
            usleep (1000);
            goto REFILL_BUFFER;
        }
        ret = buf_put (out, pinfo->outptr + fill_size, pinfo->outlen);
        fill_size += ret;
        pinfo->outlen -= ret;
        decoder->pts_cache_size = pinfo->outlen;
        if (pinfo->outlen > 0)
            goto REFILL_BUFFER;

        if (pinfo->inlen)
            goto DECODE_LOOP;
    }
    while (1);
  EXIT:
    dt_info (TAG, "[file:%s][%s:%d]decoder loop thread exit ok\n", __FILE__, __FUNCTION__, __LINE__);
    /* free adec_ctrl_t buf */
    if(pinfo->outptr)
        free(pinfo->outptr);
    pinfo->outlen = pinfo->outsize = 0;
    pthread_exit (NULL);
    return NULL;
}
示例#3
0
static void *video_decode_loop (void *arg)
{
    dt_av_frame_t frame;
    dtvideo_decoder_t *decoder = (dtvideo_decoder_t *) arg;
    vd_wrapper_t *wrapper = decoder->wrapper;
    dtvideo_context_t *vctx = (dtvideo_context_t *) decoder->parent;
    queue_t *picture_queue = vctx->vo_queue;
    /*used for decode */
    AVPicture_t *picture = NULL;
    int ret;
    dt_info (TAG, "[%s:%d] start decode loop \n", __FUNCTION__, __LINE__);

    do
    {
        if (decoder->status == VDEC_STATUS_IDLE)
        {
            dt_info (TAG, "[%s:%d] Idle status ,please wait \n", __FUNCTION__, __LINE__);
            usleep (100);
            continue;
        }
        if (decoder->status == VDEC_STATUS_EXIT)
        {
            dt_info (TAG, "[%s:%d] receive decode loop exit cmd \n", __FUNCTION__, __LINE__);
            break;
        }

        /*read frame */
        if (!decoder->parent)
        {
            usleep (100);
            continue;
        }

        if (picture_queue->length >= VIDEO_OUT_MAX_COUNT)
        {
            //vo queue full
            usleep (1000);
            continue;
        }
        ret = dtvideo_read_frame (decoder->parent, &frame);
        if (ret < 0)
        {
            usleep (100);
            dt_debug (TAG, "[%s:%d] dtaudio decoder loop read frame failed \n", __FUNCTION__, __LINE__);
            continue;
        }
        /*read one frame,enter decode frame module */
        //will exec once for one time
        ret = wrapper->decode_frame (wrapper, &frame, &picture);
        if (ret <= 0)
        {
            decoder->decode_err_cnt++;
            dt_debug (TAG, "[%s:%d]decode failed \n", __FUNCTION__, __LINE__);
            picture = NULL;
            goto DECODE_END;
        }
        if (!picture)
            goto DECODE_END;
        decoder->frame_count++;
        //Got one frame
        //picture->pts = frame.pts;
        
        //update current pts, clear the buffer size
        if (frame.pts >= 0 && decoder->pts_first == -1)
        {
            //we will use first pts to estimate pts
            dt_info (TAG, "[%s:%d]first frame decoded ok, pts:0x%x dts:0x%x duration:%d size:%d\n", __FUNCTION__, __LINE__, frame.pts, frame.dts, frame.duration, frame.size);
            decoder->pts_first = pts_exchange (decoder, picture->pts);
            decoder->pts_current = decoder->pts_first;
        }
        else
        {
            if(pts_mode)
            {
                int fps = decoder->para.fps;
                float dur_inc = 90000/fps;
                picture->pts = decoder->pts_current + dur_inc;
                decoder->pts_current = picture->pts; 
            }
        }

        /*queue in */
        queue_push_tail (picture_queue, picture);
        picture = NULL;
      DECODE_END:
        //we successfully decodec one frame
        if (frame.data)
        {
            free (frame.data);
            frame.data = NULL;
            frame.size = 0;
            frame.pts = -1;
        }
    }
    while (1);
    dt_info (TAG, "[file:%s][%s:%d]decoder loop thread exit ok\n", __FILE__, __FUNCTION__, __LINE__);
    pthread_exit (NULL);
    return NULL;
}
示例#4
0
static void *video_decode_loop (void *arg)
{
    dt_av_pkt_t frame;
    dtvideo_decoder_t *decoder = (dtvideo_decoder_t *) arg;
    vd_wrapper_t *wrapper = decoder->wrapper;
    dtvideo_context_t *vctx = (dtvideo_context_t *) decoder->parent;
    dtvideo_filter_t *filter = (dtvideo_filter_t *) &(vctx->video_filt);
    queue_t *picture_queue = vctx->vo_queue;
    /*used for decode */
    dt_av_frame_t *picture = NULL;
    int ret;
    dt_info (TAG, "[%s:%d] start decode loop \n", __FUNCTION__, __LINE__);

    do
    {
        //exit check before idle, maybe recieve exit cmd in idle status
        if (decoder->status == VDEC_STATUS_EXIT)
        {
            dt_info (TAG, "[%s:%d] receive decode loop exit cmd \n", __FUNCTION__, __LINE__);
            break;
        }

        if (decoder->status == VDEC_STATUS_IDLE)
        {
            dt_info (TAG, "[%s:%d] Idle status ,please wait \n", __FUNCTION__, __LINE__);
            usleep (100);
            continue;
        }

        /*read frame */
        if (!decoder->parent)
        {
            usleep (100);
            continue;
        }

        if (picture_queue->length >= VIDEO_OUT_MAX_COUNT)
        {
            //vo queue full
            usleep (1000);
            continue;
        }
        ret = dtvideo_read_frame (decoder->parent, &frame);
        if (ret < 0)
        {
            if(decoder->pts_first == -1 || decoder->pts_first == DT_NOPTS_VALUE)
            {
                usleep(1000);
                continue;
            }
            //no data left, maybe eof, need to flush left data
            memset(&frame,0,sizeof(dt_av_pkt_t));
            dt_info (TAG, "[%s:%d] no video frame left, flush left frames \n", __FUNCTION__, __LINE__);
        }
        /*read one frame,enter decode frame module */
        //will exec once for one time
        ret = wrapper->decode_frame (decoder, &frame, &picture);
        if (ret <= 0)
        {
            decoder->decode_err_cnt++;
            dt_info (TAG, "[%s:%d]decode failed \n", __FUNCTION__, __LINE__);
            picture = NULL;
            usleep(10000);
            goto DECODE_END;
        }
        if (!picture)
            goto DECODE_END;

        //got one frame, filter process
        if(wrapper->info_changed(decoder))
        {
            memcpy(&decoder->para, &wrapper->para, sizeof(dtvideo_para_t));
            memcpy(&filter->para, &wrapper->para, sizeof(dtvideo_para_t));
            video_filter_reset(filter, &decoder->para);
        }

        video_filter_process(filter, picture);

        decoder->frame_count++;
        //Got one frame
        //picture->pts = frame.pts;
        
        //update current pts, clear the buffer size
        if (frame.pts >= 0 && decoder->pts_first == -1)
        {
            //we will use first pts to estimate pts
            dt_info (TAG, "[%s:%d]first frame decoded ok, pts:0x%llx dts:0x%llx duration:%d size:%d\n", __FUNCTION__, __LINE__, frame.pts, frame.dts, frame.duration, frame.size);
            decoder->pts_first = pts_exchange (decoder, picture->pts);
            decoder->pts_current = decoder->pts_first;
        }
        else
        {
            if(pts_mode)
            {
                int fps = decoder->para.fps;
                float dur_inc = 90000/fps;
                picture->pts = decoder->pts_current + dur_inc;
                decoder->pts_current = picture->pts; 
            }
        }

        /*queue in */
        queue_push_tail (picture_queue, picture);
        picture = NULL;
      DECODE_END:
        //we successfully decodec one frame
        if (frame.data)
        {
            if(frame.data)
                free (frame.data);
            frame.data = NULL;
            frame.size = 0;
            frame.pts = -1;
        }
    }
    while (1);
    dt_info (TAG, "[file:%s][%s:%d]decoder loop thread exit ok\n", __FILE__, __FUNCTION__, __LINE__);

    //filter release
    video_filter_stop(filter);

    pthread_exit (NULL);
    return NULL;
}
示例#5
0
static void *video_decode_loop(void *arg)
{
    dt_av_pkt_t frame;
    dtvideo_decoder_t *decoder = (dtvideo_decoder_t *) arg;
    vd_wrapper_t *wrapper = decoder->wrapper;
    vd_statistics_info_t *p_vd_statistics_info = &decoder->statistics_info;
    dtvideo_context_t *vctx = (dtvideo_context_t *) decoder->parent;
    queue_t *picture_queue = vctx->vo_queue;
    /*used for decode */
    dt_av_frame_t *picture = NULL;
    int ret;
    dt_info(TAG, "[%s:%d] start decode loop \n", __FUNCTION__, __LINE__);

    do {
        //exit check before idle, maybe recieve exit cmd in idle status
        if (decoder->status == VDEC_STATUS_EXIT) {
            dt_info(TAG, "[%s:%d] receive decode loop exit cmd \n", __FUNCTION__, __LINE__);
            break;
        }

        if (decoder->status == VDEC_STATUS_IDLE) {
            dt_info(TAG, "[%s:%d] Idle status ,please wait \n", __FUNCTION__, __LINE__);
            usleep(100);
            continue;
        }

        /*read frame */
        if (!decoder->parent) {
            usleep(100);
            continue;
        }

        if (picture_queue->length >= VIDEO_OUT_MAX_COUNT) {
            //vo queue full
            usleep(1000);
            continue;
        }
        ret = dtvideo_read_frame(decoder->parent, &frame);
        if (ret < 0) {
            dt_usleep(1000);
            if (decoder->pts_first == DT_NOPTS_VALUE) {
                continue;
            }
            //no data left, maybe eof, need to flush left data
            memset(&frame, 0, sizeof(dt_av_pkt_t));
            dt_debug(TAG, "[%s:%d] no video frame left, flush left frames \n", __FUNCTION__,
                     __LINE__);
        }
        /*read one frame,enter decode frame module */
        //will exec once for one time
        ret = wrapper->decode_frame(decoder, &frame, &picture);
        if (ret <= 0) {
            decoder->decode_err_cnt++;
            dt_debug(TAG, "[%s:%d]decode failed \n", __FUNCTION__, __LINE__);
            picture = NULL;
            //usleep(10000);
            goto DECODE_END;
        }
        if (!picture) {
            goto DECODE_END;
        }

        // statistics collection
        {
            p_vd_statistics_info->decoded_frame_count++;
        }
        decoder->frame_count++;
        //Got one frame
        //update current pts, clear the buffer size
        if (PTS_VALID(picture->pts)) {
            picture->pts = pts_exchange(decoder, picture->pts);
        }
        if (decoder->first_frame_decoded == 0 && PTS_INVALID(decoder->pts_first)) {
            decoder->pts_first = decoder->pts_current = picture->pts;
            decoder->first_frame_decoded = 1;
            dt_info(TAG, "[%s:%d]first frame decoded ok, pts:0x%llx dts:0x%llx\n",
                    __FUNCTION__, __LINE__, picture->pts, picture->dts);
        } else {
            if (pts_mode || PTS_INVALID(picture->pts)) {
                int fps = decoder->para.fps;
                int dur_inc = (int)((double)90000 / fps);
                picture->pts = decoder->pts_current + dur_inc;
                decoder->pts_current = picture->pts;
                dt_debug(TAG, "vpts inc itself. pts_mode:%d pts:0x%llx inc:%d\n", pts_mode,
                         picture->pts, dur_inc);
            }
        }

        /*queue in */
        queue_push_tail(picture_queue, picture);
        picture = NULL;
DECODE_END:
        //we successfully decodec one frame
        if (frame.data) {
            if (frame.data) {
                free(frame.data);
            }
            frame.data = NULL;
            frame.size = 0;
            frame.pts = -1;
        }
    } while (1);
    dt_info(TAG, "[file:%s][%s:%d]decoder loop thread exit ok\n", __FILE__,
            __FUNCTION__, __LINE__);

    pthread_exit(NULL);
    return NULL;
}