proton: Add media files.
The media files are used in new media converter. CW-Bug-Id: #23225
This commit is contained in:
parent
da36c977f9
commit
40494f74a1
6 changed files with 299 additions and 0 deletions
12
Makefile.in
12
Makefile.in
|
@ -688,6 +688,18 @@ symstore-tarball:
|
||||||
$(SYMSTORE_OBJ64)/symstore --skip-managed $(DST_BASE) $(OBJ)/symstore/$(BUILD_NAME)
|
$(SYMSTORE_OBJ64)/symstore --skip-managed $(DST_BASE) $(OBJ)/symstore/$(BUILD_NAME)
|
||||||
cd $(OBJ)/symstore/$(BUILD_NAME) && zip -r ../$(BUILD_NAME)-symstore.zip . >& /dev/null
|
cd $(OBJ)/symstore/$(BUILD_NAME) && zip -r ../$(BUILD_NAME)-symstore.zip . >& /dev/null
|
||||||
|
|
||||||
|
##
|
||||||
|
## Media
|
||||||
|
##
|
||||||
|
|
||||||
|
DIST_MEDIA := $(DST_DIR)/share/media
|
||||||
|
$(DIST_MEDIA):
|
||||||
|
mkdir -p $@
|
||||||
|
cp $(SRCDIR)/media/blank.mkv $@
|
||||||
|
cp $(SRCDIR)/media/blank.ptna $@
|
||||||
|
|
||||||
|
all-dist: $(DIST_MEDIA)
|
||||||
|
|
||||||
##
|
##
|
||||||
## Fonts
|
## Fonts
|
||||||
##
|
##
|
||||||
|
|
12
media/Makefile
Normal file
12
media/Makefile
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
all: blank.mkv blank.ptna
|
||||||
|
|
||||||
|
blank.mkv:
|
||||||
|
#120 frames @ 30 FPS == 4 seconds
|
||||||
|
gst-launch-1.0 videotestsrc num-buffers=120 pattern=smpte ! 'video/x-raw,format=(string)I420,width=320,height=240,framerate=(fraction)30/1' ! av1enc ! queue ! mux. audiotestsrc num-buffers=400 freq=0 samplesperbuffer=441 ! 'audio/x-raw,rate=48000,channels=2' ! opusenc ! queue ! mux. matroskamux name=mux ! filesink location=blank.mkv
|
||||||
|
|
||||||
|
make_blank_ptna: make_blank_ptna.c
|
||||||
|
gcc -Wall -O2 $(shell pkg-config --cflags opus) -o $@ $< -lm $(shell pkg-config --libs opus)
|
||||||
|
|
||||||
|
blank.ptna: make_blank_ptna
|
||||||
|
./make_blank_ptna $@
|
||||||
|
|
BIN
media/blank.mkv
Normal file
BIN
media/blank.mkv
Normal file
Binary file not shown.
BIN
media/blank.ptna
Normal file
BIN
media/blank.ptna
Normal file
Binary file not shown.
271
media/make_blank_ptna.c
Normal file
271
media/make_blank_ptna.c
Normal file
|
@ -0,0 +1,271 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Valve Corporation
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
* other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Dumps a "blank" Proton Audio sample. For documentation of the Proton Audio
|
||||||
|
* format, see audioconv.rs. */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <opus/opus.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x))
|
||||||
|
|
||||||
|
/* indexes into frame_sizes[] */
|
||||||
|
#define FRAME_2p5MS 0
|
||||||
|
#define FRAME_SMALLEST FRAME_2p5MS
|
||||||
|
#define FRAME_5MS 1
|
||||||
|
#define FRAME_10MS 2
|
||||||
|
#define FRAME_20MS 3
|
||||||
|
#define FRAME_40MS 4
|
||||||
|
#define FRAME_60MS 5
|
||||||
|
#define FRAME_LARGEST FRAME_60MS
|
||||||
|
|
||||||
|
/* sample properties */
|
||||||
|
static const int SAMPLERATE = 48000;
|
||||||
|
static const int CHANNELS = 1;
|
||||||
|
static const int SAMPLE_LENGTH = FRAME_10MS; /* must match value in audioconv.rs */
|
||||||
|
static const float AUDIBLE_HZ = 400.f; /* freq for the --audible switch */
|
||||||
|
|
||||||
|
static const int frame_sizes[] = {
|
||||||
|
SAMPLERATE * 2.5 / 1000,
|
||||||
|
SAMPLERATE * 5 / 1000,
|
||||||
|
SAMPLERATE * 10 / 1000,
|
||||||
|
SAMPLERATE * 20 / 1000,
|
||||||
|
SAMPLERATE * 40 / 1000,
|
||||||
|
SAMPLERATE * 60 / 1000,
|
||||||
|
};
|
||||||
|
|
||||||
|
static float theta = 0.f;
|
||||||
|
|
||||||
|
static const uint32_t FLAG_HEADER = 0x10000000;
|
||||||
|
static const uint32_t AUDIOCONV_PADDING_LENGTH_SHIFT = 12;
|
||||||
|
|
||||||
|
static int complete_write(const int file, const void *buf, const size_t len)
|
||||||
|
{
|
||||||
|
size_t written = 0;
|
||||||
|
ssize_t ret;
|
||||||
|
while(written < len){
|
||||||
|
ret = write(file, ((const char *)buf) + written, len - written);
|
||||||
|
if(ret < 0){
|
||||||
|
if(errno != EINTR && errno != EAGAIN)
|
||||||
|
return 0;
|
||||||
|
}else
|
||||||
|
written += ret;
|
||||||
|
}
|
||||||
|
return written == len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dump_hz(float hz, int samples, OpusEncoder *encoder, int outfile)
|
||||||
|
{
|
||||||
|
int i = 0, j, c, frame_size, tot = 0, padding;
|
||||||
|
opus_int32 written;
|
||||||
|
uint32_t pkt_header;
|
||||||
|
float val, *vals;
|
||||||
|
unsigned char packet[4000 /* suggested by opus_encoder(3) */ ];
|
||||||
|
|
||||||
|
fprintf(stdout, "dumping %u samples at %f hz\n", samples, hz);
|
||||||
|
|
||||||
|
vals = malloc(sizeof(float) * CHANNELS * frame_sizes[FRAME_LARGEST]);
|
||||||
|
|
||||||
|
while(i < samples){
|
||||||
|
|
||||||
|
/* find the largest packet we can write with the samples remaining */
|
||||||
|
frame_size = -1;
|
||||||
|
for(j = ARRAY_SIZE(frame_sizes) - 1; j >= 0; --j){
|
||||||
|
if(samples - i >= frame_sizes[j]){
|
||||||
|
frame_size = frame_sizes[j];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(frame_size < 0){
|
||||||
|
/* couldn't fill a whole packet, so write a partial */
|
||||||
|
frame_size = frame_sizes[FRAME_SMALLEST];
|
||||||
|
padding = frame_size - (samples - i);
|
||||||
|
}else
|
||||||
|
padding = 0;
|
||||||
|
|
||||||
|
for(j = 0; j < frame_size - padding; ++j){
|
||||||
|
val = sinf(theta);
|
||||||
|
for(c = 0; c < CHANNELS; ++c)
|
||||||
|
vals[j * CHANNELS + c] = val;
|
||||||
|
theta += hz * 2.f * M_PI / (float)SAMPLERATE;
|
||||||
|
while(theta >= 2.f * M_PI)
|
||||||
|
theta -= 2.f * M_PI;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(padding)
|
||||||
|
memset(vals + (frame_size - padding) * CHANNELS, 0, sizeof(float) * padding * CHANNELS);
|
||||||
|
|
||||||
|
written = opus_encode_float(encoder, vals, frame_size, packet, sizeof(packet));
|
||||||
|
if(written < 0){
|
||||||
|
fprintf(stderr, "fatal: opus_encode failed!!!\n");
|
||||||
|
free(vals);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pkt_header = written | (padding << AUDIOCONV_PADDING_LENGTH_SHIFT);
|
||||||
|
|
||||||
|
fprintf(stdout, "encoded %u samples (%u are padding) to %u bytes\n", frame_size, padding, written);
|
||||||
|
if(!complete_write(outfile, &pkt_header, sizeof(pkt_header))){
|
||||||
|
fprintf(stderr, "fatal: error writing packet header!!!\n");
|
||||||
|
free(vals);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!complete_write(outfile, packet, written)){
|
||||||
|
fprintf(stderr, "fatal: error writing packet contents!!!\n");
|
||||||
|
free(vals);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
tot += written + sizeof(written);
|
||||||
|
|
||||||
|
i += frame_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stdout, "done dumping, %u bytes\n", tot);
|
||||||
|
|
||||||
|
free(vals);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* OGG's opus header (from RFC 7845 Section 5.1) */
|
||||||
|
struct __attribute__((__packed__)) opus_header {
|
||||||
|
uint64_t magic;
|
||||||
|
uint8_t version;
|
||||||
|
uint8_t channels;
|
||||||
|
uint16_t preskip;
|
||||||
|
uint32_t input_samplerate;
|
||||||
|
uint16_t output_gain;
|
||||||
|
uint8_t mapping_family;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int dump_header(int outfile)
|
||||||
|
{
|
||||||
|
struct opus_header header;
|
||||||
|
uint32_t sz = sizeof(header) | FLAG_HEADER;
|
||||||
|
|
||||||
|
static const char magic[] = "OpusHead";
|
||||||
|
|
||||||
|
memcpy(&header.magic, magic, sizeof(magic));
|
||||||
|
header.version = 1;
|
||||||
|
header.channels = CHANNELS;
|
||||||
|
header.preskip = 0;
|
||||||
|
header.input_samplerate = SAMPLERATE;
|
||||||
|
header.output_gain = 0;
|
||||||
|
header.mapping_family = 0; /* FIXME: we need to support mc */
|
||||||
|
|
||||||
|
if(!complete_write(outfile, &sz, sizeof(sz))){
|
||||||
|
fprintf(stderr, "fatal: error writing opus header header!!!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!complete_write(outfile, &header, sizeof(header))){
|
||||||
|
fprintf(stderr, "fatal: error writing opus header!!!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usage(const char *name)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "usage:\n");
|
||||||
|
fprintf(stderr, "\t%s [--help|-h] [--audible] <outfile>\n", name);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
fprintf(stderr, "\t--audible\tGenerate an audible sound clip instead of silence.\n");
|
||||||
|
fprintf(stderr, "\t--help -h\tPrint this help message.\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int err, outfile, i, audible = 0;
|
||||||
|
OpusEncoder *encoder;
|
||||||
|
const char *outfile_name = NULL;
|
||||||
|
|
||||||
|
for(i = 1; i < argc; ++i){
|
||||||
|
if(!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")){
|
||||||
|
usage(argv[0]);
|
||||||
|
return 0;
|
||||||
|
}else if(!strcmp(argv[i], "--audible")){
|
||||||
|
audible = 1;
|
||||||
|
}else if(outfile_name){
|
||||||
|
fprintf(stderr, "error: too many arguments.\n\n");
|
||||||
|
usage(argv[0]);
|
||||||
|
return 1;
|
||||||
|
}else{
|
||||||
|
outfile_name = argv[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!outfile_name){
|
||||||
|
fprintf(stderr, "error: missing filename.\n\n");
|
||||||
|
usage(argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
encoder = opus_encoder_create(SAMPLERATE, CHANNELS, OPUS_APPLICATION_AUDIO, &err);
|
||||||
|
if(!encoder){
|
||||||
|
fprintf(stderr, "couldn't create opus encoder, err: 0x%x\n", err);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
outfile = open(outfile_name, O_CREAT | O_WRONLY | O_TRUNC, 0644);
|
||||||
|
if(outfile < 0){
|
||||||
|
fprintf(stderr, "couldn't open file \"%s\": %s\n", outfile_name, strerror(errno));
|
||||||
|
opus_encoder_destroy(encoder);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!dump_header(outfile)){
|
||||||
|
close(outfile);
|
||||||
|
unlink(outfile_name);
|
||||||
|
opus_encoder_destroy(encoder);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!dump_hz(audible ? AUDIBLE_HZ : 0.f, frame_sizes[SAMPLE_LENGTH], encoder, outfile)){
|
||||||
|
close(outfile);
|
||||||
|
unlink(outfile_name);
|
||||||
|
opus_encoder_destroy(encoder);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(outfile);
|
||||||
|
opus_encoder_destroy(encoder);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
4
proton
4
proton
|
@ -415,6 +415,7 @@ class Proton:
|
||||||
self.lib_dir = self.path("files/lib/")
|
self.lib_dir = self.path("files/lib/")
|
||||||
self.lib64_dir = self.path("files/lib64/")
|
self.lib64_dir = self.path("files/lib64/")
|
||||||
self.fonts_dir = self.path("files/share/fonts/")
|
self.fonts_dir = self.path("files/share/fonts/")
|
||||||
|
self.media_dir = self.path("files/share/media/")
|
||||||
self.wine_fonts_dir = self.path("files/share/wine/fonts/")
|
self.wine_fonts_dir = self.path("files/share/wine/fonts/")
|
||||||
self.wine_inf = self.path("files/share/wine/wine.inf")
|
self.wine_inf = self.path("files/share/wine/wine.inf")
|
||||||
self.version_file = self.path("version")
|
self.version_file = self.path("version")
|
||||||
|
@ -1258,6 +1259,9 @@ class Session:
|
||||||
self.env["MEDIACONV_AUDIO_TRANSCODED_FILE"] = os.environ["STEAM_COMPAT_TRANSCODED_MEDIA_PATH"] + "/transcoded_audio.foz"
|
self.env["MEDIACONV_AUDIO_TRANSCODED_FILE"] = os.environ["STEAM_COMPAT_TRANSCODED_MEDIA_PATH"] + "/transcoded_audio.foz"
|
||||||
self.env["MEDIACONV_VIDEO_TRANSCODED_FILE"] = os.environ["STEAM_COMPAT_TRANSCODED_MEDIA_PATH"] + "/transcoded_video.foz"
|
self.env["MEDIACONV_VIDEO_TRANSCODED_FILE"] = os.environ["STEAM_COMPAT_TRANSCODED_MEDIA_PATH"] + "/transcoded_video.foz"
|
||||||
|
|
||||||
|
self.env["MEDIACONV_BLANK_VIDEO_FILE"] = g_proton.media_dir + "blank.mkv"
|
||||||
|
self.env["MEDIACONV_BLANK_AUDIO_FILE"] = g_proton.media_dir + "blank.ptna"
|
||||||
|
|
||||||
prepend_to_env_str(self.env, "PATH", g_proton.bin_dir, ":")
|
prepend_to_env_str(self.env, "PATH", g_proton.bin_dir, ":")
|
||||||
|
|
||||||
def check_environment(self, env_name, config_name):
|
def check_environment(self, env_name, config_name):
|
||||||
|
|
Loading…
Reference in a new issue