18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Vidtv serves as a reference DVB driver and helps validate the existing APIs 48c2ecf20Sopenharmony_ci * in the media subsystem. It can also aid developers working on userspace 58c2ecf20Sopenharmony_ci * applications. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * This file contains the code for an AES3 (also known as AES/EBU) encoder. 88c2ecf20Sopenharmony_ci * It is based on EBU Tech 3250 and SMPTE 302M technical documents. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * This encoder currently supports 16bit AES3 subframes using 16bit signed 118c2ecf20Sopenharmony_ci * integers. 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * Note: AU stands for Access Unit, and AAU stands for Audio Access Unit 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * Copyright (C) 2020 Daniel W. S. Almeida 168c2ecf20Sopenharmony_ci */ 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ":%s, %d: " fmt, __func__, __LINE__ 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include <linux/bug.h> 218c2ecf20Sopenharmony_ci#include <linux/crc32.h> 228c2ecf20Sopenharmony_ci#include <linux/fixp-arith.h> 238c2ecf20Sopenharmony_ci#include <linux/jiffies.h> 248c2ecf20Sopenharmony_ci#include <linux/kernel.h> 258c2ecf20Sopenharmony_ci#include <linux/math64.h> 268c2ecf20Sopenharmony_ci#include <linux/printk.h> 278c2ecf20Sopenharmony_ci#include <linux/ratelimit.h> 288c2ecf20Sopenharmony_ci#include <linux/slab.h> 298c2ecf20Sopenharmony_ci#include <linux/string.h> 308c2ecf20Sopenharmony_ci#include <linux/types.h> 318c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#include "vidtv_common.h" 348c2ecf20Sopenharmony_ci#include "vidtv_encoder.h" 358c2ecf20Sopenharmony_ci#include "vidtv_s302m.h" 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#define S302M_SAMPLING_RATE_HZ 48000 388c2ecf20Sopenharmony_ci#define PES_PRIVATE_STREAM_1 0xbd /* PES: private_stream_1 */ 398c2ecf20Sopenharmony_ci#define S302M_BLOCK_SZ 192 408c2ecf20Sopenharmony_ci#define S302M_SIN_LUT_NUM_ELEM 1024 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/* these are retrieved empirically from ffmpeg/libavcodec */ 438c2ecf20Sopenharmony_ci#define FF_S302M_DEFAULT_NUM_FRAMES 1115 448c2ecf20Sopenharmony_ci#define FF_S302M_DEFAULT_PTS_INCREMENT 2090 458c2ecf20Sopenharmony_ci#define FF_S302M_DEFAULT_PTS_OFFSET 100000 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci/* Used by the tone generator: number of samples for PI */ 488c2ecf20Sopenharmony_ci#define PI 180 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistatic const u8 reverse[256] = { 518c2ecf20Sopenharmony_ci /* from ffmpeg */ 528c2ecf20Sopenharmony_ci 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 538c2ecf20Sopenharmony_ci 0x30, 0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 548c2ecf20Sopenharmony_ci 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, 0x44, 0xC4, 558c2ecf20Sopenharmony_ci 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, 568c2ecf20Sopenharmony_ci 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 578c2ecf20Sopenharmony_ci 0x3C, 0xBC, 0x7C, 0xFC, 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 588c2ecf20Sopenharmony_ci 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, 0x0A, 0x8A, 0x4A, 0xCA, 598c2ecf20Sopenharmony_ci 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, 608c2ecf20Sopenharmony_ci 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 618c2ecf20Sopenharmony_ci 0x36, 0xB6, 0x76, 0xF6, 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 628c2ecf20Sopenharmony_ci 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 0x01, 0x81, 0x41, 0xC1, 638c2ecf20Sopenharmony_ci 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, 648c2ecf20Sopenharmony_ci 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 658c2ecf20Sopenharmony_ci 0x39, 0xB9, 0x79, 0xF9, 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 668c2ecf20Sopenharmony_ci 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 0x0D, 0x8D, 0x4D, 0xCD, 678c2ecf20Sopenharmony_ci 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, 688c2ecf20Sopenharmony_ci 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 698c2ecf20Sopenharmony_ci 0x33, 0xB3, 0x73, 0xF3, 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 708c2ecf20Sopenharmony_ci 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7, 718c2ecf20Sopenharmony_ci 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, 728c2ecf20Sopenharmony_ci 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 738c2ecf20Sopenharmony_ci 0x3F, 0xBF, 0x7F, 0xFF, 748c2ecf20Sopenharmony_ci}; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_cistruct tone_duration { 778c2ecf20Sopenharmony_ci enum musical_notes note; 788c2ecf20Sopenharmony_ci int duration; 798c2ecf20Sopenharmony_ci}; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci#define COMPASS 100 /* beats per minute */ 828c2ecf20Sopenharmony_cistatic const struct tone_duration beethoven_fur_elise[] = { 838c2ecf20Sopenharmony_ci { NOTE_SILENT, 512}, 848c2ecf20Sopenharmony_ci { NOTE_E_6, 128}, { NOTE_DS_6, 128}, { NOTE_E_6, 128}, 858c2ecf20Sopenharmony_ci { NOTE_DS_6, 128}, { NOTE_E_6, 128}, { NOTE_B_5, 128}, 868c2ecf20Sopenharmony_ci { NOTE_D_6, 128}, { NOTE_C_6, 128}, { NOTE_A_3, 128}, 878c2ecf20Sopenharmony_ci { NOTE_E_4, 128}, { NOTE_A_4, 128}, { NOTE_C_5, 128}, 888c2ecf20Sopenharmony_ci { NOTE_E_5, 128}, { NOTE_A_5, 128}, { NOTE_E_3, 128}, 898c2ecf20Sopenharmony_ci { NOTE_E_4, 128}, { NOTE_GS_4, 128}, { NOTE_E_5, 128}, 908c2ecf20Sopenharmony_ci { NOTE_GS_5, 128}, { NOTE_B_5, 128}, { NOTE_A_3, 128}, 918c2ecf20Sopenharmony_ci { NOTE_E_4, 128}, { NOTE_A_4, 128}, { NOTE_E_5, 128}, 928c2ecf20Sopenharmony_ci { NOTE_E_6, 128}, { NOTE_DS_6, 128}, { NOTE_E_6, 128}, 938c2ecf20Sopenharmony_ci { NOTE_DS_6, 128}, { NOTE_E_6, 128}, { NOTE_B_5, 128}, 948c2ecf20Sopenharmony_ci { NOTE_D_6, 128}, { NOTE_C_6, 128}, { NOTE_A_3, 128}, 958c2ecf20Sopenharmony_ci { NOTE_E_4, 128}, { NOTE_A_4, 128}, { NOTE_C_5, 128}, 968c2ecf20Sopenharmony_ci { NOTE_E_5, 128}, { NOTE_A_5, 128}, { NOTE_E_3, 128}, 978c2ecf20Sopenharmony_ci { NOTE_E_4, 128}, { NOTE_GS_4, 128}, { NOTE_E_5, 128}, 988c2ecf20Sopenharmony_ci { NOTE_C_6, 128}, { NOTE_B_5, 128}, { NOTE_A_3, 128}, 998c2ecf20Sopenharmony_ci { NOTE_E_4, 128}, { NOTE_A_4, 128}, { NOTE_SILENT, 128}, 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci { NOTE_E_6, 128}, { NOTE_DS_6, 128}, { NOTE_E_6, 128}, 1028c2ecf20Sopenharmony_ci { NOTE_DS_6, 128}, { NOTE_E_6, 128}, { NOTE_B_5, 128}, 1038c2ecf20Sopenharmony_ci { NOTE_D_6, 128}, { NOTE_C_6, 128}, { NOTE_A_3, 128}, 1048c2ecf20Sopenharmony_ci { NOTE_E_4, 128}, { NOTE_A_4, 128}, { NOTE_C_5, 128}, 1058c2ecf20Sopenharmony_ci { NOTE_E_5, 128}, { NOTE_A_5, 128}, { NOTE_E_3, 128}, 1068c2ecf20Sopenharmony_ci { NOTE_E_4, 128}, { NOTE_GS_4, 128}, { NOTE_E_5, 128}, 1078c2ecf20Sopenharmony_ci { NOTE_GS_5, 128}, { NOTE_B_5, 128}, { NOTE_A_3, 128}, 1088c2ecf20Sopenharmony_ci { NOTE_E_4, 128}, { NOTE_A_4, 128}, { NOTE_E_5, 128}, 1098c2ecf20Sopenharmony_ci { NOTE_E_6, 128}, { NOTE_DS_6, 128}, { NOTE_E_6, 128}, 1108c2ecf20Sopenharmony_ci { NOTE_DS_6, 128}, { NOTE_E_6, 128}, { NOTE_B_5, 128}, 1118c2ecf20Sopenharmony_ci { NOTE_D_6, 128}, { NOTE_C_6, 128}, { NOTE_A_3, 128}, 1128c2ecf20Sopenharmony_ci { NOTE_E_4, 128}, { NOTE_A_4, 128}, { NOTE_C_5, 128}, 1138c2ecf20Sopenharmony_ci { NOTE_E_5, 128}, { NOTE_A_5, 128}, { NOTE_E_3, 128}, 1148c2ecf20Sopenharmony_ci { NOTE_E_4, 128}, { NOTE_GS_4, 128}, { NOTE_E_5, 128}, 1158c2ecf20Sopenharmony_ci { NOTE_C_6, 128}, { NOTE_B_5, 128}, { NOTE_A_3, 128}, 1168c2ecf20Sopenharmony_ci { NOTE_E_4, 128}, { NOTE_A_4, 128}, { NOTE_B_4, 128}, 1178c2ecf20Sopenharmony_ci { NOTE_C_5, 128}, { NOTE_D_5, 128}, { NOTE_C_4, 128}, 1188c2ecf20Sopenharmony_ci { NOTE_G_4, 128}, { NOTE_C_5, 128}, { NOTE_G_4, 128}, 1198c2ecf20Sopenharmony_ci { NOTE_F_5, 128}, { NOTE_E_5, 128}, { NOTE_G_3, 128}, 1208c2ecf20Sopenharmony_ci { NOTE_G_4, 128}, { NOTE_B_3, 128}, { NOTE_F_4, 128}, 1218c2ecf20Sopenharmony_ci { NOTE_E_5, 128}, { NOTE_D_5, 128}, { NOTE_A_3, 128}, 1228c2ecf20Sopenharmony_ci { NOTE_E_4, 128}, { NOTE_A_4, 128}, { NOTE_E_4, 128}, 1238c2ecf20Sopenharmony_ci { NOTE_D_5, 128}, { NOTE_C_5, 128}, { NOTE_E_3, 128}, 1248c2ecf20Sopenharmony_ci { NOTE_E_4, 128}, { NOTE_E_5, 128}, { NOTE_E_5, 128}, 1258c2ecf20Sopenharmony_ci { NOTE_E_6, 128}, { NOTE_E_5, 128}, { NOTE_E_6, 128}, 1268c2ecf20Sopenharmony_ci { NOTE_E_5, 128}, { NOTE_E_5, 128}, { NOTE_DS_5, 128}, 1278c2ecf20Sopenharmony_ci { NOTE_E_5, 128}, { NOTE_DS_6, 128}, { NOTE_E_6, 128}, 1288c2ecf20Sopenharmony_ci { NOTE_DS_5, 128}, { NOTE_E_5, 128}, { NOTE_DS_6, 128}, 1298c2ecf20Sopenharmony_ci { NOTE_E_6, 128}, { NOTE_DS_6, 128}, { NOTE_E_6, 128}, 1308c2ecf20Sopenharmony_ci { NOTE_DS_6, 128}, { NOTE_E_6, 128}, { NOTE_B_5, 128}, 1318c2ecf20Sopenharmony_ci { NOTE_D_6, 128}, { NOTE_C_6, 128}, { NOTE_A_3, 128}, 1328c2ecf20Sopenharmony_ci { NOTE_E_4, 128}, { NOTE_A_4, 128}, { NOTE_C_5, 128}, 1338c2ecf20Sopenharmony_ci { NOTE_E_5, 128}, { NOTE_A_5, 128}, { NOTE_E_3, 128}, 1348c2ecf20Sopenharmony_ci { NOTE_E_4, 128}, { NOTE_GS_4, 128}, { NOTE_E_5, 128}, 1358c2ecf20Sopenharmony_ci { NOTE_GS_5, 128}, { NOTE_B_5, 128}, { NOTE_A_3, 128}, 1368c2ecf20Sopenharmony_ci { NOTE_E_4, 128}, { NOTE_A_4, 128}, { NOTE_E_5, 128}, 1378c2ecf20Sopenharmony_ci { NOTE_E_6, 128}, { NOTE_DS_6, 128}, { NOTE_E_6, 128}, 1388c2ecf20Sopenharmony_ci { NOTE_DS_6, 128}, { NOTE_E_6, 128}, { NOTE_B_5, 128}, 1398c2ecf20Sopenharmony_ci { NOTE_D_6, 128}, { NOTE_C_6, 128}, { NOTE_A_3, 128}, 1408c2ecf20Sopenharmony_ci { NOTE_E_4, 128}, { NOTE_A_4, 128}, { NOTE_C_5, 128}, 1418c2ecf20Sopenharmony_ci { NOTE_E_5, 128}, { NOTE_A_5, 128}, { NOTE_E_3, 128}, 1428c2ecf20Sopenharmony_ci { NOTE_E_4, 128}, { NOTE_GS_4, 128}, { NOTE_E_5, 128}, 1438c2ecf20Sopenharmony_ci { NOTE_C_6, 128}, { NOTE_B_5, 128}, { NOTE_A_5, 512}, 1448c2ecf20Sopenharmony_ci { NOTE_SILENT, 256}, 1458c2ecf20Sopenharmony_ci}; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_cistatic struct vidtv_access_unit *vidtv_s302m_access_unit_init(struct vidtv_access_unit *head) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci struct vidtv_access_unit *au; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci au = kzalloc(sizeof(*au), GFP_KERNEL); 1528c2ecf20Sopenharmony_ci if (!au) 1538c2ecf20Sopenharmony_ci return NULL; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci if (head) { 1568c2ecf20Sopenharmony_ci while (head->next) 1578c2ecf20Sopenharmony_ci head = head->next; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci head->next = au; 1608c2ecf20Sopenharmony_ci } 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci return au; 1638c2ecf20Sopenharmony_ci} 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_cistatic void vidtv_s302m_access_unit_destroy(struct vidtv_encoder *e) 1668c2ecf20Sopenharmony_ci{ 1678c2ecf20Sopenharmony_ci struct vidtv_access_unit *head = e->access_units; 1688c2ecf20Sopenharmony_ci struct vidtv_access_unit *tmp = NULL; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci while (head) { 1718c2ecf20Sopenharmony_ci tmp = head; 1728c2ecf20Sopenharmony_ci head = head->next; 1738c2ecf20Sopenharmony_ci kfree(tmp); 1748c2ecf20Sopenharmony_ci } 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci e->access_units = NULL; 1778c2ecf20Sopenharmony_ci} 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_cistatic void vidtv_s302m_alloc_au(struct vidtv_encoder *e) 1808c2ecf20Sopenharmony_ci{ 1818c2ecf20Sopenharmony_ci struct vidtv_access_unit *sync_au = NULL; 1828c2ecf20Sopenharmony_ci struct vidtv_access_unit *temp = NULL; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci if (e->sync && e->sync->is_video_encoder) { 1858c2ecf20Sopenharmony_ci sync_au = e->sync->access_units; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci while (sync_au) { 1888c2ecf20Sopenharmony_ci temp = vidtv_s302m_access_unit_init(e->access_units); 1898c2ecf20Sopenharmony_ci if (!e->access_units) 1908c2ecf20Sopenharmony_ci e->access_units = temp; 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci sync_au = sync_au->next; 1938c2ecf20Sopenharmony_ci } 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci return; 1968c2ecf20Sopenharmony_ci } 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci e->access_units = vidtv_s302m_access_unit_init(NULL); 1998c2ecf20Sopenharmony_ci} 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_cistatic void 2028c2ecf20Sopenharmony_cividtv_s302m_compute_sample_count_from_video(struct vidtv_encoder *e) 2038c2ecf20Sopenharmony_ci{ 2048c2ecf20Sopenharmony_ci struct vidtv_access_unit *sync_au = e->sync->access_units; 2058c2ecf20Sopenharmony_ci struct vidtv_access_unit *au = e->access_units; 2068c2ecf20Sopenharmony_ci u32 sample_duration_usecs; 2078c2ecf20Sopenharmony_ci u32 vau_duration_usecs; 2088c2ecf20Sopenharmony_ci u32 s; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci vau_duration_usecs = USEC_PER_SEC / e->sync->sampling_rate_hz; 2118c2ecf20Sopenharmony_ci sample_duration_usecs = USEC_PER_SEC / e->sampling_rate_hz; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci while (au && sync_au) { 2148c2ecf20Sopenharmony_ci s = DIV_ROUND_UP(vau_duration_usecs, sample_duration_usecs); 2158c2ecf20Sopenharmony_ci au->num_samples = s; 2168c2ecf20Sopenharmony_ci au = au->next; 2178c2ecf20Sopenharmony_ci sync_au = sync_au->next; 2188c2ecf20Sopenharmony_ci } 2198c2ecf20Sopenharmony_ci} 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_cistatic void vidtv_s302m_compute_pts_from_video(struct vidtv_encoder *e) 2228c2ecf20Sopenharmony_ci{ 2238c2ecf20Sopenharmony_ci struct vidtv_access_unit *au = e->access_units; 2248c2ecf20Sopenharmony_ci struct vidtv_access_unit *sync_au = e->sync->access_units; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci /* use the same pts from the video access unit*/ 2278c2ecf20Sopenharmony_ci while (au && sync_au) { 2288c2ecf20Sopenharmony_ci au->pts = sync_au->pts; 2298c2ecf20Sopenharmony_ci au = au->next; 2308c2ecf20Sopenharmony_ci sync_au = sync_au->next; 2318c2ecf20Sopenharmony_ci } 2328c2ecf20Sopenharmony_ci} 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_cistatic u16 vidtv_s302m_get_sample(struct vidtv_encoder *e) 2358c2ecf20Sopenharmony_ci{ 2368c2ecf20Sopenharmony_ci u16 sample; 2378c2ecf20Sopenharmony_ci int pos; 2388c2ecf20Sopenharmony_ci struct vidtv_s302m_ctx *ctx = e->ctx; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci if (!e->src_buf) { 2418c2ecf20Sopenharmony_ci /* 2428c2ecf20Sopenharmony_ci * Simple tone generator: play the tones at the 2438c2ecf20Sopenharmony_ci * beethoven_fur_elise array. 2448c2ecf20Sopenharmony_ci */ 2458c2ecf20Sopenharmony_ci if (ctx->last_duration <= 0) { 2468c2ecf20Sopenharmony_ci if (e->src_buf_offset >= ARRAY_SIZE(beethoven_fur_elise)) 2478c2ecf20Sopenharmony_ci e->src_buf_offset = 0; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci ctx->last_tone = beethoven_fur_elise[e->src_buf_offset].note; 2508c2ecf20Sopenharmony_ci ctx->last_duration = beethoven_fur_elise[e->src_buf_offset].duration * 2518c2ecf20Sopenharmony_ci S302M_SAMPLING_RATE_HZ / COMPASS / 5; 2528c2ecf20Sopenharmony_ci e->src_buf_offset++; 2538c2ecf20Sopenharmony_ci ctx->note_offset = 0; 2548c2ecf20Sopenharmony_ci } else { 2558c2ecf20Sopenharmony_ci ctx->last_duration--; 2568c2ecf20Sopenharmony_ci } 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci /* Handle pause notes */ 2598c2ecf20Sopenharmony_ci if (!ctx->last_tone) 2608c2ecf20Sopenharmony_ci return 0x8000; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci pos = (2 * PI * ctx->note_offset * ctx->last_tone) / S302M_SAMPLING_RATE_HZ; 2638c2ecf20Sopenharmony_ci ctx->note_offset++; 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci return (fixp_sin32(pos % (2 * PI)) >> 16) + 0x8000; 2668c2ecf20Sopenharmony_ci } 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci /* bug somewhere */ 2698c2ecf20Sopenharmony_ci if (e->src_buf_offset > e->src_buf_sz) { 2708c2ecf20Sopenharmony_ci pr_err_ratelimited("overflow detected: %d > %d, wrapping.\n", 2718c2ecf20Sopenharmony_ci e->src_buf_offset, 2728c2ecf20Sopenharmony_ci e->src_buf_sz); 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci e->src_buf_offset = 0; 2758c2ecf20Sopenharmony_ci } 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci if (e->src_buf_offset >= e->src_buf_sz) { 2788c2ecf20Sopenharmony_ci /* let the source know we are out of data */ 2798c2ecf20Sopenharmony_ci if (e->last_sample_cb) 2808c2ecf20Sopenharmony_ci e->last_sample_cb(e->sample_count); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci e->src_buf_offset = 0; 2838c2ecf20Sopenharmony_ci } 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci sample = *(u16 *)(e->src_buf + e->src_buf_offset); 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci return sample; 2888c2ecf20Sopenharmony_ci} 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_cistatic u32 vidtv_s302m_write_frame(struct vidtv_encoder *e, 2918c2ecf20Sopenharmony_ci u16 sample) 2928c2ecf20Sopenharmony_ci{ 2938c2ecf20Sopenharmony_ci struct vidtv_s302m_ctx *ctx = e->ctx; 2948c2ecf20Sopenharmony_ci struct vidtv_s302m_frame_16 f = {}; 2958c2ecf20Sopenharmony_ci u32 nbytes = 0; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci /* from ffmpeg: see s302enc.c */ 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci u8 vucf = ctx->frame_index == 0 ? 0x10 : 0; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci f.data[0] = sample & 0xFF; 3028c2ecf20Sopenharmony_ci f.data[1] = (sample & 0xFF00) >> 8; 3038c2ecf20Sopenharmony_ci f.data[2] = ((sample & 0x0F) << 4) | vucf; 3048c2ecf20Sopenharmony_ci f.data[3] = (sample & 0x0FF0) >> 4; 3058c2ecf20Sopenharmony_ci f.data[4] = (sample & 0xF000) >> 12; 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci f.data[0] = reverse[f.data[0]]; 3088c2ecf20Sopenharmony_ci f.data[1] = reverse[f.data[1]]; 3098c2ecf20Sopenharmony_ci f.data[2] = reverse[f.data[2]]; 3108c2ecf20Sopenharmony_ci f.data[3] = reverse[f.data[3]]; 3118c2ecf20Sopenharmony_ci f.data[4] = reverse[f.data[4]]; 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci nbytes += vidtv_memcpy(e->encoder_buf, 3148c2ecf20Sopenharmony_ci e->encoder_buf_offset, 3158c2ecf20Sopenharmony_ci VIDTV_S302M_BUF_SZ, 3168c2ecf20Sopenharmony_ci &f, 3178c2ecf20Sopenharmony_ci sizeof(f)); 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci e->encoder_buf_offset += nbytes; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci ctx->frame_index++; 3228c2ecf20Sopenharmony_ci if (ctx->frame_index >= S302M_BLOCK_SZ) 3238c2ecf20Sopenharmony_ci ctx->frame_index = 0; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci return nbytes; 3268c2ecf20Sopenharmony_ci} 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_cistatic u32 vidtv_s302m_write_h(struct vidtv_encoder *e, u32 p_sz) 3298c2ecf20Sopenharmony_ci{ 3308c2ecf20Sopenharmony_ci struct vidtv_smpte_s302m_es h = {}; 3318c2ecf20Sopenharmony_ci u32 nbytes = 0; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci /* 2 channels, ident: 0, 16 bits per sample */ 3348c2ecf20Sopenharmony_ci h.bitfield = cpu_to_be32((p_sz << 16)); 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci nbytes += vidtv_memcpy(e->encoder_buf, 3378c2ecf20Sopenharmony_ci e->encoder_buf_offset, 3388c2ecf20Sopenharmony_ci e->encoder_buf_sz, 3398c2ecf20Sopenharmony_ci &h, 3408c2ecf20Sopenharmony_ci sizeof(h)); 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci e->encoder_buf_offset += nbytes; 3438c2ecf20Sopenharmony_ci return nbytes; 3448c2ecf20Sopenharmony_ci} 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_cistatic void vidtv_s302m_write_frames(struct vidtv_encoder *e) 3478c2ecf20Sopenharmony_ci{ 3488c2ecf20Sopenharmony_ci struct vidtv_access_unit *au = e->access_units; 3498c2ecf20Sopenharmony_ci struct vidtv_s302m_ctx *ctx = e->ctx; 3508c2ecf20Sopenharmony_ci u32 nbytes_per_unit = 0; 3518c2ecf20Sopenharmony_ci u32 nbytes = 0; 3528c2ecf20Sopenharmony_ci u32 au_sz = 0; 3538c2ecf20Sopenharmony_ci u16 sample; 3548c2ecf20Sopenharmony_ci u32 j; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci while (au) { 3578c2ecf20Sopenharmony_ci au_sz = au->num_samples * 3588c2ecf20Sopenharmony_ci sizeof(struct vidtv_s302m_frame_16); 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci nbytes_per_unit = vidtv_s302m_write_h(e, au_sz); 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci for (j = 0; j < au->num_samples; ++j) { 3638c2ecf20Sopenharmony_ci sample = vidtv_s302m_get_sample(e); 3648c2ecf20Sopenharmony_ci nbytes_per_unit += vidtv_s302m_write_frame(e, sample); 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci if (e->src_buf) 3678c2ecf20Sopenharmony_ci e->src_buf_offset += sizeof(u16); 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci e->sample_count++; 3708c2ecf20Sopenharmony_ci } 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci au->nbytes = nbytes_per_unit; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci if (au_sz + sizeof(struct vidtv_smpte_s302m_es) != nbytes_per_unit) { 3758c2ecf20Sopenharmony_ci pr_warn_ratelimited("write size was %u, expected %zu\n", 3768c2ecf20Sopenharmony_ci nbytes_per_unit, 3778c2ecf20Sopenharmony_ci au_sz + sizeof(struct vidtv_smpte_s302m_es)); 3788c2ecf20Sopenharmony_ci } 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci nbytes += nbytes_per_unit; 3818c2ecf20Sopenharmony_ci au->offset = nbytes - nbytes_per_unit; 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci nbytes_per_unit = 0; 3848c2ecf20Sopenharmony_ci ctx->au_count++; 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci au = au->next; 3878c2ecf20Sopenharmony_ci } 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_cistatic void *vidtv_s302m_encode(struct vidtv_encoder *e) 3918c2ecf20Sopenharmony_ci{ 3928c2ecf20Sopenharmony_ci struct vidtv_s302m_ctx *ctx = e->ctx; 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci /* 3958c2ecf20Sopenharmony_ci * According to SMPTE 302M, an audio access unit is specified as those 3968c2ecf20Sopenharmony_ci * AES3 words that are associated with a corresponding video frame. 3978c2ecf20Sopenharmony_ci * Therefore, there is one audio access unit for every video access unit 3988c2ecf20Sopenharmony_ci * in the corresponding video encoder ('sync'), using the same values 3998c2ecf20Sopenharmony_ci * for PTS as used by the video encoder. 4008c2ecf20Sopenharmony_ci * 4018c2ecf20Sopenharmony_ci * Assuming that it is also possible to send audio without any 4028c2ecf20Sopenharmony_ci * associated video, as in a radio-like service, a single audio access unit 4038c2ecf20Sopenharmony_ci * is created with values for 'num_samples' and 'pts' taken empirically from 4048c2ecf20Sopenharmony_ci * ffmpeg 4058c2ecf20Sopenharmony_ci */ 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci vidtv_s302m_access_unit_destroy(e); 4088c2ecf20Sopenharmony_ci vidtv_s302m_alloc_au(e); 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci if (e->sync && e->sync->is_video_encoder) { 4118c2ecf20Sopenharmony_ci vidtv_s302m_compute_sample_count_from_video(e); 4128c2ecf20Sopenharmony_ci vidtv_s302m_compute_pts_from_video(e); 4138c2ecf20Sopenharmony_ci } else { 4148c2ecf20Sopenharmony_ci e->access_units->num_samples = FF_S302M_DEFAULT_NUM_FRAMES; 4158c2ecf20Sopenharmony_ci e->access_units->pts = (ctx->au_count * FF_S302M_DEFAULT_PTS_INCREMENT) + 4168c2ecf20Sopenharmony_ci FF_S302M_DEFAULT_PTS_OFFSET; 4178c2ecf20Sopenharmony_ci } 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci vidtv_s302m_write_frames(e); 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci return e->encoder_buf; 4228c2ecf20Sopenharmony_ci} 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_cistatic u32 vidtv_s302m_clear(struct vidtv_encoder *e) 4258c2ecf20Sopenharmony_ci{ 4268c2ecf20Sopenharmony_ci struct vidtv_access_unit *au = e->access_units; 4278c2ecf20Sopenharmony_ci u32 count = 0; 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci while (au) { 4308c2ecf20Sopenharmony_ci count++; 4318c2ecf20Sopenharmony_ci au = au->next; 4328c2ecf20Sopenharmony_ci } 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci vidtv_s302m_access_unit_destroy(e); 4358c2ecf20Sopenharmony_ci memset(e->encoder_buf, 0, VIDTV_S302M_BUF_SZ); 4368c2ecf20Sopenharmony_ci e->encoder_buf_offset = 0; 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci return count; 4398c2ecf20Sopenharmony_ci} 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_cistruct vidtv_encoder 4428c2ecf20Sopenharmony_ci*vidtv_s302m_encoder_init(struct vidtv_s302m_encoder_init_args args) 4438c2ecf20Sopenharmony_ci{ 4448c2ecf20Sopenharmony_ci u32 priv_sz = sizeof(struct vidtv_s302m_ctx); 4458c2ecf20Sopenharmony_ci struct vidtv_s302m_ctx *ctx; 4468c2ecf20Sopenharmony_ci struct vidtv_encoder *e; 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci e = kzalloc(sizeof(*e), GFP_KERNEL); 4498c2ecf20Sopenharmony_ci if (!e) 4508c2ecf20Sopenharmony_ci return NULL; 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci e->id = S302M; 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci if (args.name) 4558c2ecf20Sopenharmony_ci e->name = kstrdup(args.name, GFP_KERNEL); 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci e->encoder_buf = vzalloc(VIDTV_S302M_BUF_SZ); 4588c2ecf20Sopenharmony_ci if (!e->encoder_buf) 4598c2ecf20Sopenharmony_ci goto out_kfree_e; 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci e->encoder_buf_sz = VIDTV_S302M_BUF_SZ; 4628c2ecf20Sopenharmony_ci e->encoder_buf_offset = 0; 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci e->sample_count = 0; 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci e->src_buf = (args.src_buf) ? args.src_buf : NULL; 4678c2ecf20Sopenharmony_ci e->src_buf_sz = (args.src_buf) ? args.src_buf_sz : 0; 4688c2ecf20Sopenharmony_ci e->src_buf_offset = 0; 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci e->is_video_encoder = false; 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci ctx = kzalloc(priv_sz, GFP_KERNEL); 4738c2ecf20Sopenharmony_ci if (!ctx) 4748c2ecf20Sopenharmony_ci goto out_kfree_buf; 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci e->ctx = ctx; 4778c2ecf20Sopenharmony_ci ctx->last_duration = 0; 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci e->encode = vidtv_s302m_encode; 4808c2ecf20Sopenharmony_ci e->clear = vidtv_s302m_clear; 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci e->es_pid = cpu_to_be16(args.es_pid); 4838c2ecf20Sopenharmony_ci e->stream_id = cpu_to_be16(PES_PRIVATE_STREAM_1); 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci e->sync = args.sync; 4868c2ecf20Sopenharmony_ci e->sampling_rate_hz = S302M_SAMPLING_RATE_HZ; 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci e->last_sample_cb = args.last_sample_cb; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci e->destroy = vidtv_s302m_encoder_destroy; 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci if (args.head) { 4938c2ecf20Sopenharmony_ci while (args.head->next) 4948c2ecf20Sopenharmony_ci args.head = args.head->next; 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci args.head->next = e; 4978c2ecf20Sopenharmony_ci } 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci e->next = NULL; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci return e; 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ciout_kfree_buf: 5048c2ecf20Sopenharmony_ci kfree(e->encoder_buf); 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ciout_kfree_e: 5078c2ecf20Sopenharmony_ci kfree(e->name); 5088c2ecf20Sopenharmony_ci kfree(e); 5098c2ecf20Sopenharmony_ci return NULL; 5108c2ecf20Sopenharmony_ci} 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_civoid vidtv_s302m_encoder_destroy(struct vidtv_encoder *e) 5138c2ecf20Sopenharmony_ci{ 5148c2ecf20Sopenharmony_ci if (e->id != S302M) { 5158c2ecf20Sopenharmony_ci pr_err_ratelimited("Encoder type mismatch, skipping.\n"); 5168c2ecf20Sopenharmony_ci return; 5178c2ecf20Sopenharmony_ci } 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci vidtv_s302m_access_unit_destroy(e); 5208c2ecf20Sopenharmony_ci kfree(e->name); 5218c2ecf20Sopenharmony_ci vfree(e->encoder_buf); 5228c2ecf20Sopenharmony_ci kfree(e->ctx); 5238c2ecf20Sopenharmony_ci kfree(e); 5248c2ecf20Sopenharmony_ci} 525