if (!priv)
return -ENOMEM;
- pthread_mutex_init(&priv->mutex);
- pthread_cond_init (&priv->cond);
-
- priv->tid = -1;
priv->vidx = -1;
priv->aidx = -1;
+ priv->vframe = av_frame_alloc();
+ if (!priv->vframe) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ priv->aframe = av_frame_alloc();
+ if (!priv->aframe) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
ret = avformat_open_input(&priv->fmt_ctx, path, NULL, NULL);
if (ret < 0) {
scf_loge("ret: %s\n", av_err2str(ret));
if (priv->adec_ctx)
avcodec_close(priv->adec_ctx);
+ if (priv->vframe)
+ av_frame_free(&priv->vframe);
+
+ if (priv->aframe)
+ av_frame_free(&priv->aframe);
+
free(priv);
return ret;
}
simp_ffmpeg_t* priv;
if (io) {
+ pthread_mutex_lock(&io->mutex);
+ io->exit = 1;
+ while (-1 != io->tid) {
+ pthread_cond_signal(&io->cond);
+ pthread_cond_signal(&io->cond);
+ }
+ pthread_mutex_unlock(&io->mutex);
+
priv = io->priv;
if (priv) {
-
if (priv->fmt_ctx)
avformat_close_input(&priv->fmt_ctx);
if (priv->adec_ctx)
avcodec_close(priv->adec_ctx);
+ if (priv->vframe)
+ av_frame_free(&priv->vframe);
+
+ if (priv->aframe)
+ av_frame_free(&priv->aframe);
+
free(priv);
}
}
return 0;
}
+int __ffmpeg_decode(simp_avio_t* io, AVCodecContext* dec_ctx, AVPacket* pkt, AVFrame* frame, scf_list_t* h)
+{
+ int ret = avcodec_send_packet(dec_ctx, pkt);
+ if (ret < 0) {
+ scf_loge("avcodec_send_packet error, ret: %s\n", av_err2str(ret));
+ return ret;
+ }
+
+ while (ret >= 0) {
+ ret = avcodec_receive_frame(dec_ctx, frame);
+
+ if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
+ break;
+ else if (ret < 0) {
+ printf("avcodec_receive_frame error, ret: %d, %s\n", ret, av_err2str(ret));
+ return ret;
+ }
+
+ frame->pts = frame->best_effort_timestamp;
+
+ simp_frame_t* f = simp_frame_alloc();
+ if (!f)
+ return -ENOMEM;
+
+ ret = av_frame_copy(f->frame, frame);
+ if (ret < 0)
+ return ret;
+
+ pthread_mutex_lock(&io->mutex);
+ scf_list_add_tail(h, &f->list);
+ pthread_cond_signal(&io->cond);
+ pthread_mutex_unlock(&io->mutex);
+ }
+
+ return 0;
+}
+
void* __ffmpeg_run(void* arg)
{
- simp_avio_t* io = arg;
- simp_ffmpeg_t* priv = io->priv;
- AVPacket* pkt;
+ simp_avio_t* io = arg;
+ simp_ffmpeg_t* priv = io->priv;
+ AVPacket* pkt = NULL;
+
+ int key_frame = 0;
pkt = av_packet_alloc();
if (!pkt)
- return NULL;
-
- int key_frame = 0;
+ goto end;
while (!priv->exit) {
if (ret < 0) {
scf_loge("av_read_frame error, ret: %s\n", av_err2str(ret));
av_packet_free(&pkt);
+ priv->error = ret;
break;
}
continue;
}
+ ret = __ffmpeg_decode(io, priv->adec_ctx, pkt, priv->aframe, &io->ain);
+ if (ret < 0) {
+ io->error = ret;
+ goto end;
+ }
+
} else if (pkt->stream_index == priv->vidx) {
if (pkt->flags & AV_PKT_FLAG_KEY)
continue;
}
- ret = avcodec_send_packet(priv->vdec_ctx, pkt);
- av_packet_unref(&pkt);
+ ret = __ffmpeg_decode(io, priv->vdec_ctx, pkt, priv->vframe, &io->vin);
if (ret < 0) {
- scf_loge("avcodec_send_packet error, ret: %s\n", av_err2str(ret));
- break;
- }
-
- while (ret >= 0) {
- ret = avcodec_receive_frame(priv->vdec_ctx, frame);
+ io->error = ret;
+ goto end;
}
-
- } else {
- av_packet_unref(pkt);
- continue;
}
+
+ av_packet_unref(&pkt);
}
+end:
+ if (pkt)
+ av_packet_free(&pkt);
+
+ pthread_mutex_lock(&io->mutex);
+ io->tid = -1;
+ pthread_cond_signal(&io->cond);
+ pthread_mutex_unlock(&io->mutex);
+
return NULL;
}
static int _ffmpeg_run(simp_avio_t* io)
{
- simp_ffmpeg_t* priv = io->priv;
-
- if (pthread_create(&priv->tid, NULL, __ffmpeg_run, io)) {
+ if (pthread_create(&io->tid, NULL, __ffmpeg_run, io)) {
scf_loge("\n");
return -1;
}
return 0;
}
+simp_avio_ops_t simp_avio_ffmpeg =
+{
+ .type = "ffmpeg_input",
+ .open = _ffmpeg_open,
+ .close = _ffmpeg_close,
+ .run = _ffmpeg_run,
+};
+