Exemplo n.º 1
0
SINT SoundSourceFFmpeg::seekSampleFrame(SINT frameIndex) {
    DEBUG_ASSERT(isValidFrameIndex(frameIndex));

    int ret = 0;
    qint64 i = 0;

    if (frameIndex < 0 || frameIndex < m_lCacheStartFrame) {
        ret = avformat_seek_file(m_pFormatCtx,
                                 m_iAudioStream,
                                 0,
                                 32767 * 2,
                                 32767 * 2,
                                 AVSEEK_FLAG_BACKWARD);


        if (ret < 0) {
            qDebug() << "SoundSourceFFmpeg::seek: Can't seek to 0 byte!";
            return -1;
        }

        clearCache();
        m_lCacheStartFrame = 0;
        m_lCacheEndFrame = 0;
        m_lCacheLastPos = 0;
        m_lCacheFramePos = 0;
        m_lStoredSeekPoint = -1;


        // Try to find some jump point near to
        // where we are located so we don't needed
        // to try guess it
        if (frameIndex >= AUDIOSOURCEFFMPEG_POSDISTANCE) {
            for (i = 0; i < m_SJumpPoints.size(); i ++) {
                if (m_SJumpPoints[i]->startFrame >= frameIndex && i > 2) {
                    m_lCacheFramePos = m_SJumpPoints[i - 2]->startFrame * 2;
                    m_lStoredSeekPoint = m_SJumpPoints[i - 2]->pos;
                    break;
                }
            }
        }

        if (frameIndex == 0) {
            readFramesToCache((AUDIOSOURCEFFMPEG_CACHESIZE - 50), -1);
        } else {
            readFramesToCache((AUDIOSOURCEFFMPEG_CACHESIZE / 2), frameIndex);
        }
    }


    if (m_lCacheEndFrame <= frameIndex) {
        readFramesToCache(100, frameIndex);
    }

    m_currentMixxxFrameIndex = frameIndex;

    m_bIsSeeked = TRUE;

    return frameIndex;
}
Exemplo n.º 2
0
int FFMpegDecoder::seekToSec(double sec)
{
	//TODO: implement
	/*
	AV_TIME_BASE
	avformat_seek_file(pFormatCtx,this->videoStream,
	*/
	int64_t seekTarget = sec*AV_TIME_BASE;
	int ret = avformat_seek_file(pFormatCtx,-1,INT64_MIN,seekTarget,INT64_MAX,0);
	return ret;
}
Exemplo n.º 3
0
bool VideoDecoder::seekFrame(int64_t frame)
{

    qDebug("\t avformat_seek_file\n");
    if(avformat_seek_file(videoFormatContext, videoStream, 0, frame, frame, AVSEEK_FLAG_FRAME)<0)
        return false;

    avcodec_flush_buffers(videoFormatContext->streams[videoStream]->codec);

    return true;
}
Exemplo n.º 4
0
bool AVDecoder::seekVideo(int percentage)
{
    if(!loadCodec(CODEC_VIDEO)) {
        return false;
    }

    qint64 seek_pos = pFormatCtx->duration * percentage / (AV_TIME_BASE * 100);
    qint64 frame = av_rescale(seek_pos, av_stream->time_base.den, av_stream->time_base.num);

    return avformat_seek_file(pFormatCtx, stream_index, 0, frame, frame, AVSEEK_FLAG_FRAME) >= 0;
}
Exemplo n.º 5
0
void Demuxer::run()
{
	for(;;)
	{
        if(aw->abortRequest == 1)
            break;

        if(aw->seekPos != 0){
            qint64 seek_target = aw->seekPos;
            qint64 seek_min    = aw->seekPos > aw->pos ? aw->pos + 2: INT64_MIN;
            qint64 seek_max    = aw->seekPos < aw->pos ? aw->pos - 2: INT64_MAX;
            int ret = avformat_seek_file(aw->formatCtx, -1, seek_min, seek_target, seek_max, 0);
            if(ret < 0){
                std::cout<<"seek failed!"<<"\n";
            } else {
                /*seek success*/
                aw->serial++;
                aw->basePos = seek_target;
            }
            aw->seekPos = 0;
        }

        auto sharedPkt = std::make_shared<Packet>();
        //av_init_packet(&pkt);
        sharedPkt->serial = aw->serial;
        AVPacket* ppkt = &sharedPkt->pkt;
        ppkt->size = 0;
        ppkt->data = NULL;
        int ret = av_read_frame(aw->formatCtx, ppkt);
		//end of stream, put null packet flush the remaining frames
		if((ret == AVERROR_EOF || avio_feof(aw->formatCtx->pb)) && !aw->eof){
            ppkt->size = 0;
            ppkt->data = NULL;
            aw->audioPacketQ.push(sharedPkt);
            aw->videoPacketQ.push(sharedPkt);
			aw->eof = true;
			//FIXME: maybe stop
			break;
		}
		/*push the audio packet*/
        if(ppkt->stream_index == aw->audioIndex){            
            aw->audioPacketQ.push(sharedPkt);
        } else if(ppkt->stream_index == aw->videoIndex){
            aw->videoPacketQ.push(sharedPkt);
        }
	}
}
Exemplo n.º 6
0
static int demuxer_ffmpeg_seek_frame (demuxer_wrapper_t * wrapper, int timestamp)
{
    AVFormatContext *ic = (AVFormatContext *) wrapper->demuxer_priv;
    int seek_flags = AVSEEK_FLAG_ANY;

    int64_t seek_target = timestamp * 1000000;
    int64_t seek_min = (seek_target > 0) ? seek_target - timestamp + 2 : INT64_MIN;
    int64_t seek_max = (seek_target < 0) ? seek_target - timestamp - 2 : INT64_MAX;
    int64_t ret = avformat_seek_file (ic, -1, seek_min, seek_target, seek_max, seek_flags);

    if (ret >= 0)
    {
        dt_info (TAG, "AV_FORMAT_SEEK_FILE OK \n");
        return 0;
    }

    dt_info (TAG, "AV_FORMAT_SEEK_FILE FAIL \n");
    return -1;
}
Exemplo n.º 7
0
uint_t aubio_source_avcodec_seek (aubio_source_avcodec_t * s, uint_t pos) {
  int64_t resampled_pos = (uint_t)ROUND(pos * (s->input_samplerate * 1. / s->samplerate));
  int64_t min_ts = MAX(resampled_pos - 2000, 0);
  int64_t max_ts = MIN(resampled_pos + 2000, INT64_MAX);
  int seek_flags = AVSEEK_FLAG_FRAME | AVSEEK_FLAG_ANY;
  int ret = avformat_seek_file(s->avFormatCtx, s->selected_stream,
      min_ts, resampled_pos, max_ts, seek_flags);
  if (ret < 0) {
    AUBIO_ERR("Failed seeking to %d in file %s", pos, s->path);
  }
  // reset read status
  s->eof = 0;
  s->read_index = 0;
  s->read_samples = 0;
  // reset the AVAudioResampleContext
  avresample_close(s->avr);
  avresample_open(s->avr);
  return ret;
}
Exemplo n.º 8
0
void VideoPlayer::doAccurateSeek()
{
    int ret;

    vLOGE("before seek....\n");
    //ret = av_seek_frame(mFormatCtx, mVideoStreamIndex, mSeekTime, 0);
    ret = avformat_seek_file(mFormatCtx, -1, INT64_MIN, mSeekTime, INT64_MAX, 0);
    if (ret < 0) {
        vLOGE("Could not find seek time: %lld\n", mSeekTime);
        return;
    }

    decodeToSeekTime();

    mPictureRingBuffer.notifyRingBufferExit();
    mPictureRingBuffer.flush();

    mAccurateSeek = false;
    vLOGE("after seek...\n");
}
Exemplo n.º 9
0
int ffsox_source_seek(source_t *n, int64_t ts)
{
  AVStream *st;
  int si;

  if (0ll<ts) {
    si=av_find_default_stream_index(n->f.fc);
    st=n->f.fc->streams[si];
    ts=av_rescale_q(ts,AV_TIME_BASE_Q,st->time_base);

    if (avformat_seek_file(n->f.fc,si,INT64_MIN,ts,INT64_MAX,0)<0) {
      DMESSAGE("seeking");
      goto seek;
    }

    n->ts=av_rescale_q(st->cur_dts,st->time_base,AV_TIME_BASE_Q);
  }

  return 0;
seek:
  return -1;
}
Exemplo n.º 10
0
/**
  \brief Seek to frame
**/
bool DecodeThread::seekFrame(qint64 frame)
{
    //printf("**** seekFrame to %d. LLT: %d. LT: %d. LLF: %d. LF: %d. LastFrameOk: %d\n",(int)frame,LastLastFrameTime,LastFrameTime,LastLastFrameNumber,LastFrameNumber,(int)LastFrameOk);
    cout << "frame" << frame << endl;
    // Seek if:
    // - we don't know where we are (Ok=false)
    // - we know where we are but:
    //    - the desired frame is after the last decoded frame (this could be optimized: if the distance is small, calling decodeSeekFrame may be faster than seeking from the last key frame)
    //    - the desired frame is smaller or equal than the previous to the last decoded frame. Equal because if frame==LastLastFrameNumber we don't want the LastFrame, but the one before->we need to seek there
    //if( (LastFrameOk==false) || ((LastFrameOk==true) && (frame<=LastLastFrameNumber || frame>LastFrameNumber) ) )
    //{
    //printf("\t avformat_seek_file\n");
    if(avformat_seek_file(pFormatCtx,videoStream,frame,frame,frame,AVSEEK_FLAG_FRAME)<0)
        return false;

    avcodec_flush_buffers(pVideoCodecCtx);

    //DesiredFrameNumber = frame;
    //LastFrameOk=false;
    //}
    //printf("\t decodeSeekFrame\n");
    return true;
    //return decodeSeekFrame(frame);
}
Exemplo n.º 11
0
status_t
StreamBase::Seek(uint32 flags, int64* frame, bigtime_t* time)
{
	BAutolock _(fStreamLock);

	if (fContext == NULL || fStream == NULL)
		return B_NO_INIT;

	TRACE_SEEK("StreamBase::Seek(%ld,%s%s%s%s, %lld, "
		"%lld)\n", VirtualIndex(),
		(flags & B_MEDIA_SEEK_TO_FRAME) ? " B_MEDIA_SEEK_TO_FRAME" : "",
		(flags & B_MEDIA_SEEK_TO_TIME) ? " B_MEDIA_SEEK_TO_TIME" : "",
		(flags & B_MEDIA_SEEK_CLOSEST_BACKWARD)
			? " B_MEDIA_SEEK_CLOSEST_BACKWARD" : "",
		(flags & B_MEDIA_SEEK_CLOSEST_FORWARD)
			? " B_MEDIA_SEEK_CLOSEST_FORWARD" : "",
		*frame, *time);

	double frameRate = FrameRate();
	if ((flags & B_MEDIA_SEEK_TO_FRAME) != 0) {
		// Seeking is always based on time, initialize it when client seeks
		// based on frame.
		*time = (bigtime_t)(*frame * 1000000.0 / frameRate + 0.5);
	}

	int64_t timeStamp = *time;

	int searchFlags = AVSEEK_FLAG_BACKWARD;
	if ((flags & B_MEDIA_SEEK_CLOSEST_FORWARD) != 0)
		searchFlags = 0;

	if (fSeekByBytes) {
		searchFlags |= AVSEEK_FLAG_BYTE;

		BAutolock _(fSourceLock);
		int64_t fileSize;
		if (fSource->GetSize(&fileSize) != B_OK)
			return B_NOT_SUPPORTED;
		int64_t duration = Duration();
		if (duration == 0)
			return B_NOT_SUPPORTED;

		timeStamp = int64_t(fileSize * ((double)timeStamp / duration));
		if ((flags & B_MEDIA_SEEK_CLOSEST_BACKWARD) != 0) {
			timeStamp -= 65536;
			if (timeStamp < 0)
				timeStamp = 0;
		}

		bool seekAgain = true;
		bool seekForward = true;
		bigtime_t lastFoundTime = -1;
		int64_t closestTimeStampBackwards = -1;
		while (seekAgain) {
			if (avformat_seek_file(fContext, -1, INT64_MIN, timeStamp,
				INT64_MAX, searchFlags) < 0) {
				TRACE("  avformat_seek_file() (by bytes) failed.\n");
				return B_ERROR;
			}
			seekAgain = false;

			// Our last packet is toast in any case. Read the next one so we
			// know where we really seeked.
			fReusePacket = false;
			if (_NextPacket(true) == B_OK) {
				while (fPacket.pts == kNoPTSValue) {
					fReusePacket = false;
					if (_NextPacket(true) != B_OK)
						return B_ERROR;
				}
				if (fPacket.pos >= 0)
					timeStamp = fPacket.pos;
				bigtime_t foundTime
					= _ConvertFromStreamTimeBase(fPacket.pts);
				if (foundTime != lastFoundTime) {
					lastFoundTime = foundTime;
					if (foundTime > *time) {
						if (closestTimeStampBackwards >= 0) {
							timeStamp = closestTimeStampBackwards;
							seekAgain = true;
							seekForward = false;
							continue;
						}
						int64_t diff = int64_t(fileSize
							* ((double)(foundTime - *time) / (2 * duration)));
						if (diff < 8192)
							break;
						timeStamp -= diff;
						TRACE_SEEK("  need to seek back (%lld) (time: %.2f "
							"-> %.2f)\n", timeStamp, *time / 1000000.0,
							foundTime / 1000000.0);
						if (timeStamp < 0)
							foundTime = 0;
						else {
							seekAgain = true;
							continue;
						}
					} else if (seekForward && foundTime < *time - 100000) {
						closestTimeStampBackwards = timeStamp;
						int64_t diff = int64_t(fileSize
							* ((double)(*time - foundTime) / (2 * duration)));
						if (diff < 8192)
							break;
						timeStamp += diff;
						TRACE_SEEK("  need to seek forward (%lld) (time: "
							"%.2f -> %.2f)\n", timeStamp, *time / 1000000.0,
							foundTime / 1000000.0);
						if (timeStamp > duration)
							foundTime = duration;
						else {
							seekAgain = true;
							continue;
						}
					}
				}
				TRACE_SEEK("  found time: %lld -> %lld (%.2f)\n", *time,
					foundTime, foundTime / 1000000.0);
				*time = foundTime;
				*frame = (uint64)(*time * frameRate / 1000000LL + 0.5);
				TRACE_SEEK("  seeked frame: %lld\n", *frame);
			} else {
				TRACE_SEEK("  _NextPacket() failed!\n");
				return B_ERROR;
			}
		}
	} else {
		// We may not get a PTS from the next packet after seeking, so
		// we try to get an expected time from the index.
		int64_t streamTimeStamp = _ConvertToStreamTimeBase(*time);
		int index = av_index_search_timestamp(fStream, streamTimeStamp,
			searchFlags);
		if (index < 0) {
			TRACE("  av_index_search_timestamp() failed\n");
		} else {
			if (index > 0) {
				const AVIndexEntry& entry = fStream->index_entries[index];
				streamTimeStamp = entry.timestamp;
			} else {
				// Some demuxers use the first index entry to store some
				// other information, like the total playing time for example.
				// Assume the timeStamp of the first entry is alays 0.
				// TODO: Handle start-time offset?
				streamTimeStamp = 0;
			}
			bigtime_t foundTime = _ConvertFromStreamTimeBase(streamTimeStamp);
			bigtime_t timeDiff = foundTime > *time
				? foundTime - *time : *time - foundTime;

			if (timeDiff > 1000000
				&& (fStreamBuildsIndexWhileReading
					|| index == fStream->nb_index_entries - 1)) {
				// If the stream is building the index on the fly while parsing
				// it, we only have entries in the index for positions already
				// decoded, i.e. we cannot seek into the future. In that case,
				// just assume that we can seek where we want and leave
				// time/frame unmodified. Since successfully seeking one time
				// will generate index entries for the seeked to position, we
				// need to remember this in fStreamBuildsIndexWhileReading,
				// since when seeking back there will be later index entries,
				// but we still want to ignore the found entry.
				fStreamBuildsIndexWhileReading = true;
				TRACE_SEEK("  Not trusting generic index entry. "
					"(Current count: %d)\n", fStream->nb_index_entries);
			} else {
				// If we found a reasonably time, write it into *time.
				// After seeking, we will try to read the sought time from
				// the next packet. If the packet has no PTS value, we may
				// still have a more accurate time from the index lookup.
				*time = foundTime;
			}
		}

		if (avformat_seek_file(fContext, -1, INT64_MIN, timeStamp, INT64_MAX,
				searchFlags) < 0) {
			TRACE("  avformat_seek_file() failed.\n");
			// Try to fall back to av_seek_frame()
			timeStamp = _ConvertToStreamTimeBase(timeStamp);
			if (av_seek_frame(fContext, fStream->index, timeStamp,
				searchFlags) < 0) {
				TRACE("  avformat_seek_frame() failed as well.\n");
				// Fall back to seeking to the beginning by bytes
				timeStamp = 0;
				if (av_seek_frame(fContext, fStream->index, timeStamp,
						AVSEEK_FLAG_BYTE) < 0) {
					TRACE("  avformat_seek_frame() by bytes failed as "
						"well.\n");
					// Do not propagate error in any case. We fail if we can't
					// read another packet.
				} else
					*time = 0;
			}
		}

		// Our last packet is toast in any case. Read the next one so
		// we know where we really sought.
		bigtime_t foundTime = *time;

		fReusePacket = false;
		if (_NextPacket(true) == B_OK) {
			if (fPacket.pts != kNoPTSValue)
				foundTime = _ConvertFromStreamTimeBase(fPacket.pts);
			else
				TRACE_SEEK("  no PTS in packet after seeking\n");
		} else
			TRACE_SEEK("  _NextPacket() failed!\n");

		*time = foundTime;
		TRACE_SEEK("  sought time: %.2fs\n", *time / 1000000.0);
		*frame = (uint64)(*time * frameRate / 1000000.0 + 0.5);
		TRACE_SEEK("  sought frame: %lld\n", *frame);
	}

	return B_OK;
}
Exemplo n.º 12
0
int main(int argc, char **argv)
{
    int opt, ret, stream, flags;
    const char *filename;
    AVFormatContext *avf = NULL;
    int64_t min_ts, max_ts, ts;
    AVPacket packet;

    while ((opt = getopt(argc, argv, "h")) != -1) {
        switch (opt) {
        case 'h':
            usage(0);
        default:
            usage(1);
        }
    }
    argc -= optind;
    argv += optind;
    if (!argc)
        usage(1);
    filename = *argv;
    argv++;
    argc--;

    av_register_all();
    if ((ret = avformat_open_input(&avf, filename, NULL, NULL)) < 0) {
        fprintf(stderr, "%s: %s\n", filename, av_err2str(ret));
        return 1;
    }
    if ((ret = avformat_find_stream_info(avf, NULL)) < 0) {
        fprintf(stderr, "%s: could not find codec parameters: %s\n", filename,
                av_err2str(ret));
        return 1;
    }

    for (; argc; argc--, argv++) {
        if (!strcmp(*argv, "read")) {
            ret = av_read_frame(avf, &packet);
            if (ret < 0) {
                printf("read: %d (%s)\n", ret, av_err2str(ret));
            } else {
                AVRational *tb = &avf->streams[packet.stream_index]->time_base;
                printf("read: %d size=%d stream=%d dts=%s (%s) pts=%s (%s)\n",
                       ret, packet.size, packet.stream_index,
                       av_ts2str(packet.dts), av_ts2timestr(packet.dts, tb),
                       av_ts2str(packet.pts), av_ts2timestr(packet.pts, tb));
                av_packet_unref(&packet);
            }
        } else if (sscanf(*argv, "seek:%i:%"SCNi64":%"SCNi64":%"SCNi64":%i",
                   &stream, &min_ts, &ts, &max_ts, &flags) == 5) {
            ret = avformat_seek_file(avf, stream, min_ts, ts, max_ts, flags);
            printf("seek: %d (%s)\n", ret, av_err2str(ret));
        } else {
            fprintf(stderr, "'%s': unknown command\n", *argv);
            return 1;
        }
    }

    avformat_close_input(&avf);

    return 0;
}
Exemplo n.º 13
0
void ImageLoader::loadImage( const QString& fileName, const int index )
{
    const QString extension = QFileInfo(fileName).suffix().toLower();

    if( extension == "dcx" )
    {
        QImage img = createSlideImage_( flow_->slideSize(), fileName, false,
                                        Qt::darkCyan, Qt::cyan );
        flow_->setSlide( index, img );
        return;
    }

    if( extension == "pyr" )
    {
        QImageReader reader( fileName + "amid/0.jpg" );
        QImage img = reader.read();
        img.setText( "source", fileName );
        flow_->setSlide( index, img );
        return;
    }

    QImageReader reader( fileName );
    if( reader.canRead( ))
    {
        QImage img = reader.read();
        img.setText( "source", fileName );
        flow_->setSlide( index, img );
        return;
    }
    else if( reader.error() != QImageReader::UnsupportedFormatError )
        return;

    if( !MovieContent::getSupportedExtensions().contains( extension ))
        return;

    AVFormatContext* avFormatContext;
    if( avformat_open_input( &avFormatContext, fileName.toAscii(), 0, 0 ) != 0 )
        return;

    if( avformat_find_stream_info( avFormatContext, 0 ) < 0 )
        return;

    // find the first video stream
    int streamIdx = -1;
    for( unsigned int i = 0; i < avFormatContext->nb_streams; ++i )
    {
        if( avFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO )
        {
            streamIdx = i;
            break;
        }
    }

    if( streamIdx == -1 )
        return;

    AVStream* videostream = avFormatContext->streams[streamIdx];
    AVCodecContext* avCodecContext = videostream->codec;
    AVCodec* codec = avcodec_find_decoder( avCodecContext->codec_id );
    if( !codec )
        return;

    if( avcodec_open2( avCodecContext, codec, 0 ) < 0 )
        return;

    AVFrame* avFrame = avcodec_alloc_frame();
    AVFrame* avFrameRGB = avcodec_alloc_frame();

    QImage image( avCodecContext->width, avCodecContext->height,
                  QImage::Format_RGB32 );
    int numBytes = avpicture_get_size( PIX_FMT_RGB24, image.width(),
                                       image.height( ));
    uint8_t* buffer = (uint8_t*)av_malloc( numBytes * sizeof(uint8_t));
    avpicture_fill( (AVPicture*)avFrameRGB, buffer, PIX_FMT_RGB24,
                    image.width(), image.height( ));

    SwsContext* swsContext = sws_getContext( avCodecContext->width,
                                             avCodecContext->height,
                                             avCodecContext->pix_fmt,
                                             image.width(), image.height(),
                                             PIX_FMT_RGB24, SWS_FAST_BILINEAR,
                                             0, 0, 0 );

    // seek to 10% of movie time
    const int64_t den2 = videostream->time_base.den * videostream->r_frame_rate.den;
    const int64_t num2 = videostream->time_base.num * videostream->r_frame_rate.num;
    const int64_t num_frames = av_rescale( videostream->duration, num2, den2 );
    const int64_t desiredTimestamp = videostream->start_time +
                                       av_rescale( num_frames / 10, den2, num2 );
    if( avformat_seek_file( avFormatContext, streamIdx, 0, desiredTimestamp,
                            desiredTimestamp, 0 ) != 0 )
    {
        return;
    }

    AVPacket packet;
    while( av_read_frame( avFormatContext, &packet ) >= 0 )
    {
        if( packet.stream_index != streamIdx )
            continue;

        int frameFinished;
        avcodec_decode_video2( avCodecContext, avFrame, &frameFinished,
                               &packet );

        if( !frameFinished )
            continue;

        sws_scale( swsContext, avFrame->data, avFrame->linesize, 0,
                   avCodecContext->height, avFrameRGB->data,
                   avFrameRGB->linesize );

        unsigned char* src = (unsigned char*)avFrameRGB->data[0];
        for( int y = 0; y < image.height(); ++y )
        {
            QRgb* scanLine = (QRgb*)image.scanLine(y);
            for( int x = 0; x < image.width(); ++x )
                scanLine[x] = qRgb(src[3*x], src[3*x+1], src[3*x+2]);
            src += avFrameRGB->linesize[0];
        }

        av_free_packet( &packet );

        image.setText( "source", fileName );
        flow_->setSlide( index, image );
        break;
    }

    avformat_close_input( &avFormatContext );
    sws_freeContext( swsContext );
    av_free( avFrame );
    av_free( avFrameRGB );
}
Exemplo n.º 14
0
void sxpi_demuxing_run(struct demuxing_ctx *ctx)
{
    int ret;
    int in_err, out_err;

    TRACE(ctx, "demuxing packets in queue %p", ctx->pkt_queue);

    for (;;) {
        AVPacket pkt;
        struct message msg;

        ret = av_thread_message_queue_recv(ctx->src_queue, &msg, AV_THREAD_MESSAGE_NONBLOCK);
        if (ret != AVERROR(EAGAIN)) {
            if (ret < 0)
                break;

            if (msg.type == MSG_SEEK) {
                av_assert0(!ctx->is_image);

                /* Make later modules stop working ASAP */
                av_thread_message_flush(ctx->pkt_queue);

                /* do actual seek so the following packet that will be pulled in
                 * this current thread will be at the (approximate) requested time */
                const int64_t seek_to = *(int64_t *)msg.data;
                LOG(ctx, INFO, "Seek in media at ts=%s", PTS2TIMESTR(seek_to));
                ret = avformat_seek_file(ctx->fmt_ctx, -1, INT64_MIN, seek_to, seek_to, 0);
                if (ret < 0) {
                    sxpi_msg_free_data(&msg);
                    break;
                }
            }

            /* Forward the message */
            ret = av_thread_message_queue_send(ctx->pkt_queue, &msg, 0);
            if (ret < 0) {
                sxpi_msg_free_data(&msg);
                break;
            }
        }

        msg.type = MSG_PACKET;

        ret = pull_packet(ctx, &pkt);
        if (ret < 0)
            break;

        TRACE(ctx, "pulled a packet of size %d, sending to decoder", pkt.size);

        msg.data = av_memdup(&pkt, sizeof(pkt));
        if (!msg.data) {
            av_packet_unref(&pkt);
            break;
        }

        ret = av_thread_message_queue_send(ctx->pkt_queue, &msg, 0);
        TRACE(ctx, "sent packet to decoder, ret=%s", av_err2str(ret));

        if (ret < 0) {
            av_packet_unref(&pkt);
            av_freep(&msg.data);
            if (ret != AVERROR_EOF && ret != AVERROR_EXIT)
                LOG(ctx, ERROR, "Unable to send packet to decoder: %s", av_err2str(ret));
            TRACE(ctx, "can't send pkt to decoder: %s", av_err2str(ret));
            av_thread_message_queue_set_err_recv(ctx->pkt_queue, ret);
            break;
        }
    }

    if (ret < 0 && ret != AVERROR_EOF) {
        in_err = out_err = ret;
    } else {
        in_err = AVERROR_EXIT;
        out_err = AVERROR_EOF;
    }
    TRACE(ctx, "notify user with %s and decoder with %s",
          av_err2str(in_err), av_err2str(out_err));
    av_thread_message_queue_set_err_send(ctx->src_queue, in_err);
    av_thread_message_flush(ctx->src_queue);
    av_thread_message_queue_set_err_recv(ctx->pkt_queue, out_err);
}
Exemplo n.º 15
0
void player_decode(void *data)
{
	State *state = (State *) data;
	
	int ret;
	int eof = 0;

	for (;;) {

		if (state->abort_request) {
			break;
		}

        if (state->paused != state->last_paused) {
        	state->last_paused = state->paused;
            if (state->paused) {
            	state->read_pause_return = av_read_pause(state->pFormatCtx);
            } else {
                av_read_play(state->pFormatCtx);
            }
        }

        if (state->seek_req) {
            int64_t seek_target = state->seek_pos;
            int64_t seek_min = state->seek_rel > 0 ? seek_target - state->seek_rel + 2: INT64_MIN;
            int64_t seek_max = state->seek_rel < 0 ? seek_target - state->seek_rel - 2: INT64_MAX;

            ret = avformat_seek_file(state->pFormatCtx, -1, seek_min, seek_target, seek_max, state->seek_flags);
            if (ret < 0) {
                fprintf(stderr, "%s: error while seeking\n", state->pFormatCtx->filename);
            } else {
                if (state->audio_stream >= 0) {
                	avcodec_flush_buffers(state->audio_st->codec);
                }
                state->notify_callback(state->clazz, MEDIA_SEEK_COMPLETE, 0, 0, FROM_THREAD);
            }
            state->seek_req = 0;
            eof = 0;
        }

        if (state->paused) {
        	goto sleep;
        }

		AVPacket packet;
		memset(&packet, 0, sizeof(packet)); //make sure we can safely free it

		int i;
			
		for (i = 0; i < state->pFormatCtx->nb_streams; ++i) {
			//av_init_packet(&packet);
			ret = av_read_frame(state->pFormatCtx, &packet);

	        if (ret < 0) {
	            if (ret == AVERROR_EOF || url_feof(state->pFormatCtx->pb)) {
	                eof = 1;
	                break;
	            }
	        }

	        int frame_size_ptr;
			ret = decode_frame_from_packet(state, &packet, &frame_size_ptr, FROM_THREAD);
			av_free_packet(&packet);

			if (ret != 0) { //an error or a frame decoded
				// TODO add this bacl=k
			}
		}

		if (eof) {
			break;
		}

		sleep:
		    usleep(100);
	}

	if (eof) {
		state->notify_callback(state->clazz, MEDIA_PLAYBACK_COMPLETE, 0, 0, FROM_THREAD);
	}
}
Exemplo n.º 16
0
int getFrameAt(int64_t timeUs, int width, int height)
{
    int ret = -1;
    AVFrame* pFrame = NULL;

    ret = avformat_seek_file(m_pFormatContext, -1, INT16_MIN, timeUs, INT16_MAX, 0);

    pFrame = av_frame_alloc();
    m_pThumbFrame = av_frame_alloc();
    ret = openDecoder();
    if (ret != 0)
    {
        av_frame_free(&pFrame);
        av_frame_free(&m_pThumbFrame);
        return ret;
    }
#ifdef DEBUG_SPEND_TIME
#ifdef _WIN32
    DWORD start_time = timeGetTime();
#else
    struct timeval start, end;
    gettimeofday(&start, NULL);
#endif
#endif

    ret = decodeOneFrame(pFrame);
    if (ret < 0)
    {
        av_frame_free(&pFrame);
        av_frame_free(&m_pThumbFrame);
        return ret;
    }
#ifdef DEBUG_SPEND_TIME
#ifdef _WIN32
    DWORD end_time = timeGetTime();
    printf("decodeOneFrame spend time = %d ms\n", end_time - start_time);
#else
    gettimeofday(&end, NULL);
    int spend_time = (end.tv_sec - start.tv_sec) * 1000 + (end.tv_usec - start.tv_usec) / 1000;
    printf("spend_time = %d ms\n", spend_time);
#endif
#endif

    ret = getThumbnail(pFrame, m_pThumbFrame, width, height);
    if (ret < 0)
    {
        av_frame_free(&pFrame);
        av_frame_free(&m_pThumbFrame);
        return ret;
    }

    // save the rgb565
    FILE *pFile = fopen(strThumbFileName, "ab");
    if (pFile)
    {
        fwrite(m_pThumbFrame->data[0], 1, m_pThumbFrame->width * m_pThumbFrame->height * 2, pFile);
        fclose(pFile);
    }

    av_frame_free(&pFrame);
    av_frame_free(&m_pThumbFrame);

    closeDecoder();

    return ret;
}
Exemplo n.º 17
0
 bool Demuxer::didSeek(const Timer &timer, sf::Time oldPosition)
 {
     resetEndOfFileStatus();
     sf::Time newPosition = timer.getOffset();
     std::set< std::shared_ptr<Stream> > connectedStreams;
     
     if (m_connectedVideoStream)
         connectedStreams.insert(m_connectedVideoStream);
     if (m_connectedAudioStream)
         connectedStreams.insert(m_connectedAudioStream);
     if (m_connectedSubtitleStream)
         connectedStreams.insert(m_connectedSubtitleStream);
     
     CHECK(!connectedStreams.empty(), "Inconcistency error: seeking with no active stream");
     
     // Trivial seeking to beginning
     if (newPosition == sf::Time::Zero)
     {
         int64_t timestamp = 0;
         
         if (m_formatCtx->iformat->flags & AVFMT_SEEK_TO_PTS && m_formatCtx->start_time != AV_NOPTS_VALUE)
             timestamp += m_formatCtx->start_time;
         
         
         // Flush all streams
         for (std::shared_ptr<Stream> stream : connectedStreams)
             stream->flushBuffers();
         flushBuffers();
         
         // Seek to beginning
         int err = avformat_seek_file(m_formatCtx, -1, INT64_MIN, timestamp, INT64_MAX, AVSEEK_FLAG_BACKWARD);
         if (err < 0)
         {
             sfeLogError("Error while seeking at time " + s(newPosition.asMilliseconds()) + "ms");
             return false;
         }
     }
     else // Seeking to some other position
     {
         // Initial target seek point
         int64_t timestamp = newPosition.asSeconds() * AV_TIME_BASE;
         
         // < 0 = before seek point
         // > 0 = after seek point
         std::map< std::shared_ptr<Stream>, sf::Time> seekingGaps;
         
         static const float brokenSeekingThreshold = 60.f; // seconds
         bool didReseekBackward = false;
         bool didReseekForward = false;
         int tooEarlyCount = 0;
         int tooLateCount = 0;
         int brokenSeekingCount = 0;
         int ffmpegSeekFlags = AVSEEK_FLAG_BACKWARD;
         
         do
         {
             // Flush all streams
             for (std::shared_ptr<Stream> stream : connectedStreams)
                 stream->flushBuffers();
             flushBuffers();
             
             // Seek to new estimated target
             if (m_formatCtx->iformat->flags & AVFMT_SEEK_TO_PTS && m_formatCtx->start_time != AV_NOPTS_VALUE)
                 timestamp += m_formatCtx->start_time;
             
             int err = avformat_seek_file(m_formatCtx, -1, timestamp - 10 * AV_TIME_BASE,
                                          timestamp, timestamp, ffmpegSeekFlags);
             CHECK0(err, "avformat_seek_file failure");
             
             // Compute the new gap
             for (std::shared_ptr<Stream> stream : connectedStreams)
             {
                 sf::Time gap = stream->computeEncodedPosition() - newPosition;
                 seekingGaps[stream] = gap;
             }
             
             tooEarlyCount = 0;
             tooLateCount = 0;
             brokenSeekingCount = 0;
             
             // Check the current situation
             for (std::pair< std::shared_ptr<Stream>, sf::Time>&& gapByStream : seekingGaps)
             {
                 // < 0 = before seek point
                 // > 0 = after seek point
                 const sf::Time& gap = gapByStream.second;
                 float absoluteDiff = fabs(gap.asSeconds());
                 
                 // Before seek point
                 if (gap < sf::Time::Zero)
                 {
                     if (absoluteDiff > brokenSeekingThreshold)
                     {
                         brokenSeekingCount++;
                         tooEarlyCount++;
                     }
                 
                     // else: a bit early but not too much, this is the final situation we want
                 }
                 // After seek point
                 else if (gap > sf::Time::Zero)
                 {
                     tooLateCount++;
                 
                     if (absoluteDiff > brokenSeekingThreshold)
                         brokenSeekingCount++; // TODO: unhandled for now => should seek to non-key frame
                 }
                 
                 if (brokenSeekingCount > 0)
                     sfeLogWarning("Seeking on " + gapByStream.first->description() + " is broken! Gap: "
                                   + s(gap.asSeconds()) + "s");
             }
             
             CHECK(false == (tooEarlyCount && tooLateCount),
                   "Both too late and too early for different streams, unhandled situation!");
             
             // Define what to do next
             if (tooEarlyCount)
             {
                 // Go forward by 1 sec
                 timestamp += AV_TIME_BASE;
                 didReseekForward = true;
             }
             else if (tooLateCount)
             {
                 // Go backward by 1 sec
                 timestamp -= AV_TIME_BASE;
                 didReseekBackward = true;
             }
             
             if (brokenSeekingCount)
             {
                 if (ffmpegSeekFlags & AVSEEK_FLAG_ANY)
                 {
                     sfeLogError("Seeking is really broken in the media, giving up");
                     return false;
                 }
                 else
                 {
                     // Try to seek to non-key frame before giving up
                     // Image may be wrong but it's better than nothing :)
                     ffmpegSeekFlags |= AVSEEK_FLAG_ANY;
                     sfeLogError("Media has broken seeking index, trying to seek to non-key frame");
                 }
             }
             
             CHECK(!(didReseekBackward && didReseekForward), "infinitely seeking backward and forward");
         }
         while (tooEarlyCount != 0 || tooLateCount != 0);
     }
     
     return true;
 }
