bool RtspStreamWorker::openCodec(AVStream *stream, AVDictionary *options) { startInterruptableOperation(5); AVCodec *codec = avcodec_find_decoder(stream->codec->codec_id); AVDictionary *optionsCopy = 0; av_dict_copy(&optionsCopy, options, 0); startInterruptableOperation(5); int errorCode = avcodec_open2(stream->codec, codec, &optionsCopy); av_dict_free(&optionsCopy); return 0 == errorCode; }
AVFrame * RtspStreamWorker::extractVideoFrame(AVPacket &packet) { AVFrame *frame = av_frame_alloc(); startInterruptableOperation(5); int pictureAvailable; int re = avcodec_decode_video2(m_ctx->streams[m_videoStreamIndex]->codec, frame, &pictureAvailable, &packet); if (re == 0) { return 0; } if (re < 0) { m_decodeErrorsCnt++; if (m_decodeErrorsCnt >= maxDecodeErrors) { emit fatalError(QString::fromLatin1("Decoding error: %1").arg(errorMessageFromCode(re))); } av_free(frame); return 0; } m_decodeErrorsCnt = 0; //reset error counter if avcodec_decode_video2() call was successful packet.size -= re; packet.data += re; if (!pictureAvailable) { av_free(frame); return 0; } return frame; }
AVFrame * RtspStreamWorker::extractAudioFrame(AVPacket &packet) { AVFrame *frame = av_frame_alloc(); startInterruptableOperation(5); int frameAvailable; int ret = avcodec_decode_audio4(m_ctx->streams[m_audioStreamIndex]->codec, frame, &frameAvailable, &packet); if (ret == 0) return 0; if (ret < 0) { av_free(frame); return 0; } packet.size -= ret; packet.data += ret; if (!frameAvailable) { av_free(frame); return 0; } return frame; }
AVFrame * RtspStreamWorker::extractFrame(AVPacket &packet, bool *breakLoop) { *breakLoop = false; AVFrame *frame = avcodec_alloc_frame(); startInterruptableOperation(5); int pictureAvailable; int re = avcodec_decode_video2(m_ctx->streams[0]->codec, frame, &pictureAvailable, &packet); if (re == 0) { *breakLoop = true; return 0; } if (re < 0) { emit fatalError(QString::fromLatin1("Decoding error: %1").arg(errorMessageFromCode(re))); av_free(frame); *breakLoop = true; return 0; } packet.size -= re; packet.data += re; if (!pictureAvailable) { av_free(frame); return 0; } return frame; }
RtspStreamWorker::~RtspStreamWorker() { if (!m_ctx) return; for (unsigned int i = 0; i < m_ctx->nb_streams; ++i) { avcodec_close(m_ctx->streams[i]->codec); } startInterruptableOperation(5); avformat_close_input(&m_ctx); }
bool RtspStreamWorker::findStreamInfo(AVFormatContext* context, AVDictionary* options) { AVDictionary **streamOptions = createStreamsOptions(context, options); startInterruptableOperation(20); int errorCode = avformat_find_stream_info(context, streamOptions); destroyStreamOptions(context, streamOptions); if (errorCode < 0) { emit fatalError(QString::fromLatin1("Find stream error: %1").arg(errorMessageFromCode(errorCode))); return false; } return true; }
bool RtspStreamWorker::openInput(AVFormatContext **context, AVDictionary *options) { AVDictionary *optionsCopy = 0; av_dict_copy(&optionsCopy, options, 0); startInterruptableOperation(20); int errorCode = avformat_open_input(context, qPrintable(m_url.toString()), NULL, &optionsCopy); av_dict_free(&optionsCopy); if (errorCode < 0) { emit fatalError(QString::fromLatin1("Open error: %1").arg(errorMessageFromCode(errorCode))); return false; } return true; }
AVPacket RtspStreamWorker::readPacket(bool *ok) { if (ok) *ok = true; AVPacket packet; startInterruptableOperation(30); int re = av_read_frame(m_ctx, &packet); if (0 == re) return packet; emit fatalError(QString::fromLatin1("Reading error: %1").arg(errorMessageFromCode(re))); av_packet_unref(&packet); if (ok) *ok = false; return packet; }
void RtspStreamWorker::processVideoFrame(struct AVFrame *rawFrame) { Q_ASSERT(m_frameFormatter); startInterruptableOperation(5); m_frameQueue->enqueue(m_frameFormatter->formatFrame(rawFrame)); }