static void *receiver_thread(void *arg) { int i, ret = 0; struct receiver_data *rd = arg; for (i = 0; i < rd->workload; i++) { if (rand() % rd->workload < rd->workload / 10) { av_log(NULL, AV_LOG_INFO, "receiver #%d: flushing the queue\n", rd->id); av_thread_message_flush(rd->queue); } else { struct message msg; AVDictionary *meta; AVDictionaryEntry *e; ret = av_thread_message_queue_recv(rd->queue, &msg, 0); if (ret < 0) break; av_assert0(msg.magic == MAGIC); meta = msg.frame->metadata; e = av_dict_get(meta, "sig", NULL, 0); av_log(NULL, AV_LOG_INFO, "got \"%s\" (%p)\n", e->value, msg.frame); av_frame_free(&msg.frame); } } av_log(NULL, AV_LOG_INFO, "consumed enough (%d), stop\n", i); av_thread_message_queue_set_err_send(rd->queue, ret < 0 ? ret : AVERROR_EOF); return NULL; }
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); }
static void *sender_thread(void *arg) { int i, ret = 0; struct sender_data *wd = arg; av_log(NULL, AV_LOG_INFO, "sender #%d: workload=%d\n", wd->id, wd->workload); for (i = 0; i < wd->workload; i++) { if (rand() % wd->workload < wd->workload / 10) { av_log(NULL, AV_LOG_INFO, "sender #%d: flushing the queue\n", wd->id); av_thread_message_flush(wd->queue); } else { char *val; AVDictionary *meta = NULL; struct message msg = { .magic = MAGIC, .frame = av_frame_alloc(), }; if (!msg.frame) { ret = AVERROR(ENOMEM); break; } /* we add some metadata to identify the frames */ val = av_asprintf("frame %d/%d from sender %d", i + 1, wd->workload, wd->id); if (!val) { av_frame_free(&msg.frame); ret = AVERROR(ENOMEM); break; } ret = av_dict_set(&meta, "sig", val, AV_DICT_DONT_STRDUP_VAL); if (ret < 0) { av_frame_free(&msg.frame); break; } msg.frame->metadata = meta; /* allocate a real frame in order to simulate "real" work */ msg.frame->format = AV_PIX_FMT_RGBA; msg.frame->width = 320; msg.frame->height = 240; ret = av_frame_get_buffer(msg.frame, 32); if (ret < 0) { av_frame_free(&msg.frame); break; } /* push the frame in the common queue */ av_log(NULL, AV_LOG_INFO, "sender #%d: sending my work (%d/%d frame:%p)\n", wd->id, i + 1, wd->workload, msg.frame); ret = av_thread_message_queue_send(wd->queue, &msg, 0); if (ret < 0) { av_frame_free(&msg.frame); break; } } } av_log(NULL, AV_LOG_INFO, "sender #%d: my work is done here (%s)\n", wd->id, av_err2str(ret)); av_thread_message_queue_set_err_recv(wd->queue, ret < 0 ? ret : AVERROR_EOF); return NULL; }