Exemplo n.º 18
0
jint Java_org_telegram_ui_Components_AnimatedFileDrawable_getVideoFrame(JNIEnv *env, jclass clazz, jobject ptr, jobject bitmap, jintArray data) {
    if (ptr == NULL || bitmap == nullptr) {
        return 0;
    }
    VideoInfo *info = (VideoInfo *) ptr;
    int ret = 0;
    int got_frame = 0;
    
    while (true) {
        if (info->pkt.size == 0) {
            ret = av_read_frame(info->fmt_ctx, &info->pkt);
            //LOGD("got packet with size %d", info->pkt.size);
            if (ret >= 0) {
                info->orig_pkt = info->pkt;
            }
        }
        
        if (info->pkt.size > 0) {
            ret = decode_packet(info, &got_frame);
            if (ret < 0) {
                if (info->has_decoded_frames) {
                    ret = 0;
                }
                info->pkt.size = 0;
            } else {
                //LOGD("read size %d from packet", ret);
                info->pkt.data += ret;
                info->pkt.size -= ret;
            }
            
            if (info->pkt.size == 0) {
                av_free_packet(&info->orig_pkt);
            }
        } else {
            info->pkt.data = NULL;
            info->pkt.size = 0;
            ret = decode_packet(info, &got_frame);
            if (ret < 0) {
                LOGE("can't decode packet flushed %s", info->src);
                return 0;
            }
            if (got_frame == 0) {
                if (info->has_decoded_frames) {
                    //LOGD("file end reached %s", info->src);
                    if ((ret = avformat_seek_file(info->fmt_ctx, -1, std::numeric_limits<int64_t>::min(), 0, std::numeric_limits<int64_t>::max(), 0)) < 0) {
                        LOGE("can't seek to begin of file %s, %s", info->src, av_err2str(ret));
                        return 0;
                    } else {
                        avcodec_flush_buffers(info->video_dec_ctx);
                    }
                }
            }
        }
        if (ret < 0) {
            return 0;
        }
        if (got_frame) {
            //LOGD("decoded frame with w = %d, h = %d, format = %d", info->frame->width, info->frame->height, info->frame->format);
            if (info->frame->format == AV_PIX_FMT_YUV420P || info->frame->format == AV_PIX_FMT_BGRA || info->frame->format == AV_PIX_FMT_YUVJ420P) {
                jint *dataArr = env->GetIntArrayElements(data, 0);
                if (dataArr != nullptr) {
                    dataArr[3] = (int) (1000 * info->frame->pkt_pts * av_q2d(info->video_stream->time_base));
                    env->ReleaseIntArrayElements(data, dataArr, 0);
                }
                
                void *pixels;
                if (AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0) {
                    if (info->frame->format == AV_PIX_FMT_YUV420P || info->frame->format == AV_PIX_FMT_YUVJ420P) {
                        //LOGD("y %d, u %d, v %d, width %d, height %d", info->frame->linesize[0], info->frame->linesize[2], info->frame->linesize[1], info->frame->width, info->frame->height);
                        libyuv::I420ToARGB(info->frame->data[0], info->frame->linesize[0], info->frame->data[2], info->frame->linesize[2], info->frame->data[1], info->frame->linesize[1], (uint8_t *) pixels, info->frame->width * 4, info->frame->width, info->frame->height);
                    } else if (info->frame->format == AV_PIX_FMT_BGRA) {
                        libyuv::ABGRToARGB(info->frame->data[0], info->frame->linesize[0], (uint8_t *) pixels, info->frame->width * 4, info->frame->width, info->frame->height);
                    }
                    AndroidBitmap_unlockPixels(env, bitmap);
                }
            }
            info->has_decoded_frames = true;
            av_frame_unref(info->frame);
            return 1;
        }
    }
    return 0;
}
Exemplo n.º 19
0
int decode_thread(void *arg) {

  VideoState *is = (VideoState *)arg;
  AVPacket pkt1, *packet = &pkt1;

  AVDictionary *io_dict = NULL;
  AVIOInterruptCB callback;

  int video_index = -1;
  int audio_index = -1;
  int i;

  int ret;
  int eof = 0;

  is->videoStream=-1;
  is->audioStream=-1;

  AVDictionary *options = NULL;
  av_dict_set(&options, "icy", "1", 0);
  av_dict_set(&options, "user-agent", "FFmpegMediaPlayer", 0);
    
  if (is->headers) {
    av_dict_set(&options, "headers", is->headers, 0);
  }

  if (is->offset > 0) {
    is->pFormatCtx = avformat_alloc_context();
    is->pFormatCtx->skip_initial_bytes = is->offset;
    //is->pFormatCtx->iformat = av_find_input_format("mp3");
  }

  // will interrupt blocking functions if we quit!
  callback.callback = decode_interrupt_cb;
  callback.opaque = is;
  if (avio_open2(&is->io_context, is->filename, 0, &callback, &io_dict))
  {
    fprintf(stderr, "Unable to open I/O for %s\n", is->filename);
    return -1;
  }

  // Open video file
  if(avformat_open_input(&is->pFormatCtx, is->filename, NULL, &options)!=0)
    return -1; // Couldn't open file

  // Retrieve stream information
  if(avformat_find_stream_info(is->pFormatCtx, NULL)<0)
    return -1; // Couldn't find stream information

  // Dump information about file onto standard error
  av_dump_format(is->pFormatCtx, 0, is->filename, 0);

  // Find the first video stream
  for(i=0; i<is->pFormatCtx->nb_streams; i++) {
    if(is->pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO &&
       video_index < 0) {
      video_index=i;
    }
    if(is->pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO &&
       audio_index < 0) {
      audio_index=i;
    }
      
    set_codec(is->pFormatCtx, i);
  }
  if(audio_index >= 0) {
    stream_component_open(is, audio_index);
  }
  if(video_index >= 0) {
    stream_component_open(is, video_index);
  }

  if(is->videoStream < 0 && is->audioStream < 0) {
  //if(is->videoStream < 0 || is->audioStream < 0) {
    fprintf(stderr, "%s: could not open codecs\n", is->filename);
    notify(is, MEDIA_ERROR, 0, 0);
    return 0;
  }

  set_rotation(is->pFormatCtx, is->audio_st, is->video_st);
  set_framerate(is->pFormatCtx, is->audio_st, is->video_st);
  set_filesize(is->pFormatCtx);
  set_chapter_count(is->pFormatCtx);

  // main decode loop

  for(;;) {
    if(is->quit) {
      break;
    }

    /*if (is->paused != is->last_paused) {
        is->last_paused = is->paused;
        if (is->paused)
            is->read_pause_return = av_read_pause(is->pFormatCtx);
        else
            av_read_play(is->pFormatCtx);
    }*/

    // seek stuff goes here
    if(is->seek_req) {
		int64_t seek_target = is->seek_pos;
		int64_t seek_min    = is->seek_rel > 0 ? seek_target - is->seek_rel + 2: INT64_MIN;
		int64_t seek_max    = is->seek_rel < 0 ? seek_target - is->seek_rel - 2: INT64_MAX;

		int ret = avformat_seek_file(is->pFormatCtx, -1, seek_min, seek_target, seek_max, is->seek_flags);
      if(ret < 0) {
	fprintf(stderr, "%s: error while seeking\n", is->pFormatCtx->filename);
      } else {
	if(is->audioStream >= 0) {
	  packet_queue_flush(&is->audioq);
	  packet_queue_put(is, &is->audioq, &is->flush_pkt);
	}
	if(is->videoStream >= 0) {
	  packet_queue_flush(&is->videoq);
	  packet_queue_put(is, &is->videoq, &is->flush_pkt);
	}
	notify(is, MEDIA_SEEK_COMPLETE, 0, 0);

      }
      is->seek_req = 0;
      eof = 0;
    }

    if (is->audioq.size >= MAX_AUDIOQ_SIZE && !is->prepared) {
        queueAudioSamples(&is->audio_player, is);

		notify(is, MEDIA_PREPARED, 0, 0);
    	is->prepared = 1;
    }

    if(is->audioq.size > MAX_AUDIOQ_SIZE ||
       is->videoq.size > MAX_VIDEOQ_SIZE) {
      SDL_Delay(10);
      continue;
    }
    if((ret = av_read_frame(is->pFormatCtx, packet)) < 0) {
      if (ret == AVERROR_EOF || !is->pFormatCtx->pb->eof_reached) {
          eof = 1;
    	  break;
      }

      if(is->pFormatCtx->pb->error == 0) {
	SDL_Delay(100); /* no error; wait for user input */
	continue;
      } else {
	break;
      }
    }
    // Is this a packet from the video stream?
    if(packet->stream_index == is->videoStream) {
      packet_queue_put(is, &is->videoq, packet);
    } else if(packet->stream_index == is->audioStream) {
      packet_queue_put(is, &is->audioq, packet);
    } else {
      av_free_packet(packet);
    }

	if (eof) {
		break;
	}
  }

  if (eof) {
      notify(is, MEDIA_PLAYBACK_COMPLETE, 0, 0);
  }
  return 0;
}
 JNIEXPORT jint JNICALL Java_com_jiuan_it_ipc_utils_RtspFromFFMPEG_thread_1RecvPacket
   (JNIEnv *env, jobject obj, jlong seek_pos, jint seek_req, jint isAudio)
 {
	LOGD("%s-------%d进入该函数", __FUNCTION__, __LINE__);
 	AVPacket *packet = (AVPacket *)av_malloc(sizeof(AVPacket));
 	av_init_packet(packet);
 	int index = 0;
 	int ret = -1;

 	//调整视频的播放位置的处理(快进、后退)
	if (seek_req) {
        int64_t seek_target = seek_pos;
        int64_t seek_min = INT64_MIN;
        int64_t seek_max = INT64_MAX;
        
        //LOGE("--------*********-----------seek_pos:%lld\n", seek_pos);
        //把APP的时间戳转换成设备的时间戳
        //int64_t seek_conv_target = av_rescale_q(seek_target, pCodecCtx_video->time_base, timebase_pri);
        //把设备的时间戳转换成APP的时间戳
        int64_t seek_conv_target = av_rescale_q(seek_target, timebase_pri, pCodecCtx_video->time_base);
        LOGE("--------*********-----------timebase_pri:%d\n", timebase_pri.den);
        LOGE("--------*********-----------time_base:%d\n", pCodecCtx_video->time_base.den);
		ret = avformat_seek_file(pFormatCtx, videoindex, seek_min, seek_conv_target, seek_max, 0);
		LOGE("--------*********-----------seek_conv_target:%lld\n", seek_conv_target);
		if (ret >= 0) {
			AVPacket_cbuf_free(&m_cbuf_video);
			AVPacket_cbuf_free(&m_cbuf_audio);
			ret = 1;
			goto Errlab;
		}
	}

	LOGD("av_read_frameing................\n");
	if (av_read_frame(pFormatCtx, packet)>=0)
	{
		if(packet->stream_index==videoindex)
		{
			//LOGE("packet_pts_video->pts = %f\n", packet.pts * av_q2d(pCodecCtx_video->time_base));
			LOGD("av_read_frame:OK\n");
			//AVPacket *packet_cpy = (AVPacket *)av_malloc(sizeof(AVPacket));
			//av_copy_packet(packet_cpy, &packet);
			cbuf_enqueue(&m_cbuf_video, packet);
			//LOGE("thread_1RecvPacket.m_cbuf.size:%d\n", m_cbuf_video.size);
			//av_free_packet(&packet);
		}
		else if(packet->stream_index==audioindex && isAudio)
		{
			//LOGE("packet_pts_audio->pts = %f\n", packet.pts * av_q2d(pCodecCtx_audio->time_base));
			LOGD("av_read_audio_frame:OK\n");
			//AVPacket *packet_cpy = (AVPacket *)av_malloc(sizeof(AVPacket));
			//av_copy_packet(packet_cpy, &packet);
			cbuf_enqueue(&m_cbuf_audio, packet);
			//LOGE("thread_1RecvPacket.m_cbuf.size:%d\n", m_cbuf_audio.size);
			//av_free_packet(&packet);
		}
		else
		{
			av_free_packet(packet);
		}
	 	ret = 0;
	}
	else
	{
		if (cbuf_empty(&m_cbuf_video)){
			LOGE("cbuf_empty:OK\n");
			ret = -1;
		}else {
			ret = 0;
		}

	}

Errlab:
 	return ret;
 }
