mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	videoconvert-ffmpeg: fix passthrough mode
Keep the passthrough flag up to date when we unset a port format or when it changes. We should only fill in the buffer data/fd when the ALLOC flag is set. We should only take the passthrough input buffer as output when we are in passthrough mode. Copy the header metadata.
This commit is contained in:
		
							parent
							
								
									2873d7a6cc
								
							
						
					
					
						commit
						f8dcf32c8d
					
				
					 1 changed files with 40 additions and 17 deletions
				
			
		| 
						 | 
					@ -63,6 +63,7 @@ struct buffer {
 | 
				
			||||||
	struct spa_list link;
 | 
						struct spa_list link;
 | 
				
			||||||
	struct spa_buffer *buf;
 | 
						struct spa_buffer *buf;
 | 
				
			||||||
	void *datas[MAX_DATAS];
 | 
						void *datas[MAX_DATAS];
 | 
				
			||||||
 | 
						struct spa_meta_header *h;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct port {
 | 
					struct port {
 | 
				
			||||||
| 
						 | 
					@ -1480,6 +1481,7 @@ static int port_set_format(void *object,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (format == NULL) {
 | 
						if (format == NULL) {
 | 
				
			||||||
		port->have_format = false;
 | 
							port->have_format = false;
 | 
				
			||||||
 | 
							this->fmt_passthrough = false;
 | 
				
			||||||
		clear_buffers(this, port);
 | 
							clear_buffers(this, port);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		struct spa_video_info info = { 0 };
 | 
							struct spa_video_info info = { 0 };
 | 
				
			||||||
| 
						 | 
					@ -1566,8 +1568,8 @@ static int port_set_format(void *object,
 | 
				
			||||||
			dir->format = info;
 | 
								dir->format = info;
 | 
				
			||||||
			dir->have_format = true;
 | 
								dir->have_format = true;
 | 
				
			||||||
			if (odir->have_format) {
 | 
								if (odir->have_format) {
 | 
				
			||||||
				if (memcmp(&odir->format, &dir->format, sizeof(dir->format)) == 0)
 | 
									this->fmt_passthrough =
 | 
				
			||||||
					this->fmt_passthrough = true;
 | 
										(memcmp(&odir->format, &dir->format, sizeof(dir->format)) == 0);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			this->setup = false;
 | 
								this->setup = false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -1676,8 +1678,8 @@ impl_node_port_use_buffers(void *object,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	port = GET_PORT(this, direction, port_id);
 | 
						port = GET_PORT(this, direction, port_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_log_debug(this->log, "%p: use buffers %d on port %d:%d",
 | 
						spa_log_debug(this->log, "%p: use buffers %d on port %d:%d flags %08x",
 | 
				
			||||||
			this, n_buffers, direction, port_id);
 | 
								this, n_buffers, direction, port_id, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	clear_buffers(this, port);
 | 
						clear_buffers(this, port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1697,6 +1699,8 @@ impl_node_port_use_buffers(void *object,
 | 
				
			||||||
		b->id = i;
 | 
							b->id = i;
 | 
				
			||||||
		b->flags = 0;
 | 
							b->flags = 0;
 | 
				
			||||||
		b->buf = buffers[i];
 | 
							b->buf = buffers[i];
 | 
				
			||||||
 | 
							b->h = spa_buffer_find_meta_data(b->buf,
 | 
				
			||||||
 | 
									SPA_META_Header, sizeof(struct spa_meta_header));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (n_datas != port->blocks) {
 | 
							if (n_datas != port->blocks) {
 | 
				
			||||||
			spa_log_error(this->log, "%p: invalid blocks %d on buffer %d",
 | 
								spa_log_error(this->log, "%p: invalid blocks %d on buffer %d",
 | 
				
			||||||
| 
						 | 
					@ -1712,8 +1716,11 @@ impl_node_port_use_buffers(void *object,
 | 
				
			||||||
			for (j = 0; j < n_datas; j++) {
 | 
								for (j = 0; j < n_datas; j++) {
 | 
				
			||||||
				b->datas[j] = other->buffers[i % other->n_buffers].datas[j];
 | 
									b->datas[j] = other->buffers[i % other->n_buffers].datas[j];
 | 
				
			||||||
				maxsize = SPA_MAX(maxsize, d[j].maxsize);
 | 
									maxsize = SPA_MAX(maxsize, d[j].maxsize);
 | 
				
			||||||
 | 
									spa_log_debug(this->log, "buffer %d: mem:%d passthrough:%p maxsize:%d",
 | 
				
			||||||
 | 
											i, j, b->datas[j], d[j].maxsize);
 | 
				
			||||||
 | 
									b->buf->datas[j].data = b->datas[j];
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			*b->buf = *other->buffers[i % other->n_buffers].buf;
 | 
					
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			for (j = 0; j < n_datas; j++) {
 | 
								for (j = 0; j < n_datas; j++) {
 | 
				
			||||||
				void *data = d[j].data;
 | 
									void *data = d[j].data;
 | 
				
			||||||
| 
						 | 
					@ -1732,6 +1739,8 @@ impl_node_port_use_buffers(void *object,
 | 
				
			||||||
							this, j, i);
 | 
												this, j, i);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				b->datas[j] = data;
 | 
									b->datas[j] = data;
 | 
				
			||||||
 | 
									spa_log_debug(this->log, "buffer %d: mem:%d mapped:%p maxsize:%d",
 | 
				
			||||||
 | 
											i, j, data, d[j].maxsize);
 | 
				
			||||||
				maxsize = SPA_MAX(maxsize, d[j].maxsize);
 | 
									maxsize = SPA_MAX(maxsize, d[j].maxsize);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -1851,11 +1860,12 @@ static int impl_node_process(void *object)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sbuf = &in_port->buffers[input->buffer_id];
 | 
						sbuf = &in_port->buffers[input->buffer_id];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((dbuf = peek_buffer(this, out_port)) == NULL) {
 | 
						if (this->fmt_passthrough) {
 | 
				
			||||||
                spa_log_error(this->log, "%p: out of buffers", this);
 | 
							dbuf = &out_port->buffers[input->buffer_id];
 | 
				
			||||||
 | 
						} else if ((dbuf = peek_buffer(this, out_port)) == NULL) {
 | 
				
			||||||
 | 
							spa_log_error(this->log, "%p: out of buffers", this);
 | 
				
			||||||
		return -EPIPE;
 | 
							return -EPIPE;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	dbuf = &out_port->buffers[input->buffer_id];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_log_trace(this->log, "%d %p:%p %d %d %d", input->buffer_id, sbuf->buf->datas[0].chunk,
 | 
						spa_log_trace(this->log, "%d %p:%p %d %d %d", input->buffer_id, sbuf->buf->datas[0].chunk,
 | 
				
			||||||
			dbuf->buf->datas[0].chunk, sbuf->buf->datas[0].chunk->size,
 | 
								dbuf->buf->datas[0].chunk, sbuf->buf->datas[0].chunk->size,
 | 
				
			||||||
| 
						 | 
					@ -1866,6 +1876,9 @@ static int impl_node_process(void *object)
 | 
				
			||||||
		this->decoder.packet->data = sbuf->datas[0];
 | 
							this->decoder.packet->data = sbuf->datas[0];
 | 
				
			||||||
		this->decoder.packet->size = sbuf->buf->datas[0].chunk->size;
 | 
							this->decoder.packet->size = sbuf->buf->datas[0].chunk->size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							spa_log_trace(this->log, "decode %p:%d", this->decoder.packet->data,
 | 
				
			||||||
 | 
									this->decoder.packet->size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if ((res = avcodec_send_packet(this->decoder.context, this->decoder.packet)) < 0) {
 | 
							if ((res = avcodec_send_packet(this->decoder.context, this->decoder.packet)) < 0) {
 | 
				
			||||||
			spa_log_error(this->log, "failed to send frame to codec: %d %p:%d",
 | 
								spa_log_error(this->log, "failed to send frame to codec: %d %p:%d",
 | 
				
			||||||
					res, this->decoder.packet->data, this->decoder.packet->size);
 | 
										res, this->decoder.packet->data, this->decoder.packet->size);
 | 
				
			||||||
| 
						 | 
					@ -1887,8 +1900,11 @@ static int impl_node_process(void *object)
 | 
				
			||||||
		f->width = in->width;
 | 
							f->width = in->width;
 | 
				
			||||||
		f->height = in->height;
 | 
							f->height = in->height;
 | 
				
			||||||
		for (uint_fast32_t i = 0; i < sbuf->buf->n_datas; ++i) {
 | 
							for (uint_fast32_t i = 0; i < sbuf->buf->n_datas; ++i) {
 | 
				
			||||||
			f->data[i] = sbuf->datas[i];
 | 
								spa_log_trace(this->log, "in %d %ld %p %d", sbuf->id, i,
 | 
				
			||||||
			f->linesize[i] = sbuf->buf->datas[i].chunk->stride;
 | 
										sbuf->datas[i], sbuf->buf->datas[i].chunk->size);
 | 
				
			||||||
 | 
								datas[i] = f->data[i] = sbuf->datas[i];
 | 
				
			||||||
 | 
								strides[i] = f->linesize[i] = sbuf->buf->datas[i].chunk->stride;
 | 
				
			||||||
 | 
								sizes[i] = sbuf->buf->datas[i].chunk->size;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1902,8 +1918,14 @@ static int impl_node_process(void *object)
 | 
				
			||||||
					out->width, out->height, out->pix_fmt,
 | 
										out->width, out->height, out->pix_fmt,
 | 
				
			||||||
					0, NULL, NULL, NULL);
 | 
										0, NULL, NULL, NULL);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							spa_log_trace(this->log, "convert");
 | 
				
			||||||
		sws_scale_frame(this->convert.context, this->convert.frame, f);
 | 
							sws_scale_frame(this->convert.context, this->convert.frame, f);
 | 
				
			||||||
		f = this->convert.frame;
 | 
							f = this->convert.frame;
 | 
				
			||||||
 | 
							for (uint_fast32_t i = 0; i < dbuf->buf->n_datas; ++i) {
 | 
				
			||||||
 | 
								datas[i] = f->data[i];
 | 
				
			||||||
 | 
								strides[i] = f->linesize[i];
 | 
				
			||||||
 | 
								sizes[i] = out->size[i];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* do encoding */
 | 
						/* do encoding */
 | 
				
			||||||
	if (this->encoder.codec) {
 | 
						if (this->encoder.codec) {
 | 
				
			||||||
| 
						 | 
					@ -1918,12 +1940,7 @@ static int impl_node_process(void *object)
 | 
				
			||||||
		datas[0] = this->encoder.packet->data;
 | 
							datas[0] = this->encoder.packet->data;
 | 
				
			||||||
		sizes[0] = this->encoder.packet->size;
 | 
							sizes[0] = this->encoder.packet->size;
 | 
				
			||||||
		strides[0] = 1;
 | 
							strides[0] = 1;
 | 
				
			||||||
	} else {
 | 
							spa_log_trace(this->log, "encode %p %d", datas[0], sizes[0]);
 | 
				
			||||||
		for (uint_fast32_t i = 0; i < dbuf->buf->n_datas; ++i) {
 | 
					 | 
				
			||||||
			datas[i] = f->data[i];
 | 
					 | 
				
			||||||
			strides[i] = f->linesize[i];
 | 
					 | 
				
			||||||
			sizes[i] = out->size[i];
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* write to output */
 | 
						/* write to output */
 | 
				
			||||||
| 
						 | 
					@ -1937,9 +1954,15 @@ static int impl_node_process(void *object)
 | 
				
			||||||
			dbuf->buf->datas[i].chunk->stride = strides[i];
 | 
								dbuf->buf->datas[i].chunk->stride = strides[i];
 | 
				
			||||||
			dbuf->buf->datas[i].chunk->size = sizes[i];
 | 
								dbuf->buf->datas[i].chunk->size = sizes[i];
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							spa_log_trace(this->log, "out %d %ld %p %d", dbuf->id, i,
 | 
				
			||||||
 | 
									dbuf->buf->datas[i].data,
 | 
				
			||||||
 | 
									dbuf->buf->datas[i].chunk->size);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	dequeue_buffer(this, out_port, dbuf);
 | 
						dequeue_buffer(this, out_port, dbuf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sbuf->h && dbuf->h)
 | 
				
			||||||
 | 
							*dbuf->h = *sbuf->h;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	output->buffer_id = dbuf->id;
 | 
						output->buffer_id = dbuf->id;
 | 
				
			||||||
	output->status = SPA_STATUS_HAVE_DATA;
 | 
						output->status = SPA_STATUS_HAVE_DATA;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue