You can try these two solutions where prod is the name of your table :
Solution 1 with Window function
SELECT DISTINCT ON (t.Product)
t.Product
, nth_value(t.Quantity, m.median) OVER (PARTITION BY t.Product ORDER BY Quantity ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS median_Qty
FROM prod AS t
INNER JOIN
( SELECT Product, round(count(*)/2+1) :: integer AS median
FROM prod
GROUP BY Product
) AS m
ON m.Product = t.Product
Solution 2 without Window function
This solution is based on the SELECT ... LIMIT 1 OFFSET median query where median is a value only known at the run time, so this query must be implemented as a dynamic statement within a plpgsql function whose input parameter is the Product :
CREATE OR REPLACE FUNCTION median_quantity(INOUT myProduct varchar(1), OUT Median_Quantity integer)
RETURNS setof record LANGUAGE plpgsql AS
$$
DECLARE
median integer ;
BEGIN
SELECT round(count(*)/2) :: integer
INTO median
FROM prod
WHERE Product = myProduct ;
RETURN QUERY EXECUTE E'
SELECT Product, Quantity
FROM prod
WHERE Product = ' || quote_nullable(myProduct) || '
ORDER BY Quantity
LIMIT 1
OFFSET ' || median ;
END ;
$$ ;
The expected result is given by the query :
SELECT m.myProduct, m.Median_Quantity
FROM
( SELECT DISTINCT ON (Product)
Product
FROM prod
) AS p
CROSS JOIN LATERAL median_quantity(p.Product) AS m
All the details in dbfiddle