Exemplo n.º 21
0
void Editor::seek_time(float seconds, bool display)
{
	int64_t ts_rel = seconds / m_videoTimeBase;
	int64_t req_ts = pts_val(m_timeStampStart + ts_rel);
	int64_t ts = pts_val(req_ts + m_timeFudge);
	int64_t min_ts = ts - 2.0 / m_videoTimeBase;
	int64_t max_ts = ts;
	
	int64_t pts_base = av_rescale_q(ts_rel + m_timeFudge, m_videoTimeBase_q, AV_TIME_BASE_Q);
	
	// From time to time, my receiver (Kathrein UFS-910) screws up
	// and gives me the start of the stream instead of the requested
	// offset. So we have to wrap this in a loop and try again...
	
	int tries;
	for(tries = 5; tries > 0; --tries)
	{
		loff_t byte_offset = (loff_t)-1;
		
		avcodec_flush_buffers(m_videoCodecCtx);
		
		// If we got an index file, use it
		if(m_indexFile)
			byte_offset = m_indexFile->bytePositionForPTS(pts_base);
		
		if(byte_offset != (loff_t)-1)
		{
			log_debug("Seeking to byte pos %'10lld", byte_offset);
			if(avformat_seek_file(m_stream, -1, 0, byte_offset, byte_offset, AVSEEK_FLAG_BYTE) < 0)
			{
				log_debug("Byte seeking to %fs failed", seconds);
				byte_offset = (loff_t)-1;
			}
		}
		
		// Fallback to binary search
		if(byte_offset == (loff_t)-1)
		{
			log_debug("Seeking to pts %'10lld", ts);
			if(avformat_seek_file(m_stream, m_videoID, min_ts, ts, max_ts, 0) < 0)
			{
				error("could not seek");
				return;
			}
		}
		
		resetBuffer();
		
		// Detect Kathrein bug
		if(byte_offset
			&& seconds > 1.0 // not actually at start of stream
			&& m_frameTimestamps[0] - m_timeStampFirstKey == 0) // bug
		{
			log_debug("KATHREIN BUG detected");
			continue;
		}
		
		break;
	}
	
	if(!tries)
		QMessageBox::critical(this, tr("Error"), tr("Seeking failed, sorry."));
	
	int64_t diff = req_ts - m_frameTimestamps[0];
	if(llabs(diff) > 20.0 / m_videoTimeBase)
		log_debug("seek_time: missed destination (PTS: %'10lld) by more than 20 seconds, fudge = %'10lld", 
			ts, m_frameTimestamps[0], diff, m_videoTimeBase * diff, m_timeFudge
		);
	
	m_timeFudge += diff;
	if(llabs(m_timeFudge) > 10.0 / m_videoTimeBase)
	{
		log_debug("Resetting time fudge value");
		m_timeFudge = 0;
	}
	
	if(display)
		displayCurrentFrame();
}
Exemplo n.º 22
0
	bool seekInternal(double t, int depth)
	{
		ResetRetries();
		emptyFrameQueue();
		audioHandler->clearQueue();

		int64_t firstTs = getFirstSeekTs();

		double backSeek = (double)depth * 2.0f + 1.0f;

		int64_t minTs = tsFromTime(t - backSeek - 2.5) + firstTs;
		int64_t ts = tsFromTime(t - backSeek) + firstTs;
		int64_t maxTs = tsFromTime(t - backSeek) + firstTs;

		// There is no discernible way to determine if negative timestamps are allowed
		// (or even required) to seek to low timestamps.
		// On some files you must seek to negative timestamps to be able to seek to 0
		// but on other files you get weird results from seeking to below 0.

		// So, every other try, we will allow seeking to negative timestamps.

		if((depth % 2) == 1){
			minTs = std::max((int64_t)0, minTs);
			ts = std::max((int64_t)0, minTs);
			maxTs = std::max((int64_t)0, minTs);
		}

		FlogD("Trying to seek to minTs: " << minTs << " ts: " << ts << " maxTs: " << maxTs << " with firsTs: " << firstTs);

		int flags = 0;
		
		if(ts < pFormatCtx->streams[videoStream]->cur_dts)
			flags |= AVSEEK_FLAG_BACKWARD;

		int seekRet = avformat_seek_file(pFormatCtx, videoStream, minTs, ts, maxTs, flags);

		if(seekRet > 0){
			FlogD("avformat_seek_file failed, returned " << seekRet);
			return false;
		}

		avcodec_flush_buffers(pCodecCtx);

		double newTime = t + timeFromTs(firstPts);
		double actualTime = skipToTs(newTime);

		// consider the seek failed and try again if the actual time diffs more than .5 seconds
		// from the desired new time. 
		
		FlogD("wanted to seek to " << newTime << " and ended up at " << actualTime);

		bool ret = true;

		if(fabsf(newTime - actualTime) > .5){
			if(depth < 5){
				FlogD("not good enough, trying again");
				return seekInternal(t, depth + 1);
			}
			else{
				ret = false;
				FlogW("seek failed, wanted to seek to " << newTime << " and ended up at " << actualTime);
			}
		}

		timeHandler->SetTime(actualTime);

		stepIntoQueue = true;

		audioHandler->onSeek();

		return ret;
	}
