diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9f8a5c7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/rem-*.tar.gz diff --git a/README.md b/README.md deleted file mode 100644 index 348abc2..0000000 --- a/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# librem - -Librem is a portable and generic library for real-time audio and video processing. \ No newline at end of file diff --git a/librem-0.6.0-52bbacb.patch b/librem-0.6.0-52bbacb.patch new file mode 100644 index 0000000..779b8e6 --- /dev/null +++ b/librem-0.6.0-52bbacb.patch @@ -0,0 +1,1084 @@ +https://github.com/creytiv/rem/compare/v0.6.0...52bbacb + +diff --git a/.travis.yml b/.travis.yml +index 4b51c00..02fc237 100644 +--- a/.travis.yml ++++ b/.travis.yml +@@ -1,15 +1,24 @@ + language: c + +-before_install: +- - sudo apt-get -qq update +- - sudo apt-get -y install libssl-dev ++os: ++ - linux ++ - osx ++ ++compiler: ++ - clang ++ - gcc ++ ++addons: ++ apt: ++ packages: ++ libssl-dev + + install: + - git clone https://github.com/creytiv/re.git +- - cd re && make && sudo make install && cd .. +- - sudo ldconfig ++ - cd re && make && sudo PATH="$PATH" make install && cd .. ++ - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo ldconfig; fi + - wget "https://github.com/alfredh/pytools/raw/master/ccheck.py" + + script: +- - make EXTRA_CFLAGS=-Werror ++ - make CCACHE= EXTRA_CFLAGS=-Werror + - python2 ccheck.py +diff --git a/Makefile b/Makefile +index b46ba87..7342c46 100644 +--- a/Makefile ++++ b/Makefile +@@ -37,7 +37,9 @@ MODULES += aumix vidmix + endif + + MODULES += vid vidconv ++MODULES += aac + MODULES += avc ++MODULES += h264 + + LIBS += -lm + +diff --git a/README.md b/README.md +index 7d45c93..57330d6 100644 +--- a/README.md ++++ b/README.md +@@ -3,7 +3,7 @@ librem README + + + librem is a Audio and video processing media library +-Copyright (C) 2010 - 2018 Creytiv.com ++Copyright (C) 2010 - 2019 Creytiv.com + + [![Build Status](https://travis-ci.org/creytiv/rem.svg?branch=master)](https://travis-ci.org/creytiv/rem) + +@@ -64,6 +64,7 @@ Audio Modules: + + name: status: description: + ++* aac unstable Advanced Audio Coding (AAC) + * au testing Base audio types + * aubuf testing Audio buffer + * auconv unstable Audio sample format conversion +@@ -82,6 +83,7 @@ Video Modules: + name: status: description: + + * avc unstable Advanced Video Coding (AVC) ++* h264 unstable H.264 header parser + * vid testing Base video types + * vidconv testing Colorspace conversion and scaling + * vidmix unstable Video mixer +diff --git a/debian/changelog b/debian/changelog +index b503b67..fe1494d 100644 +--- a/debian/changelog ++++ b/debian/changelog +@@ -1,3 +1,33 @@ ++librem (0.6.0-5) unstable; urgency=medium ++ ++ * version 0.6.0-5 ++ ++ -- Alfred E. Heggestad Tue, 14 Apr 2020 14:00:00 +0200 ++ ++librem (0.6.0-4) unstable; urgency=medium ++ ++ * version 0.6.0-4 ++ ++ -- Richard Aas Wed, 4 Mar 2020 14:00:00 +0100 ++ ++librem (0.6.0-3) unstable; urgency=medium ++ ++ * version 0.6.0-3 ++ ++ -- Richard Aas Fri, 11 Oct 2019 12:00:00 +0200 ++ ++librem (0.6.0-2) unstable; urgency=medium ++ ++ * version 0.6.0-2 ++ ++ -- Richard Aas Fri, 26 Apr 2019 12:00:00 +0200 ++ ++librem (0.6.0-1) unstable; urgency=medium ++ ++ * version 0.6.0-1 ++ ++ -- Richard Aas Mon, 11 Mar 2019 13:00:00 +0100 ++ + librem (0.6.0) unstable; urgency=medium + + * version 0.6.0 +diff --git a/debian/control b/debian/control +index 34b7a62..f03728a 100644 +--- a/debian/control ++++ b/debian/control +@@ -17,6 +17,6 @@ Description: Audio and video processing media library + Package: librem-dev + Architecture: any + Section: libdevel +-Depends: librem (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends} ++Depends: librem (= ${binary:Version}), ${misc:Depends} + Description: Audio and video processing media library (development files) + Development package for librem +diff --git a/debian/rules b/debian/rules +index ae23c06..a1da56e 100755 +--- a/debian/rules ++++ b/debian/rules +@@ -83,7 +83,7 @@ binary-arch: build install + dh_fixperms + # dh_perl + # dh_python +-# dh_makeshlibs ++ dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol +diff --git a/debian/source/format b/debian/source/format +new file mode 100644 +index 0000000..d3827e7 +--- /dev/null ++++ b/debian/source/format +@@ -0,0 +1 @@ ++1.0 +diff --git a/docs/COPYING b/docs/COPYING +index 643039e..1b8c3af 100644 +--- a/docs/COPYING ++++ b/docs/COPYING +@@ -1,6 +1,6 @@ +-Copyright (c) 2010 - 2018, Alfred E. Heggestad +-Copyright (c) 2010 - 2018, Richard Aas +-Copyright (c) 2010 - 2018, Creytiv.com ++Copyright (c) 2010 - 2019, Alfred E. Heggestad ++Copyright (c) 2010 - 2019, Richard Aas ++Copyright (c) 2010 - 2019, Creytiv.com + All rights reserved. + + +diff --git a/include/rem_aac.h b/include/rem_aac.h +new file mode 100644 +index 0000000..f6e9b2c +--- /dev/null ++++ b/include/rem_aac.h +@@ -0,0 +1,15 @@ ++/** ++ * @file rem_aac.h Advanced Audio Coding ++ * ++ * Copyright (C) 2010 Creytiv.com ++ */ ++ ++ ++/** Defines the AAC header */ ++struct aac_header { ++ unsigned sample_rate; /**< Audio sample rate in [Hz] */ ++ unsigned channels; /**< Number of audio channels */ ++ unsigned frame_size; /**< Frame size, 960 or 1024 bits */ ++}; ++ ++int aac_header_decode(struct aac_header *hdr, const uint8_t *p, size_t len); +diff --git a/include/rem_audio.h b/include/rem_audio.h +index e543a6f..02eb243 100644 +--- a/include/rem_audio.h ++++ b/include/rem_audio.h +@@ -16,3 +16,4 @@ + #include "rem_goertzel.h" + #include "rem_auresamp.h" + #include "rem_g711.h" ++#include "rem_aac.h" +diff --git a/include/rem_flv.h b/include/rem_flv.h +index 395206e..abc8338 100644 +--- a/include/rem_flv.h ++++ b/include/rem_flv.h +@@ -11,6 +11,8 @@ + + enum flv_aucodec { + FLV_AUCODEC_PCM = 0, ++ FLV_AUCODEC_MP3 = 2, ++ FLV_AUCODEC_PCM_LE = 3, + FLV_AUCODEC_ALAW = 7, + FLV_AUCODEC_ULAW = 8, + FLV_AUCODEC_AAC = 10, +diff --git a/include/rem_g711.h b/include/rem_g711.h +index 8476445..b093aab 100644 +--- a/include/rem_g711.h ++++ b/include/rem_g711.h +@@ -18,8 +18,9 @@ extern const int16_t g711_A2l[256]; + * + * @return U-law byte + */ +-static inline uint8_t g711_pcm2ulaw(int16_t l) ++static inline uint8_t g711_pcm2ulaw(int16_t lx) + { ++ int32_t l = lx; + const uint8_t mask = (l < 0) ? 0x7f : 0xff; + if (l < 0) + l = -l; +@@ -43,7 +44,7 @@ static inline uint8_t g711_pcm2alaw(int16_t l) + { + const uint8_t mask = (l < 0) ? 0x7f : 0xff; + if (l < 0) +- l = -l; ++ l = ~l; + l >>= 4; + + return g711_l2A[l] & mask; +diff --git a/include/rem_h264.h b/include/rem_h264.h +new file mode 100644 +index 0000000..0d8dbc0 +--- /dev/null ++++ b/include/rem_h264.h +@@ -0,0 +1,75 @@ ++/** ++ * @file rem_h264.h Interface to H.264 header parser ++ * ++ * Copyright (C) 2010 Creytiv.com ++ */ ++ ++ ++/** NAL unit types */ ++enum h264_nalu { ++ H264_NALU_SLICE = 1, ++ H264_NALU_DPA = 2, ++ H264_NALU_DPB = 3, ++ H264_NALU_DPC = 4, ++ H264_NALU_IDR_SLICE = 5, ++ H264_NALU_SEI = 6, ++ H264_NALU_SPS = 7, ++ H264_NALU_PPS = 8, ++ H264_NALU_AUD = 9, ++ H264_NALU_END_SEQUENCE = 10, ++ H264_NALU_END_STREAM = 11, ++ H264_NALU_FILLER_DATA = 12, ++ H264_NALU_SPS_EXT = 13, ++ H264_NALU_AUX_SLICE = 19, ++ ++ H264_NALU_STAP_A = 24, ++ H264_NALU_STAP_B = 25, ++ H264_NALU_MTAP16 = 26, ++ H264_NALU_MTAP24 = 27, ++ H264_NALU_FU_A = 28, ++ H264_NALU_FU_B = 29, ++}; ++ ++ ++/** ++ * H.264 NAL Header ++ */ ++struct h264_nal_header { ++ unsigned f:1; /**< Forbidden zero bit (must be 0) */ ++ unsigned nri:2; /**< nal_ref_idc */ ++ unsigned type:5; /**< NAL unit type */ ++}; ++ ++ ++int h264_nal_header_encode(struct mbuf *mb, const struct h264_nal_header *hdr); ++int h264_nal_header_decode(struct h264_nal_header *hdr, struct mbuf *mb); ++const char *h264_nal_unit_name(enum h264_nalu nal_type); ++ ++ ++/** ++ * H.264 Sequence Parameter Set (SPS) ++ */ ++struct h264_sps { ++ uint8_t profile_idc; ++ uint8_t level_idc; ++ uint8_t seq_parameter_set_id; /* 0-31 */ ++ uint8_t chroma_format_idc; /* 0-3 */ ++ ++ unsigned log2_max_frame_num; ++ unsigned pic_order_cnt_type; ++ ++ unsigned max_num_ref_frames; ++ unsigned pic_width_in_mbs; ++ unsigned pic_height_in_map_units; ++ ++ unsigned frame_crop_left_offset; /* pixels */ ++ unsigned frame_crop_right_offset; /* pixels */ ++ unsigned frame_crop_top_offset; /* pixels */ ++ unsigned frame_crop_bottom_offset; /* pixels */ ++}; ++ ++struct vidsz; ++ ++int h264_sps_decode(struct h264_sps *sps, const uint8_t *p, size_t len); ++void h264_sps_resolution(const struct h264_sps *sps, struct vidsz *sz); ++const char *h264_sps_chroma_format_name(uint8_t chroma_format_idc); +diff --git a/include/rem_video.h b/include/rem_video.h +index 73b4c77..c15692c 100644 +--- a/include/rem_video.h ++++ b/include/rem_video.h +@@ -9,3 +9,4 @@ + #include "rem_vidmix.h" + #include "rem_vidconv.h" + #include "rem_avc.h" ++#include "rem_h264.h" +diff --git a/mk/win32/rem.vcxproj b/mk/win32/rem.vcxproj +index b64f67f..313caf9 100644 +--- a/mk/win32/rem.vcxproj ++++ b/mk/win32/rem.vcxproj +@@ -50,17 +50,17 @@ + rem-win32 + {3E767371-A72B-4F5C-A695-8F844B0889C5} + Win32Proj +- 8.1 ++ 10.0.17763.0 + + + + StaticLibrary +- v140 ++ v141 + MultiByte + + + StaticLibrary +- v140 ++ v141 + MultiByte + + +@@ -90,7 +90,6 @@ + Default + ..\..\include;..\..\..\re\include;..\..\..\misc;%(AdditionalIncludeDirectories) + WIN32;_CONSOLE;HAVE_SELECT;HAVE_IO_H;_CRT_SECURE_NO_DEPRECATE;FD_SETSIZE=1024;_DEBUG;%(PreprocessorDefinitions) +- true + EnableFastChecks + MultiThreadedDebug + +@@ -107,7 +106,7 @@ + + ..\..\include;..\..\..\re\include;..\..\..\misc;%(AdditionalIncludeDirectories) + WIN32;_CONSOLE;HAVE_SELECT;HAVE_IO_H;_CRT_SECURE_NO_DEPRECATE;FD_SETSIZE=1024;NDEBUG;%(PreprocessorDefinitions) +- MultiThreadedDLL ++ MultiThreaded + + Level3 + ProgramDatabase +diff --git a/src/aac/aac.c b/src/aac/aac.c +new file mode 100644 +index 0000000..58a67c2 +--- /dev/null ++++ b/src/aac/aac.c +@@ -0,0 +1,69 @@ ++/** ++ * @file aac.c Advanced Audio Coding ++ * ++ * Copyright (C) 2018 Creytiv.com ++ */ ++ ++#include ++#include ++ ++ ++/* ++ * Ref https://wiki.multimedia.cx/index.php/MPEG-4_Audio ++ */ ++ ++enum { ++ OBJECT_TYPE_AAC_LC = 2 ++}; ++ ++ ++static const unsigned aac_sample_rates[13] = { ++ 96000, 88200, 64000, 48000, 44100, 32000, ++ 24000, 22050, 16000, 12000, 11025, 8000, 7350 ++}; ++ ++ ++static const unsigned aac_channels[8] = { ++ 0, 1, 2, 3, 4, 5, 6, 8 ++}; ++ ++ ++/** ++ * Decode an AAC header ++ * ++ * @param hdr Decoded AAC header ++ * @param p Packet to decode ++ * @param len Packet length ++ * ++ * @return 0 if success, otherwise errorcode ++ */ ++int aac_header_decode(struct aac_header *hdr, const uint8_t *p, size_t len) ++{ ++ uint8_t object_type; ++ uint8_t srate_index; ++ uint8_t channel_index; ++ ++ if (!hdr || !p || len<2) ++ return EINVAL; ++ ++ object_type = (p[0] >> 3) & 0x1f; ++ ++ if (object_type != OBJECT_TYPE_AAC_LC) ++ return EBADMSG; ++ ++ srate_index = (p[0] & 0x07) << 1; ++ srate_index |= (p[1] & 0x80) >> 7; ++ ++ channel_index = (p[1] >> 3) & 0xf; ++ ++ if (srate_index >= ARRAY_SIZE(aac_sample_rates)) ++ return ENOTSUP; ++ if (channel_index >= ARRAY_SIZE(aac_channels)) ++ return ENOTSUP; ++ ++ hdr->sample_rate = aac_sample_rates[srate_index]; ++ hdr->channels = aac_channels[channel_index]; ++ hdr->frame_size = ((p[1] >> 2) & 1) ? 960 : 1024; ++ ++ return 0; ++} +diff --git a/src/aac/mod.mk b/src/aac/mod.mk +new file mode 100644 +index 0000000..35a5c71 +--- /dev/null ++++ b/src/aac/mod.mk +@@ -0,0 +1,7 @@ ++# ++# mod.mk ++# ++# Copyright (C) 2010 Creytiv.com ++# ++ ++SRCS += aac/aac.c +diff --git a/src/h264/getbit.c b/src/h264/getbit.c +new file mode 100644 +index 0000000..f6f3531 +--- /dev/null ++++ b/src/h264/getbit.c +@@ -0,0 +1,92 @@ ++/** ++ * @file h264/getbit.c Generic bit parser ++ * ++ * Copyright (C) 2010 Creytiv.com ++ */ ++ ++#include ++#include ++#include "h264.h" ++ ++ ++void getbit_init(struct getbit *gb, const uint8_t *buf, size_t size) ++{ ++ if (!gb) ++ return; ++ ++ gb->buf = buf; ++ gb->pos = 0; ++ gb->end = size; ++} ++ ++ ++size_t getbit_get_left(const struct getbit *gb) ++{ ++ if (!gb) ++ return 0; ++ ++ if (gb->end > gb->pos) ++ return gb->end - gb->pos; ++ else ++ return 0; ++} ++ ++ ++unsigned get_bit(struct getbit *gb) ++{ ++ const uint8_t *p; ++ register unsigned tmp; ++ ++ if (!gb) ++ return 0; ++ ++ if (gb->pos >= gb->end) { ++ re_fprintf(stderr, "get_bit: read past end" ++ " (%zu >= %zu)\n", gb->pos, gb->end); ++ return 0; ++ } ++ ++ p = gb->buf; ++ tmp = ((*(p + (gb->pos >> 0x3))) >> (0x7 - (gb->pos & 0x7))) & 0x1; ++ ++ ++gb->pos; ++ ++ return tmp; ++} ++ ++ ++int get_ue_golomb(struct getbit *gb, unsigned *valp) ++{ ++ unsigned zeros = 0; ++ unsigned info; ++ int i; ++ ++ if (!gb) ++ return EINVAL; ++ ++ while (1) { ++ ++ if (getbit_get_left(gb) < 1) ++ return EBADMSG; ++ ++ if (0 == get_bit(gb)) ++ ++zeros; ++ else ++ break; ++ } ++ ++ info = 1 << zeros; ++ ++ for (i = zeros - 1; i >= 0; i--) { ++ ++ if (getbit_get_left(gb) < 1) ++ return EBADMSG; ++ ++ info |= get_bit(gb) << i; ++ } ++ ++ if (valp) ++ *valp = info - 1; ++ ++ return 0; ++} +diff --git a/src/h264/h264.h b/src/h264/h264.h +new file mode 100644 +index 0000000..105e3b5 +--- /dev/null ++++ b/src/h264/h264.h +@@ -0,0 +1,18 @@ ++/** ++ * @file h264/h264.h Internal interface ++ * ++ * Copyright (C) 2010 Creytiv.com ++ */ ++ ++ ++struct getbit { ++ const uint8_t *buf; ++ size_t pos; ++ size_t end; ++}; ++ ++ ++void getbit_init(struct getbit *gb, const uint8_t *buf, size_t size); ++size_t getbit_get_left(const struct getbit *gb); ++unsigned get_bit(struct getbit *gb); ++int get_ue_golomb(struct getbit *gb, unsigned *valp); +diff --git a/src/h264/mod.mk b/src/h264/mod.mk +new file mode 100644 +index 0000000..abe8433 +--- /dev/null ++++ b/src/h264/mod.mk +@@ -0,0 +1,9 @@ ++# ++# mod.mk ++# ++# Copyright (C) 2010 Creytiv.com ++# ++ ++SRCS += h264/getbit.c ++SRCS += h264/nal.c ++SRCS += h264/sps.c +diff --git a/src/h264/nal.c b/src/h264/nal.c +new file mode 100644 +index 0000000..7d71077 +--- /dev/null ++++ b/src/h264/nal.c +@@ -0,0 +1,94 @@ ++/** ++ * @file h264/nal.c H.264 header parser ++ * ++ * Copyright (C) 2010 Creytiv.com ++ */ ++ ++#include ++#include ++#include ++ ++ ++/** ++ * Encode H.264 NAL header ++ * ++ * @param mb Buffer to encode into ++ * @param hdr H.264 NAL header to encode ++ * ++ * @return 0 if success, otherwise errorcode ++ */ ++int h264_nal_header_encode(struct mbuf *mb, const struct h264_nal_header *hdr) ++{ ++ uint8_t v; ++ ++ if (!mb || !hdr) ++ return EINVAL; ++ ++ v = hdr->f<<7 | hdr->nri<<5 | hdr->type; ++ ++ return mbuf_write_u8(mb, v); ++} ++ ++ ++/** ++ * Decode H.264 NAL header ++ * ++ * @param hdr H.264 NAL header to decode into ++ * @param mb Buffer to decode ++ * ++ * @return 0 if success, otherwise errorcode ++ */ ++int h264_nal_header_decode(struct h264_nal_header *hdr, struct mbuf *mb) ++{ ++ uint8_t v; ++ ++ if (!hdr || !mb) ++ return EINVAL; ++ if (mbuf_get_left(mb) < 1) ++ return EBADMSG; ++ ++ v = mbuf_read_u8(mb); ++ ++ hdr->f = v>>7 & 0x1; ++ hdr->nri = v>>5 & 0x3; ++ hdr->type = v & 0x1f; ++ ++ return 0; ++} ++ ++ ++/** ++ * Get the name of an H.264 NAL unit ++ * ++ * @param nal_type NAL unit type ++ * ++ * @return A string containing the NAL unit name ++ */ ++const char *h264_nal_unit_name(enum h264_nalu nal_type) ++{ ++ switch (nal_type) { ++ ++ case H264_NALU_SLICE: return "SLICE"; ++ case H264_NALU_DPA: return "DPA"; ++ case H264_NALU_DPB: return "DPB"; ++ case H264_NALU_DPC: return "DPC"; ++ case H264_NALU_IDR_SLICE: return "IDR_SLICE"; ++ case H264_NALU_SEI: return "SEI"; ++ case H264_NALU_SPS: return "SPS"; ++ case H264_NALU_PPS: return "PPS"; ++ case H264_NALU_AUD: return "AUD"; ++ case H264_NALU_END_SEQUENCE: return "END_SEQUENCE"; ++ case H264_NALU_END_STREAM: return "END_STREAM"; ++ case H264_NALU_FILLER_DATA: return "FILLER_DATA"; ++ case H264_NALU_SPS_EXT: return "SPS_EXT"; ++ case H264_NALU_AUX_SLICE: return "AUX_SLICE"; ++ case H264_NALU_STAP_A: return "STAP-A"; ++ case H264_NALU_STAP_B: return "STAP-B"; ++ case H264_NALU_MTAP16: return "MTAP16"; ++ case H264_NALU_MTAP24: return "MTAP24"; ++ case H264_NALU_FU_A: return "FU-A"; ++ case H264_NALU_FU_B: return "FU-B"; ++ } ++ ++ return "???"; ++} +diff --git a/src/h264/sps.c b/src/h264/sps.c +new file mode 100644 +index 0000000..605a33d +--- /dev/null ++++ b/src/h264/sps.c +@@ -0,0 +1,341 @@ ++/** ++ * @file h264/sps.c H.264 SPS parser ++ * ++ * Copyright (C) 2010 Creytiv.com ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "h264.h" ++ ++ ++enum { ++ MAX_SPS_COUNT = 32, ++ MAX_LOG2_MAX_FRAME_NUM = 16, ++ MACROBLOCK_SIZE = 16, ++}; ++ ++#define MAX_MACROBLOCKS 1048576u ++ ++ ++static int scaling_list(struct getbit *gb, ++ unsigned *scaling_list, size_t sizeofscalinglist, ++ bool *usedefaultscalingmatrix) ++{ ++ unsigned lastscale = 8; ++ unsigned nextscale = 8; ++ size_t j; ++ int err; ++ ++ for (j = 0; j < sizeofscalinglist; j++) { ++ ++ if (nextscale != 0) { ++ ++ unsigned delta_scale; ++ ++ err = get_ue_golomb(gb, &delta_scale); ++ if (err) ++ return err; ++ ++ nextscale = (lastscale + delta_scale + 256) % 256; ++ ++ *usedefaultscalingmatrix = (j==0 && nextscale==0); ++ } ++ ++ scaling_list[j] = (nextscale==0) ? lastscale : nextscale; ++ ++ lastscale = scaling_list[j]; ++ } ++ ++ return 0; ++} ++ ++ ++static int decode_scaling_matrix(struct getbit *gb, unsigned chroma_format_idc) ++{ ++ unsigned scalinglist4x4[16]; ++ unsigned scalinglist8x8[64]; ++ bool usedefaultscalingmatrix[12]; ++ unsigned i; ++ int err; ++ ++ for (i = 0; i < ((chroma_format_idc != 3) ? 8 : 12); i++) { ++ ++ unsigned seq_scaling_list_present_flag; ++ ++ if (getbit_get_left(gb) < 1) ++ return EBADMSG; ++ ++ seq_scaling_list_present_flag = get_bit(gb); ++ ++ if (seq_scaling_list_present_flag) { ++ ++ if (i < 6) { ++ err = scaling_list(gb, scalinglist4x4, 16, ++ &usedefaultscalingmatrix[i]); ++ } ++ else { ++ err = scaling_list(gb, scalinglist8x8, 64, ++ &usedefaultscalingmatrix[i]); ++ } ++ ++ if (err) ++ return err; ++ } ++ } ++ ++ return 0; ++} ++ ++ ++/** ++ * Decode a Sequence Parameter Set (SPS) bitstream ++ * ++ * @param sps Decoded H.264 SPS ++ * @param p SPS bitstream to decode, excluding NAL header ++ * @param len Number of bytes ++ * ++ * @return 0 if success, otherwise errorcode ++ */ ++int h264_sps_decode(struct h264_sps *sps, const uint8_t *p, size_t len) ++{ ++ struct getbit gb; ++ uint8_t profile_idc; ++ unsigned seq_parameter_set_id; ++ unsigned frame_mbs_only_flag; ++ unsigned chroma_format_idc = 1; ++ bool frame_cropping_flag; ++ unsigned mb_w_m1; ++ unsigned mb_h_m1; ++ int err; ++ ++ if (!sps || !p || len < 3) ++ return EINVAL; ++ ++ memset(sps, 0, sizeof(*sps)); ++ ++ profile_idc = p[0]; ++ sps->level_idc = p[2]; ++ ++ getbit_init(&gb, p+3, (len-3)*8); ++ ++ err = get_ue_golomb(&gb, &seq_parameter_set_id); ++ if (err) ++ return err; ++ ++ if (seq_parameter_set_id >= MAX_SPS_COUNT) { ++ re_fprintf(stderr, "h264: sps: sps_id %u out of range\n", ++ seq_parameter_set_id); ++ return EBADMSG; ++ } ++ ++ if (profile_idc == 100 || ++ profile_idc == 110 || ++ profile_idc == 122 || ++ profile_idc == 244 || ++ profile_idc == 44 || ++ profile_idc == 83 || ++ profile_idc == 86 || ++ profile_idc == 118 || ++ profile_idc == 128 || ++ profile_idc == 138 || ++ profile_idc == 144) { ++ ++ unsigned seq_scaling_matrix_present_flag; ++ ++ err = get_ue_golomb(&gb, &chroma_format_idc); ++ if (err) ++ return err; ++ ++ if (chroma_format_idc > 3U) { ++ return EBADMSG; ++ } ++ else if (chroma_format_idc == 3) { ++ ++ if (getbit_get_left(&gb) < 1) ++ return EBADMSG; ++ ++ /* separate_colour_plane_flag */ ++ (void)get_bit(&gb); ++ } ++ ++ /* bit_depth_luma/chroma */ ++ err = get_ue_golomb(&gb, NULL); ++ err |= get_ue_golomb(&gb, NULL); ++ if (err) ++ return err; ++ ++ if (getbit_get_left(&gb) < 2) ++ return EBADMSG; ++ ++ /* qpprime_y_zero_transform_bypass_flag */ ++ get_bit(&gb); ++ ++ seq_scaling_matrix_present_flag = get_bit(&gb); ++ if (seq_scaling_matrix_present_flag) { ++ ++ err = decode_scaling_matrix(&gb, chroma_format_idc); ++ if (err) ++ return err; ++ } ++ } ++ ++ err = get_ue_golomb(&gb, &sps->log2_max_frame_num); ++ if (err) ++ return err; ++ ++ sps->log2_max_frame_num += 4; ++ ++ if (sps->log2_max_frame_num > MAX_LOG2_MAX_FRAME_NUM) { ++ re_fprintf(stderr, "h264: sps: log2_max_frame_num" ++ " out of range: %u\n", sps->log2_max_frame_num); ++ return EBADMSG; ++ } ++ ++ err = get_ue_golomb(&gb, &sps->pic_order_cnt_type); ++ if (err) ++ return err; ++ ++ if (sps->pic_order_cnt_type == 0) { ++ ++ /* log2_max_pic_order_cnt_lsb */ ++ err = get_ue_golomb(&gb, NULL); ++ if (err) ++ return err; ++ } ++ else if (sps->pic_order_cnt_type == 2) { ++ } ++ else { ++ re_fprintf(stderr, "h264: sps: WARNING:" ++ " unknown pic_order_cnt_type (%u)\n", ++ sps->pic_order_cnt_type); ++ return ENOTSUP; ++ } ++ ++ err = get_ue_golomb(&gb, &sps->max_num_ref_frames); ++ if (err) ++ return err; ++ ++ if (getbit_get_left(&gb) < 1) ++ return EBADMSG; ++ ++ /* gaps_in_frame_num_value_allowed_flag */ ++ (void)get_bit(&gb); ++ ++ err = get_ue_golomb(&gb, &mb_w_m1); ++ err |= get_ue_golomb(&gb, &mb_h_m1); ++ if (err) ++ return err; ++ ++ if (getbit_get_left(&gb) < 1) ++ return EBADMSG; ++ frame_mbs_only_flag = get_bit(&gb); ++ ++ sps->pic_width_in_mbs = mb_w_m1 + 1; ++ sps->pic_height_in_map_units = mb_h_m1 + 1; ++ ++ sps->pic_height_in_map_units *= 2 - frame_mbs_only_flag; ++ ++ if (sps->pic_width_in_mbs >= MAX_MACROBLOCKS || ++ sps->pic_height_in_map_units >= MAX_MACROBLOCKS) { ++ re_fprintf(stderr, "h264: sps: width/height overflow\n"); ++ return EBADMSG; ++ } ++ ++ if (!frame_mbs_only_flag) { ++ ++ if (getbit_get_left(&gb) < 1) ++ return EBADMSG; ++ ++ /* mb_adaptive_frame_field_flag */ ++ (void)get_bit(&gb); ++ } ++ ++ if (getbit_get_left(&gb) < 1) ++ return EBADMSG; ++ ++ /* direct_8x8_inference_flag */ ++ (void)get_bit(&gb); ++ ++ if (getbit_get_left(&gb) < 1) ++ return EBADMSG; ++ ++ frame_cropping_flag = get_bit(&gb); ++ ++ if (frame_cropping_flag) { ++ ++ unsigned crop_left; ++ unsigned crop_right; ++ unsigned crop_top; ++ unsigned crop_bottom; ++ ++ unsigned vsub = (chroma_format_idc == 1) ? 1 : 0; ++ unsigned hsub = (chroma_format_idc == 1 || ++ chroma_format_idc == 2) ? 1 : 0; ++ unsigned sx = 1u << hsub; ++ unsigned sy = (2u - frame_mbs_only_flag) << vsub; ++ ++ unsigned w = MACROBLOCK_SIZE * sps->pic_width_in_mbs; ++ unsigned h = MACROBLOCK_SIZE * sps->pic_height_in_map_units; ++ ++ err = get_ue_golomb(&gb, &crop_left); ++ err |= get_ue_golomb(&gb, &crop_right); ++ err |= get_ue_golomb(&gb, &crop_top); ++ err |= get_ue_golomb(&gb, &crop_bottom); ++ if (err) ++ return err; ++ ++ if ((crop_left + crop_right ) * sx >= w || ++ (crop_top + crop_bottom) * sy >= h) { ++ re_fprintf(stderr, "h264: sps: crop values invalid" ++ " %u %u %u %u / %u %u\n", ++ crop_left, crop_right, crop_top, ++ crop_bottom, w, h); ++ return EBADMSG; ++ } ++ ++ sps->frame_crop_left_offset = sx * crop_left; ++ sps->frame_crop_right_offset = sx * crop_right; ++ sps->frame_crop_top_offset = sy * crop_top; ++ sps->frame_crop_bottom_offset = sy * crop_bottom; ++ } ++ ++ /* success */ ++ sps->profile_idc = profile_idc; ++ sps->seq_parameter_set_id = (uint8_t)seq_parameter_set_id; ++ sps->chroma_format_idc = chroma_format_idc; ++ ++ return 0; ++} ++ ++ ++void h264_sps_resolution(const struct h264_sps *sps, struct vidsz *sz) ++{ ++ if (!sps || !sz) ++ return; ++ ++ sz->w = MACROBLOCK_SIZE * sps->pic_width_in_mbs ++ - sps->frame_crop_left_offset ++ - sps->frame_crop_right_offset; ++ ++ sz->h = MACROBLOCK_SIZE * sps->pic_height_in_map_units ++ - sps->frame_crop_top_offset ++ - sps->frame_crop_bottom_offset; ++} ++ ++ ++const char *h264_sps_chroma_format_name(uint8_t chroma_format_idc) ++{ ++ switch (chroma_format_idc) { ++ ++ case 0: return "monochrome"; ++ case 1: return "YUV420"; ++ case 2: return "YUV422"; ++ case 3: return "YUV444"; ++ default: return "???"; ++ } ++} +diff --git a/src/vid/frame.c b/src/vid/frame.c +index 9d2ec14..71944a6 100644 +--- a/src/vid/frame.c ++++ b/src/vid/frame.c +@@ -188,7 +188,8 @@ int vidframe_alloc(struct vidframe **vfp, enum vidfmt fmt, + void vidframe_fill(struct vidframe *vf, uint32_t r, uint32_t g, uint32_t b) + { + uint8_t *p; +- unsigned h, i; ++ unsigned h, i, x; ++ int u, v; + + if (!vf) + return; +@@ -221,6 +222,34 @@ void vidframe_fill(struct vidframe *vf, uint32_t r, uint32_t g, uint32_t b) + } + break; + ++ case VID_FMT_NV12: ++ case VID_FMT_NV21: ++ h = vf->size.h; ++ ++ if (vf->fmt == VID_FMT_NV12) { ++ u = rgb2u(r, g, b); ++ v = rgb2v(r, g, b); ++ } ++ else { ++ v = rgb2u(r, g, b); ++ u = rgb2v(r, g, b); ++ } ++ ++ memset(vf->data[0], rgb2y(r, g, b), h * vf->linesize[0]); ++ ++ p = vf->data[1]; ++ ++ for (h=0; hsize.h; h+=2) { ++ ++ for (x=0; xsize.w; x+=2) { ++ p[x ] = u; ++ p[x+1] = v; ++ } ++ ++ p += vf->linesize[1]; ++ } ++ break; ++ + default: + (void)re_printf("vidfill: no fmt %s\n", vidfmt_name(vf->fmt)); + break; diff --git a/librem.spec b/librem.spec new file mode 100644 index 0000000..0bc0326 --- /dev/null +++ b/librem.spec @@ -0,0 +1,85 @@ +# No upstream .so name versioning: https://github.com/creytiv/rem/issues/40 +%global soversion 0 + +Summary: Library for real-time audio and video processing +Name: librem +Version: 0.6.0 +Release: 2%{?dist} +License: BSD +URL: http://www.creytiv.com/rem.html +Source0: https://github.com/creytiv/rem/archive/v%{version}/rem-%{version}.tar.gz +# Latest fixes from Git (not yet available in a release) +Patch0: librem-0.6.0-52bbacb.patch +BuildRequires: make +BuildRequires: gcc +BuildRequires: libre-devel +# Cover multiple third party repositories +Obsoletes: librem0 < 0.6.0-2 +Provides: librem0 = %{version}-%{release} +Provides: librem0%{?_isa} = %{version}-%{release} +Obsoletes: rem < 0.6.0-2 +Provides: rem = %{version}-%{release} +Provides: rem%{?_isa} = %{version}-%{release} + +%description +Librem is a portable and generic library for real-time audio and video +processing. + +%package devel +Summary: Development files for the rem library +Requires: %{name}%{?_isa} = %{version}-%{release} +Requires: pkgconfig +Requires: libre-devel +# Cover multiple third party repositories +Obsoletes: librem0-devel < 0.6.0-2 +Provides: librem0-devel = %{version}-%{release} +Provides: librem0-devel%{?_isa} = %{version}-%{release} +Obsoletes: rem-devel < 0.6.0-2 +Provides: rem-devel = %{version}-%{release} +Provides: rem-devel%{?_isa} = %{version}-%{release} + +%description devel +The librem-devel package includes header files and libraries necessary for +developing programs which use the rem C library. + +%prep +%setup -q -n rem-%{version} +%patch0 -p1 -b .52bbacb + +%build +%make_build \ + SHELL='sh -x' \ + RELEASE=1 \ + EXTRA_CFLAGS="$RPM_OPT_FLAGS" \ + EXTRA_LFLAGS="$RPM_LD_FLAGS" \ + LIB_SUFFIX=.so.%{soversion} \ + SH_LFLAGS="-shared -Wl,-soname,librem.so.%{soversion}" + +%install +%make_install \ + LIBDIR=%{_libdir} \ + LIB_SUFFIX=.so.%{soversion} + +# Create missing symlink and remove static library +ln -s %{name}.so.%{soversion} $RPM_BUILD_ROOT%{_libdir}/%{name}.so +rm -f $RPM_BUILD_ROOT%{_libdir}/%{name}.a + +%ldconfig_scriptlets + +%files +%license docs/COPYING +%doc docs/ChangeLog +%{_libdir}/%{name}.so.%{soversion} + +%files devel +%{_libdir}/%{name}.so +%{_includedir}/rem/ +%{_libdir}/pkgconfig/%{name}.pc + +%changelog +* Sun Jun 28 2020 Robert Scheck 0.6.0-2 +- Changes to match the Fedora Packaging Guidelines (#1843268 #c1) + +* Thu May 28 2020 Robert Scheck 0.6.0-1 +- Upgrade to 0.6.0 (#1843268) +- Initial spec file for Fedora and Red Hat Enterprise Linux diff --git a/sources b/sources new file mode 100644 index 0000000..1d3f095 --- /dev/null +++ b/sources @@ -0,0 +1 @@ +SHA512 (rem-0.6.0.tar.gz) = 1889d9b62a0456c029f64a8066bc5a07ba7125a3b22067921bd51e0f9d105052c67e3e06c69d591222aa0ca97357ec29e58ca0ee246071ea1900627ba5d6dfdf