Exemplo n.º 23
0
SINT SoundSourceFFmpeg::seekSampleFrame(SINT frameIndex) {
    DEBUG_ASSERT(isValidFrameIndex(frameIndex));

    int ret = 0;
    qint64 i = 0;
    struct ffmpegLocationObject *l_STestObj = nullptr;

    if (frameIndex < 0 || frameIndex < m_lCacheStartFrame) {
        // Seek to set (start of the stream which is FFmpeg frame 0)
        // because we are dealing with compressed audio FFmpeg takes
        // best of to seek that point (in this case 0 Is always there)
        // in every other case we should provide MIN and MAX tolerance
        // which we can take.
        // FFmpeg just just can't take zero as MAX tolerance so we try to
        // just make some tolerable (which is never used because zero point
        // should always be there) some number (which is 0xffff 65535)
        // that is chosen because in WMA frames can be that big and if it's
        // smaller than the frame we are seeking we can get into error
        ret = avformat_seek_file(m_pFormatCtx,
                                 m_iAudioStream,
                                 0,
                                 0,
                                 0xffff,
                                 AVSEEK_FLAG_BACKWARD);

        if (ret < 0) {
            qDebug() << "SoundSourceFFmpeg::seek: Can't seek to 0 byte!";
            return -1;
        }

        clearCache();
        m_lCacheStartFrame = 0;
        m_lCacheEndFrame = 0;
        m_lCacheLastPos = 0;
        m_lCacheFramePos = 0;
        m_lStoredSeekPoint = -1;


        // Try to find some jump point near to
        // where we are located so we don't needed
        // to try guess it
        if (m_SJumpPoints.size() > 0) {
            l_STestObj = m_SJumpPoints.first();

            if (frameIndex > l_STestObj->startFrame) {
                for (i = 0; i < m_SJumpPoints.size(); i++) {
                    if (m_SJumpPoints[i]->startFrame >= frameIndex) {
                        if (i > 0) {
                            i--;
                        }

                        m_lCacheFramePos = m_SJumpPoints[i]->startFrame;
                        m_lStoredSeekPoint = m_SJumpPoints[i]->pos;
                        m_SStoredJumpPoint = m_SJumpPoints[i];
                        break;
                    }
                }
            }
        }

        if (frameIndex == 0) {
            // Because we are in the beginning just read cache full
            // but leave 50 of just in case
            // -1 one means we are seeking from current position and
            // filling the cache
            readFramesToCache((AUDIOSOURCEFFMPEG_CACHESIZE - 50),
                              AUDIOSOURCEFFMPEG_FILL_FROM_CURRENTPOS);
        }
    }

    if (m_lCacheEndFrame <= frameIndex) {
        // Cache tries to read until it gets to frameIndex
        // after that we still read 100 FFmpeg frames to memory
        // so we have good cache to go forward (100) and backward (900)
        // from the point
        readFramesToCache(100, frameIndex);
    }

    m_currentMixxxFrameIndex = frameIndex;

    m_bIsSeeked = true;

    return frameIndex;
}