Compare commits

...

463 Commits
v0.92 ... v0.96

Author SHA1 Message Date
Carlos Fernandez Sanz
a8f25ce25e fix(installer): Fix Windows MSI installer for WiX v6 2025-12-25 11:53:45 +01:00
Carlos Fernandez Sanz
2781a7f7d6 docs(mac): Add documentation for -system-libs build mode 2025-12-25 11:00:47 +01:00
Carlos Fernandez
903ccc1442 chore: trigger CI rerun 2025-12-25 09:59:16 +01:00
GAURAV KARMAKAR
941604b33c docs(mac): Add documentation for -system-libs build mode 2025-12-25 02:15:02 +05:30
Carlos Fernandez
1950f096b6 fix(workflow): Extract only numeric version for MSI
MSI version numbers must be numeric (major.minor.build format).
Strip everything after the first dash from tag names to get valid
version numbers (e.g., v1.08-test becomes 1.08).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 20:05:20 +01:00
Carlos Fernandez
1fc5ec00d4 fix(installer): Use correct WiX v4+ attribute name 'Scope' not 'InstallScope'
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 19:03:53 +01:00
Carlos Fernandez
c0deae4b0c fix(installer): Add InstallScope=perMachine and update InstallerVersion
- Set InstallScope="perMachine" to ensure proper admin-level registry access
- Bump InstallerVersion from 200 to 500 (Windows Installer 5.0)

This should fix the "Could not write key VersionMinor to Product" error.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 18:20:18 +01:00
Carlos Fernandez
84692b5658 fix(installer): Disable path validation to avoid local drive errors
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 17:23:09 +01:00
Carlos Fernandez
4a51ad114e fix(installer): Use custom UI without license dialog
Instead of trying to override WixUI_InstallDir, create a custom UI
based on it but without the LicenseAgreementDlg. This is the proper
way to remove dialogs from WiX UI sets.

- Add CustomUI.wxs with dialog flow: Welcome -> InstallDir -> VerifyReady
- Update installer.wxs to use CustomInstallDirUI instead of WixUI_InstallDir
- Update workflow to build both .wxs files

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 16:25:35 +01:00
Carlos Fernandez
6789376b92 fix(installer): Try Order=999 to force dialog override to fire last
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 16:01:43 +01:00
Carlos Fernandez
ea5125f030 fix(installer): Use Order attribute to override license dialog navigation
The previous Publish elements without Order didn't override the defaults.
Adding Order="1" ensures our overrides fire after the WixUI defaults,
making our InstallDirDlg navigation take precedence.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 13:45:28 +01:00
Carlos Fernandez Sanz
000b39775c Fix typo: 'sring' -> 'string' in DVB subtitle decoder 2025-12-24 12:02:34 +01:00
Carlos Fernandez
23fe02f0d2 fix(installer): Skip license dialog with Publish overrides
Override the WixUI_InstallDir dialog sequence to skip the license
agreement dialog, restoring the original behavior before WiX v6 migration.

- WelcomeDlg Next button now goes directly to InstallDirDlg
- InstallDirDlg Back button returns to WelcomeDlg

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 11:47:33 +01:00
Carlos Fernandez
394fb39a9c fix(installer): Update DLL list to match current build output
The installer.wxs was referencing old FFmpeg DLLs that no longer exist:
- avcodec-57.dll → avcodec-60.dll
- avformat-57.dll → avformat-60.dll
- avutil-55.dll → avutil-58.dll
- swresample-2.dll → swresample-4.dll
- swscale-4.dll → swscale-7.dll

Added new DLLs that are now part of the build:
- avdevice-60.dll, avfilter-9.dll, postproc-57.dll
- libgpac.dll, OpenSVCDecoder.dll
- libcryptoMD.dll, libsslMD.dll
- desktop_drop_plugin.dll

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 10:07:01 +01:00
Harshdhall01
294bf5bc18 Fix typo: 'sring' -> 'string' in DVB subtitle decoder 2025-12-24 13:54:47 +05:30
Carlos Fernandez
4e52e61c91 fix: Remove duplicate WiX property declarations
The <ui:WixUI Id="WixUI_InstallDir" InstallDirectory="INSTALLFOLDER" />
element already defines WIXUI_INSTALLDIR (via the InstallDirectory attribute)
and ARPNOMODIFY (in the wixlib). Declaring them again causes WIX0091 errors.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 09:05:55 +01:00
Carlos Fernandez
faaaabf63c fix(installer): Add missing WIXUI_INSTALLDIR property and fix RemoveFolder ID
- Added WIXUI_INSTALLDIR property (required per WiX issue #7105)
- Changed RemoveFolder Id from "DesktopFolder" to "RemoveDesktopShortcut"
  to avoid ID conflict with StandardDirectory element

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 07:28:33 +01:00
Carlos Fernandez
f5a9018ef0 fix(release): Upgrade WiX from v4.0.0-preview.0 to v6.0.2 stable
The WiX build was failing due to several WiX v4 to v6 migration issues.

Workflow changes:
- Uninstall existing WiX before installing v6.0.2 (force clean install)
- WiX version: 4.0.0-preview.0 -> 6.0.2
- Extension: WixToolset.UI.wixext/4.0.0-preview.0 -> WixToolset.UI.wixext/6.0.2
- Fixed extension command syntax: "extension -g add" -> "extension add -g"

installer.wxs changes (WiX v6 migration):
- Added ui namespace: xmlns:ui="http://wixtoolset.org/schemas/v4/wxs/ui"
- Replaced custom inline UI with standard <ui:WixUI Id="WixUI_InstallDir">
  (fixes WIX0094 error for WixUIValidatePath custom action)
- Changed Directory to StandardDirectory for DesktopFolder (fixes WIX5437)

See: https://github.com/orgs/wixtoolset/discussions/6516
     https://github.com/wixtoolset/issues/issues/6998

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 07:14:18 +01:00
Carlos Fernandez
e01720c05e fix: Use WiX extension by name instead of hardcoded path
The WiX v4 extension path was hardcoded and didn't match the actual
installed location. WiX v4 allows referencing globally installed
extensions by name directly.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 23:35:10 +01:00
Carlos Fernandez
f80b1f26ca fix(ci): Add -Force to Expand-Archive for Flutter GUI
The installer directory already has files from the copy step, so
Expand-Archive needs -Force to overwrite/merge.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 22:43:07 +01:00
Carlos Fernandez
f9ebfd2a32 fix(ci): Add vcpkg setup and fix permissions in release workflow
- Add permissions: contents: write for upload-release-assets
- Add vcpkg environment variables and setup steps from build_windows.yml
- Add gpac installation
- Add vcpkg clone, bootstrap, and dependency installation
- Add VCPKG_ROOT env var to build step
- Change runner to windows-2022 to match build workflow
- Add msbuild-architecture: x64
- Remove redundant llvm/clang setup (pre-installed on runner)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 21:53:40 +01:00
Carlos Fernandez
9f670de8ed fix(windows): Use latest Windows SDK instead of hardcoded version
Changed WindowsTargetPlatformVersion from 10.0.22621.0 to 10.0 to
automatically use whichever Windows 10 SDK is installed on the build
machine. This fixes CI failures when the runner has a different SDK
version installed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 21:20:51 +01:00
Carlos Fernandez
fc4a14e7d6 0.96 release, for real 2025-12-23 21:09:47 +01:00
Carlos Fernandez Sanz
4f13b861cd Merge pull request #1888 from CCExtractor/fix/release-workflow-x64
fix(ci): Update Windows release build to use x64 platform
2025-12-23 21:03:16 +01:00
Carlos Fernandez
df692f296d fix(ci): Update Windows release build to use x64 platform
The solution file only has x64 configurations (Release-Full|x64,
Debug-Full|x64). The workflow was incorrectly trying to build with
Win32 platform which doesn't exist.

Changes:
- Platform=Win32 → Platform=x64
- Output path ./Release-Full/ → ./x64/Release-Full/

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 20:58:56 +01:00
Carlos Fernandez Sanz
419fc4694d Changelog clean up and start of new version
docs: Add Upcoming section to changelog
2025-12-23 19:38:25 +01:00
Carlos Fernandez Sanz
fc230fc217 feat(teletext): Add multi-page extraction with separate output files (#665) 2025-12-23 19:37:12 +01:00
Carlos Fernandez
825e160e72 Clean up CHANGES.TXT 2025-12-23 19:33:23 +01:00
Carlos Fernandez
8e24c17c1e Clean up CHANGES.TXT 2025-12-23 19:30:32 +01:00
Carlos Fernandez
4e21fae053 docs: Add Upcoming section to changelog with teletext multi-page feature
Start new changelog section for unreleased changes. First entry is
the multi-page teletext extraction feature (#665) which allows
extracting multiple teletext pages simultaneously with separate
output files.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 17:42:50 +01:00
Carlos Fernandez
be239a5c46 fix: Restore teletext auto-detect mode for single-page extraction
The page update logic at line 1029-1035 was incorrectly updating
tlt_config.page for all accepted pages, even in single-page auto-detect
mode. This caused the auto-detect logic at line 979 to be bypassed
because the first packet (even with an invalid page number like 0xFF)
would set tlt_config.page, preventing proper auto-detection.

The fix restricts the page update to multi-page mode only. In single-page
mode, tlt_config.page is set exclusively by:
1. User specification (--tpage option)
2. Auto-detect logic (first valid subtitle page found)

This fixes regression in SP Test 76 which uses sample
8c1615c1a84d4b9b34134bde8085214bb93305407e935edcdfd4c2fc522c215f.mpg
with --autoprogram --out=ttxt --latin1.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 16:36:02 +01:00
Carlos Fernandez
1d9f32239e docs: Add doxygen comments to should_accept_page function
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 15:43:54 +01:00
Carlos Fernandez
cbb5f0b0a8 fix(clippy): Use RangeInclusive::contains() instead of manual range check
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 14:41:18 +01:00
Carlos Fernandez
fd063931ea feat(teletext): Add multi-page extraction with separate output files (#665)
Implement support for extracting multiple teletext pages simultaneously,
with each page output to a separate file.

Changes:
- Support multiple --tpage arguments (e.g., --tpage 397 --tpage 398)
- Create separate output files per page with _pNNN suffix
  (e.g., output_p397.srt, output_p398.srt)
- Maintain backward compatibility for single-page extraction (no suffix)
- Add per-page SRT counters for correct subtitle numbering
- Fix BCD to decimal page number conversion in telxcc.c
- Add --tpages-all mode support for auto-detecting all pages

Tested with 21 teletext samples from the sample platform, all passing.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 14:28:15 +01:00
Carlos Fernandez Sanz
7a9acb7bd2 Merge pull request #1883 from CCExtractor/dependabot/github_actions/actions/upload-artifact-6
build(deps): Bump actions/upload-artifact from 4 to 6
2025-12-23 10:19:30 +01:00
Carlos Fernandez Sanz
cbf180eb39 build(deps): Bump actions/checkout from 4 to 6 2025-12-23 10:19:16 +01:00
Carlos Fernandez Sanz
614e6c42b5 build(deps): Bump softprops/action-gh-release from 1 to 2 2025-12-23 10:18:50 +01:00
Carlos Fernandez Sanz
38bcb7ed85 Merge pull request #1884 from CCExtractor/dependabot/github_actions/actions/cache-5
Routine dependency update for GitHub Actions
2025-12-23 09:32:05 +01:00
Carlos Fernandez Sanz
d57354830e chore: Bump version to 0.96 2025-12-23 00:06:45 +01:00
Carlos Fernandez Sanz
7b43201ce1 fix(mp4/mkv): Add HEVC/H.265 caption extraction for MP4 and Matroska containers 2025-12-23 00:06:12 +01:00
Carlos Fernandez Sanz
ea1c82ac17 [FIX] Handle NULL bitmap gracefully in OCR instead of crashing (#1010) 2025-12-23 00:05:32 +01:00
dependabot[bot]
b3f1e27f5c build(deps): Bump actions/cache from 4 to 5
Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-22 18:02:20 +00:00
dependabot[bot]
82c92d3910 build(deps): Bump actions/upload-artifact from 4 to 6
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-22 18:02:11 +00:00
dependabot[bot]
5bf8e7de0d build(deps): Bump actions/checkout from 4 to 6
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-22 18:02:04 +00:00
dependabot[bot]
5b8a9709df build(deps): Bump softprops/action-gh-release from 1 to 2
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 1 to 2.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/v1...v2)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-version: '2'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-22 18:01:54 +00:00
Carlos Fernandez Sanz
063786c4b7 [FEATURE] Add AppImage build variants and CI workflow (#1348) 2025-12-22 09:12:36 +01:00
Carlos Fernandez
44363c0acd fix(mkv): Add HEVC/H.265 caption extraction for Matroska containers
Extends HEVC caption extraction support to MKV files.

Changes to matroska.h:
- Add hevc_codec_id constant for V_MPEGH/ISO/HEVC
- Add hevc_track_number field to matroska_ctx structure
- Add process_hevc_frame_mkv() function declaration

Changes to matroska.c:
- Detect HEVC tracks in parse_segment_track_entry()
- Modify parse_simple_block() to route HEVC tracks to HEVC processor
- Add process_hevc_frame_mkv() with is_hevc flag and store_hdcc() call
- Parse HEVCDecoderConfigurationRecord in parse_private_codec_data()
- Initialize hevc_track_number in matroska_loop()
- Update output messages to report HEVC tracks

Tested with HEVC MKV file - extracts 73 captions matching MP4 output.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 05:59:23 +01:00
Carlos Fernandez
701271ec82 fix(mp4): Add HEVC/H.265 caption extraction for MP4 containers
PR #1852 added HEVC caption extraction for MPEG-TS containers,
but MP4/MKV containers weren't supported. This adds HEVC support
for MP4 containers using GPAC.

Changes:
- Add HEVC subtype definitions (hev1, hvc1)
- Add process_hevc_sample() to parse HEVC NAL units and extract CC
- Add process_hevc_track() to iterate through HEVC track samples
- Detect and process HEVC tracks in processmp4()
- Add store_hdcc() call to flush buffered CC data after each sample

The key fix was adding store_hdcc() after processing each sample.
Without this, CC data was being parsed but never output because
store_hdcc() is normally called from slice_header() which is
AVC-only.

Closes #1690 (for MP4 containers)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 05:59:23 +01:00
Carlos Fernandez
7c74ea4112 docs: Add 0.96 (Unreleased) section to CHANGES.TXT
Move all changes made after the 0.95 version bump (commit ee232b5)
to a new 0.96 section marked as "Unreleased".

This separates the released 0.95 content from ongoing development
work that will be included in the next release.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 05:58:01 +01:00
Carlos Fernandez
ed42525f44 chore: Bump version to 0.96
Update version strings across all build configurations:
- src/lib_ccx/lib_ccx.h
- linux/configure.ac
- mac/configure.ac
- package_creators/PKGBUILD
- package_creators/ccextractor.spec
- package_creators/debian.sh
- OpenBSD/Makefile

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 05:58:01 +01:00
Carlos Fernandez
b88d1ebab2 fix(ci): Fix AppImage build failures for OCR and HardSubX variants
OCR build fix:
- linuxdeploy was failing with "Invalid magic bytes in file header"
  because it was passed the wrapper script instead of the actual binary
- When OCR is enabled, ccextractor is renamed to ccextractor.bin and
  a wrapper script sets TESSDATA_PREFIX before executing the binary
- Now correctly passes ccextractor.bin to linuxdeploy when it exists

HardSubX build fix:
- Add libavdevice-dev to FFmpeg dependencies in CI workflow
- rusty_ffmpeg requires libavdevice which was missing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 22:47:24 +01:00
Carlos Fernandez
ec11b00f9f fix(ci): Use correct Rust toolchain action name 2025-12-21 22:40:06 +01:00
Carlos Fernandez
8c0fe08781 feat: Add AppImage build variants and CI workflow (#1348)
Rewrites the AppImage build script to support three build variants
matching the Docker build options:
- minimal: Basic CCExtractor without OCR (smallest size)
- ocr: CCExtractor with OCR support (default)
- hardsubx: CCExtractor with burned-in subtitle extraction

Changes to build_appimage.sh:
- Add BUILD_TYPE environment variable to select variant
- Fix CMake options (was incorrectly using make flags)
- Bundle tessdata for OCR builds with wrapper script
- Create proper desktop file and icon handling
- Improve error handling and cleanup

New GitHub Actions workflow (build_appimage.yml):
- Builds all three variants on release
- Uploads AppImages as release assets
- Can be manually triggered for specific variants
- Caches GPAC build for faster CI runs

Usage:
  ./build_appimage.sh              # Builds 'ocr' variant
  BUILD_TYPE=minimal ./build_appimage.sh
  BUILD_TYPE=hardsubx ./build_appimage.sh

Closes #1348

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 22:37:22 +01:00
Carlos Fernandez
3304c1b094 fix(ocr): Handle NULL bitmap gracefully instead of crashing (#1010)
When processing DVB subtitles from live streams or corrupted files,
the bitmap clipping operation can fail, resulting in a NULL pix object.
Previously, this would cause a fatal crash with "Failed to perform OCR -
Failed to get text" because the code continued to call TessBaseAPIGetUTF8Text
even when no image was set.

Changes:
- Handle cpix_gs == NULL by logging a message and returning NULL
  (skip this bitmap) instead of continuing and crashing
- Change the fatal error when TessBaseAPIGetUTF8Text returns NULL
  to a non-fatal skip, since this can happen with empty/invalid bitmaps
- Both cases now properly clean up allocated resources before returning

This allows CCExtractor to gracefully skip problematic subtitle frames
instead of crashing, which is especially important for live streams
where packet loss or discontinuities can occur.

Fixes #1010

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 22:25:35 +01:00
Carlos Fernandez
5bad3732c3 chore: Remove plan files from git tracking
The plans/ directory is in .gitignore but these files were added
before that entry existed. Removing from tracking while keeping
files on disk.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 21:46:39 +01:00
Carlos Fernandez Sanz
e3b0defb49 build(rust): Upgrade bindgen to 0.72.1 for Fedora packaging 2025-12-21 21:38:02 +01:00
Carlos Fernandez Sanz
2065c5509d fix(windows): Fix c_long ABI mismatch causing Windows CI failures 2025-12-21 20:16:56 +01:00
Carlos Fernandez
5458370346 refactor: Replace c_longlong with i64 for consistency
For clarity and consistency, use explicit i64 instead of c_longlong.
While c_longlong is 64-bit on all platforms, i64 is clearer and
follows the same pattern as the previous commit that removed c_long.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 17:55:57 +01:00
Carlos Fernandez
9e19c58edf refactor: Replace platform-dependent 'long' with 'int64_t'
The C type 'long' has different sizes on different platforms:
- Linux: 64-bit
- Windows: 32-bit

This causes ABI mismatches when interfacing with Rust, since Rust's
c_long matches the platform's long size, but we were treating these
values as 64-bit throughout.

Changed the following fields from 'long' to 'int64_t':
- asf_constants.h: parsebufsize
- avc_functions.h: cc_databufsize, num_nal_unit_type_7, num_vcl_hrd,
  num_nal_hrd, num_jump_in_frames, num_unexpected_sei_length
- ccx_decoders_608.h: bytes_processed_608
- ccx_demuxer.h: capbufsize, capbuflen
- lib_ccx.h: ts_readstream() return type, FILEBUFFERSIZE
- file_functions.c: FILEBUFFERSIZE definition
- ts_functions.c: ts_readstream() implementation

Also updated Rust code in common.rs to remove c_long casts, since
bindgen will now generate i64 for these fields.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 17:52:24 +01:00
Carlos Fernandez Sanz
0bb56d508a fix(timing): Fix --goptime producing compressed timestamps 2025-12-21 17:50:53 +01:00
Carlos Fernandez
2c67381d2b fix(windows): Fix c_long ABI mismatch in demuxer.rs
The extern declaration for ccxr_add_current_pts used c_long, but the
actual implementation in time.rs uses i64. This caused an ABI mismatch
on Windows where:
- c_long = i32 (32-bit)
- i64 = 64-bit

On Linux both are 64-bit so it worked, but on Windows the type
mismatch could cause incorrect parameter passing.

Changes:
- Change extern fn declaration from c_long to i64
- Remove unnecessary cast (FRAME_DURATION_TICKS is already i64)
- Remove unused c_long import

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 17:00:50 +01:00
Carlos Fernandez
94a43928ad fix(timing): Fix --goptime producing compressed timestamps (Test 163)
When using --goptime, timestamps were compressed to 00:00:01-02 instead
of actual GOP times (17:56:40-47). This was caused by conflicts between:
- GOP timing set from GOP headers (wall-clock time, e.g., 17:56:40)
- PES PTS timing (stream-relative time, e.g., 00:00:02)

The sync detection saw these as 64,598-second "jumps" and kept resetting
timing, corrupting the output.

Fixes:
1. Guard video PES timing in general_loop.c - skip set_current_pts and
   set_fts when use_gop_as_pts == 1 to prevent PES PTS from overwriting
   GOP-based timing
2. Disable sync check in ccextractor.c when use_gop_as_pts == 1 since
   GOP time and PES PTS are in different time bases and sync detection
   is meaningless

Test results:
- Before: 00:00:01,231 --> 00:00:01,729
- After:  17:56:41,319 --> 17:56:43,084

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 12:34:05 +01:00
Carlos Fernandez Sanz
25d68b75bd fix(708): Support Korean EUC-KR encoding in CEA-708 decoder 2025-12-21 12:23:39 +01:00
Carlos Fernandez
73cd19f5d0 fix(rust): Use i64 instead of c_long for Windows compatibility
On Windows, c_long is i32 while on Linux it's i64. The function
ccxr_print_mstime_static expects i64, so casting to c_long caused
a type mismatch error on Windows builds.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 09:43:27 +01:00
Carlos Fernandez
d0caf23a82 fix(timing): Use i64 instead of c_long for Windows compatibility
The Rust FFI functions were using c_long for PTS/FTS timestamps, but:
- C code uses LLONG (int64_t, 64 bits on all platforms)
- Rust c_long is 32 bits on Windows, 64 bits on Linux

This caused timestamp truncation on Windows when PTS values exceeded
2^31 (~24 days at 90kHz), resulting in wrong subtitle timestamps.

For example, a file with Min PTS of 23:50:45 (7,726,090,500 ticks)
would have its PTS truncated, breaking the teletext delta calculation
that normalizes timestamps to start at 0.

Changes:
- ccxr_add_current_pts: pts parameter i64
- ccxr_set_current_pts: pts parameter i64
- ccxr_get_fts: return type i64
- ccxr_get_visible_end: return type i64
- ccxr_get_visible_start: return type i64
- ccxr_get_fts_max: return type i64
- ccxr_print_mstime_static: mstime parameter i64
- fts_at_gop_start: extern static i64

Fixes tests 18 and 19 on Windows CI which showed raw PTS timestamps
(23:50:46) instead of normalized timestamps (00:00:00).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 09:43:27 +01:00
Carlos Fernandez
da3dc52b45 fix(708): Support Korean EUC-KR encoding in CEA-708 decoder
Korean broadcasts use EUC-KR encoding (variable-width) in CEA-708
captions, where ASCII is 1 byte and Korean characters are 2 bytes.
The decoder was always writing 2 bytes per character (UTF-16BE style),
causing NULL bytes to be inserted before every ASCII character.

Changes:
- Add is_utf16_charset() to detect fixed-width 16-bit encodings
- Modify write_char() to accept use_utf16 flag:
  - true: Always 2 bytes (UTF-16BE for Japanese, issue #1451)
  - false: 1 byte for ASCII, 2 bytes for extended (EUC-KR for Korean)
- Detect charset type in write_row() before building output buffer

This fixes Korean subtitle extraction when using --service "1[EUC-KR]"
while maintaining compatibility with Japanese UTF-16BE (issue #1451).

Closes #1065

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 09:43:27 +01:00
Carlos Fernandez Sanz
0fdfb751ba fix(708): Handle null timing pointer in CEA-708 settings conversion 2025-12-21 09:41:25 +01:00
Carlos Fernandez Sanz
0b5f13e2c4 feat(wtv): Add DVB teletext stream detection in WTV files 2025-12-21 09:40:59 +01:00
Carlos Fernandez
60cec9e6de style: Fix clang-format indentation
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 09:38:50 +01:00
Carlos Fernandez Sanz
d758f3156a fix(windows): Prevent CEA-708 output file truncation on Windows 2025-12-21 09:36:32 +01:00
Carlos Fernandez Sanz
da802a0a39 fix(security): Add bounds checks for buffer overflow vulnerabilities 2025-12-21 09:35:47 +01:00
Carlos Fernandez
8f78a8bbb2 fix(708): Handle null timing pointer in CEA-708 settings conversion
When converting CEA-708 decoder settings from C to Rust via from_ctype(),
a null timing pointer would cause the entire conversion to fail and return
None. This triggered the unwrap_or(default()) fallback, resetting critical
settings like `enabled` and `services_enabled` to false/0.

This caused CEA-708 captions to not be extracted (exit code 10) even when
--service was specified, because the decoder's is_active flag was reset
to 0 during demuxer initialization.

The fix handles null timing pointer gracefully by using a default
CommonTimingCtx instead of propagating None, preserving the other
decoder settings.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 22:34:44 +01:00
Carlos Fernandez
e87807ec27 feat(wtv): Add DVB teletext stream detection in WTV files
This commit adds detection and basic handling of DVB teletext streams
in WTV (Windows TV) files. Previously, teletext streams were silently
ignored.

Changes:
- Add WTV_STREAM_TELETEXT GUID to wtv_constants.h
- Detect teletext streams by examining the format GUID at offset 0x4C
  in MSTVCAPTION stream metadata
- Initialize teletext decoder when teletext stream is found
- Add timing support for teletext streams
- Wrap teletext data in PES headers for the teletext decoder

Limitation: WTV files store teletext in Microsoft's VBI sample format,
which differs from standard DVB teletext data units. The decoder will
process the data but may not extract subtitles from all WTV files.
This is noted in a warning message shown when teletext is detected.
Even FFmpeg's libzvbi fails to decode this format in the test sample.

Addresses: #1391

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 21:58:50 +01:00
Carlos Fernandez
d097ec881c build(rust): Upgrade bindgen to 0.72.1 for Fedora packaging
Fixes #1608 - Update bindgen to enable Fedora Linux packaging.

- Upgrade bindgen from 0.64.0 to 0.72.1
- Fix deprecated CargoCallbacks API
- Replace (?i) regex flags with character classes for compatibility

The inline case-insensitivity flag (?i) causes bindgen 0.72.1 to
silently produce empty bindings. This fix uses [Dd][Tt][Vv][Cc][Cc]
character classes to match both lowercase (dtvcc_*) and uppercase
(DTVCC_*) type/function names.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 21:04:28 +01:00
Carlos Fernandez Sanz
87c898497a build(linux): Suppress find error when GPAC is not installed 2025-12-20 19:56:30 +01:00
Carlos Fernandez
49b698259d fix(windows): Prevent CEA-708 output file truncation on Windows
On Windows, when processing MP4/MOV files with CEA-708 captions, the
output file was being truncated to only the last subtitle. This occurred
because:

1. C code opened the file using open() and stored the fd in writer->fd
2. At end of processing, Rust's ccxr_flush_decoder was called
3. Rust checked writer->fhandle (a separate Windows-specific field)
4. Since fhandle was null (C only set fd), Rust called File::create()
5. File::create() truncates existing files, losing all previous content

The fix checks if fd is already valid before creating a new file. If fd
is valid, it converts it to a Windows handle using _get_osfhandle(),
avoiding the file truncation.

Fixes #1449

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 19:55:12 +01:00
Carlos Fernandez
5715d6d315 build(linux): Suppress find error when GPAC is not installed
Redirect stderr to /dev/null for the GPAC source file search to avoid
showing "No such file or directory" error when GPAC is not installed.
The build continues to work correctly in both cases.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 19:35:35 +01:00
Carlos Fernandez
9fddaab3b0 fix(security): Add bounds checks for buffer overflow vulnerabilities
Fixes two buffer overflow vulnerabilities reported in issues #1427 and #1428:

- #1428 (Global buffer overflow in slice_header): The slice_type value
  read from H.264 exp-golomb data was used to index slice_types[] array
  without bounds checking. Valid values are 0-9 per H.264 spec Table 7-6.
  Now validates slice_type < 10 before use.

- #1427 (Heap buffer overflow in parse_PMT): ES_info_length from PMT
  descriptor data was trusted without validation against buffer bounds.
  Malformed PMT with excessive ES_info_length could read past buffer end.
  Now validates ES_info_length and descriptor lengths against buffer.

Both issues were discovered using AddressSanitizer with crafted TS files.

Fixes #1427
Fixes #1428

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 19:34:22 +01:00
Carlos Fernandez Sanz
6fdfde0838 fix(mac): Fix HARDSUBX configure script and add documentation 2025-12-20 19:06:17 +01:00
Carlos Fernandez
8db7fc7a6d fix(mac): Correct leptonica library name in configure.ac
Homebrew installs leptonica as 'libleptonica.dylib', not 'liblept.dylib'.
Changed AC_CHECK_LIB from [lept] to [leptonica] to match the actual
library name on macOS.
2025-12-20 18:56:02 +01:00
Carlos Fernandez
d8504f80bd ci(mac): Set Homebrew paths for autoconf HARDSUBX build
The AC_CHECK_LIB checks in configure.ac need LDFLAGS and CPPFLAGS
to find libraries installed via Homebrew (in /opt/homebrew on Apple
Silicon or /usr/local on Intel Macs).
2025-12-20 18:48:43 +01:00
Carlos Fernandez
70404c29ca fix(mac): Fix HARDSUBX configure script and add documentation
Fixes #1173 - Error in ./configure enabling hardsubx on Mac
Fixes #1306 - Add HARDSUBX compilation docs for macOS

The configure.ac script failed on macOS with "binary operator expected"
because pkg-config output was unquoted. When pkg-config returns multiple
libraries (e.g., "-ltesseract -lcurl"), the unquoted expansion caused
`test ! -z` to receive multiple arguments instead of a single string.

Changes:
- Quote pkg-config output in TESSERACT_PRESENT conditional (mac & linux)
- Add macOS section to docs/HARDSUBX.txt with all build methods
- Add GitHub Actions jobs to test HARDSUBX builds on macOS:
  - build_shell_hardsubx: Tests ./build.command -hardsubx
  - build_autoconf_hardsubx: Tests ./configure --enable-hardsubx

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 18:41:37 +01:00
Carlos Fernandez Sanz
feb2a61c1d fix(ts): Skip broken PES packets instead of terminating file processing 2025-12-20 18:22:22 +01:00
Carlos Fernandez Sanz
6503502624 fix(mcc): Add MCC output support for raw caption files 2025-12-20 18:21:39 +01:00
Carlos Fernandez Sanz
bf271de52c build(mac): Add -system-libs flag for Homebrew compatibility 2025-12-20 18:20:59 +01:00
Carlos Fernandez Sanz
67e560d288 build(autoconf): Add GPAC library detection to configure 2025-12-20 18:19:57 +01:00
Carlos Fernandez Sanz
54bc97a3f8 fix(hevc): Add HEVC/H.265 caption extraction support with B-frame reordering 2025-12-20 18:18:27 +01:00
Carlos Fernandez Sanz
3d7c534824 ci: Add Docker build workflow to test all image variants 2025-12-20 18:13:49 +01:00
Carlos Fernandez
eda489265d fix(mac): Correct lib_hash include path for system-libs build
The include "../lib_hash/sha2.h" in params.c requires an include path
that makes "../lib_hash" resolve to "thirdparty/lib_hash".

Changed -I../src/lib_hash (which doesn't exist) to
-I../src/thirdparty/lib_hash. With this path, the compiler searches
for "../lib_hash/sha2.h" as:
  ../src/thirdparty/lib_hash/../lib_hash/sha2.h
  = ../src/thirdparty/lib_hash/sha2.h ✓

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 18:13:12 +01:00
Carlos Fernandez
0ac093e4b2 ci: Add Docker build workflow to test all image variants
Tests all three Dockerfile build types in parallel:
- minimal: Basic CCExtractor without OCR
- ocr: CCExtractor with Tesseract OCR support
- hardsubx: CCExtractor with burned-in subtitle extraction

Each job builds from local source and verifies the image works
by running --version. Uses GitHub Actions cache for faster rebuilds.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 18:06:27 +01:00
Carlos Fernandez
6838666b79 build(mac): Add -system-libs flag for Homebrew compatibility
Add a new `-system-libs` flag to mac/build.command that uses
system-installed libraries via pkg-config instead of bundled ones.
This enables Homebrew formula compatibility while preserving the
default standalone build behavior.

When `-system-libs` is passed:
- Uses pkg-config for: freetype2, gpac, libpng, libprotobuf-c,
  libutf8proc, zlib
- Does not compile bundled thirdparty sources
- Links against system libraries

Default behavior (no flag):
- Compiles bundled libraries as before
- No change to existing builds

Also adds a CI job `build_shell_system_libs` to test the new flag.

Refs #1580, #1534

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 17:58:46 +01:00
Carlos Fernandez
08d59ecb5f build(autoconf): Add GPAC library detection to configure
Previously, configure would succeed even without GPAC installed,
leading to a confusing compile-time error:
  "gpac/isomedia.h: No such file or directory"

Now configure checks for GPAC via pkg-config and fails early with
a helpful error message listing the package names for common distros:
  - gpac-devel (Fedora/RHEL)
  - libgpac-dev (Debian/Ubuntu)
  - gpac (Arch)

Fixes #1584

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 17:36:54 +01:00
Carlos Fernandez Sanz
2ce3e0c0de fix(docker): Rewrite Dockerfile to fix broken builds 2025-12-20 17:29:14 +01:00
Carlos Fernandez
3f45a4e136 fix(docker): Rewrite Dockerfile to fix broken builds
Fixes #1550 - Docker builds were broken after PR #1535 switched from
vendored GPAC to system GPAC.

Changes:
- Switch from Alpine to Debian Bookworm (Alpine's musl libc has issues
  with Rust bindgen's libclang dynamic loading)
- Support three build variants via BUILD_TYPE argument:
  - minimal: No OCR support
  - ocr (default): Tesseract OCR for bitmap subtitles
  - hardsubx: OCR + FFmpeg for burned-in subtitle extraction
- Support dual source modes via USE_LOCAL_SOURCE argument:
  - 0 (default): Clone from GitHub (standalone Dockerfile)
  - 1: Use local source (faster for developers)
- Add .dockerignore to exclude build artifacts (~2.7GB -> ~900KB context)
- Update README.md with comprehensive build instructions

Tested all three variants successfully:
- minimal: ~130MB image
- ocr: ~215MB image
- hardsubx: ~610MB image

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 17:27:42 +01:00
Carlos Fernandez
d0d46fc176 fix(mcc): Add MCC output support for raw caption files
Previously, when using -out=mcc with raw input files (-in=raw),
CCExtractor would print "Output format not supported" and produce
no output. This was because the raw file processing path decoded
CEA-608 data to text, but MCC format requires raw cc_data bytes.

The fix adds a new code path that bypasses the 608 decoder when
MCC output is requested:

- Added process_raw_for_mcc() helper function that:
  - Converts 2-byte raw pairs to 3-byte cc_data format
  - Wraps each CC pair in CDP format via mcc_encode_cc_data()
  - Maintains proper timing at 29.97fps

- Modified raw_loop() to detect MCC output and use the new path

Test results with McPoodle raw files:
- Before: "Output format not supported" (exit code 10)
- After: Valid MCC file with proper timing and CDP-wrapped data

Fixes #1542

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 11:53:50 +01:00
Carlos Fernandez
3e9ed3043b fix(ts): Skip broken PES packets instead of terminating file processing
Fixes #1455

When read_video_pes_header() encounters a malformed or truncated PES
packet (returns -1), copy_capbuf_demux_data() previously returned
CCX_EOF which terminated the entire file processing. This was overly
aggressive - a single broken PES packet should be skipped, not
terminate the entire file.

UK Freeview DVB recordings from September 2022 onwards contain some
malformed PES packets in the DVB subtitle stream that triggered this
condition, causing ccextractor to stop at 0% with "Processing ended
prematurely" error even though VLC could display the subtitles.

The fix changes the error handling to skip the broken packet and
continue processing:
- Before: return CCX_EOF (terminates file)
- After: return CCX_OK (skips packet, continues)

Test results with UK Freeview sample:
- Before: 0% processed, 0 subtitles extracted
- After: 100% processed, 10 subtitles extracted correctly

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 11:08:18 +01:00
Carlos Fernandez
1bdd9abd35 fix(clippy): Suppress dead_code warnings for unused HEVC NAL constants
The HEVC NAL type constants are defined for completeness and reference,
but not all are currently used in the codebase.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 10:50:47 +01:00
Carlos Fernandez
9e970fd788 style: Run cargo fmt on avc/core.rs
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 10:35:18 +01:00
Carlos Fernandez
87bc1d9613 style: Fix clang-format issue in ts_functions.c
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 10:34:50 +01:00
Carlos Fernandez
440cd5527f fix(hevc): Fix garbled captions by implementing B-frame reordering
HEVC uses B-frames extensively, causing CC data to arrive in decode
order instead of presentation order. This was causing character pairs
to be scrambled (e.g., "MEDIOCRE" became "MIOEDCRE").

Changes:
- Implement PTS-based sequence numbering for HEVC CC data (similar to H.264)
- Change flush logic to only trigger on IDR frames (not every VCL NAL)
- Add HEVC fallback detection for streams without PAT/PMT

Fixes #1639 (ATSC 3.0 HEVC caption extraction)
Tested with issue_1639_sample.ts and caption_test_1690.ts

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 10:34:50 +01:00
Carlos Fernandez
0fbbc06bcf fix(hevc): Add HEVC/H.265 caption extraction support
Fixes #1690 - Captions fail to extract on HEVC video stream

HEVC video streams with embedded EIA-608/708 captions weren't being
extracted, even though VLC/MPV could display them.

Root causes fixed:
1. HEVC stream type (0x24) wasn't recognized for CC extraction
2. HEVC NAL parsing used H.264 format (1-byte) instead of HEVC (2-byte)
3. HEVC SEI types (39/40) weren't handled (only H.264 SEI type 6)
4. CC data accumulation across SEIs caused u8 overflow/garbled output

Changes:
- C code: Add HEVC stream detection, CCX_HEVC buffer type, is_hevc flag
- Rust code: HEVC NAL header parsing (2-byte, type=(byte[0]>>1)&0x3F),
  HEVC SEI handling (PREFIX_SEI=39, SUFFIX_SEI=40), immediate CC flush

Thanks to @trufio465-bot for the initial research in PR #1735.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 10:34:50 +01:00
Carlos Fernandez Sanz
5f0c6728bf fix(avc): Handle streams that don't start with NAL start codes 2025-12-20 01:33:37 -08:00
Carlos Fernandez Sanz
b9aabcd60d fix(raw): Fix premature EOF and timing overflow in raw_loop 2025-12-20 01:32:43 -08:00
Carlos Fernandez Sanz
d0243237db fix(args): Add backward compatibility for single-dash long options 2025-12-20 01:32:08 -08:00
Carlos Fernandez Sanz
a86a4ca7ce feat: Add --list-tracks option to list media file tracks 2025-12-20 01:31:38 -08:00
Carlos Fernandez
77624ec678 style: Run cargo fmt on Rust code
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 10:27:22 +01:00
Carlos Fernandez
73db3a2c39 fix(avc): Handle streams that don't start with NAL start codes (#1626)
The AVC parser would fail with "Leading bytes are non-zero" error when
processing HLS/Twitch stream segments that start mid-stream without
proper NAL unit headers at the beginning.

Root cause: When process_avc encountered non-zero leading bytes, it
returned an error with 0 bytes processed. The C code would not remove
any bytes from the buffer, causing subsequent data to accumulate with
the corrupt beginning, leading to infinite errors.

Fix:
- Add find_nal_start_code() to search for valid NAL start codes
- If buffer doesn't start with 0x00 0x00, search for first NAL start
- Skip garbage data before first valid NAL unit
- Return full buffer length when no NAL found (clears the buffer)
- Change forbidden_zero_bit error from fatal to skip-and-continue

Tested with 6 Twitch HLS sample files - all now process correctly.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 09:08:14 +01:00
Carlos Fernandez
dd3dab7d52 fix(args): Add backward compatibility for single-dash long options (#1576)
Old versions of ccextractor accepted single-dash long options like
-quiet, -stdout, -autoprogram. The new Rust-based argument parser
(clap) only accepts double-dash options (--quiet, --stdout, etc.).

When users ran scripts with -quiet, clap parsed it as individual
short options -q -u -i -e -t and failed with exit code 7. Users
with stderr redirected never saw the error, causing silent failures
with zero-length output files.

This adds a normalize_legacy_option() function that pre-processes
arguments before passing them to clap:
- Single-dash long options (e.g., -quiet) convert to --quiet
- Double-dash options remain unchanged
- Short options like -o remain unchanged
- Numeric options like -1, -12 remain unchanged

Includes 6 unit tests for the new function.

Fixes #1576

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 08:54:48 +01:00
Carlos Fernandez
ebfa31c333 fix(raw): Fix premature EOF and timing overflow in raw_loop (#1565)
Fix raw caption file processing that would stop at exactly 9:43:00 (2MB).

Root causes and fixes:
1. Premature EOF: After processing first chunk (BUFSIZE ~2MB), data->len
   was never reset. On next iteration, general_get_more_data() calculated
   want = BUFSIZE - len = 0 and returned EOF immediately.
   Fix: Reset data->len = 0 after each chunk and change loop condition.

2. 32-bit integer overflow: The calculation cb_field1 * 1001 / 30 * 90
   overflowed for large cb_field1 values (>1M). For example,
   34,989,487 * 90 = 3,149,053,830 exceeds 32-bit signed max.
   Fix: Cast cb_field1 to LLONG before multiplication.

3. Timing initialization: Raw mode needs min_pts=0, sync_pts=0, and
   pts_set=MinPtsSet for correct fts_now calculation.

Tested with sample files from issue #1565:
- DTV3.raw: Now processes to 17:59:56 (was stopping at 9:43)
- DTV4.raw: Now processes to 14:00:00 (was stopping at 9:43)
- DTV5.raw: Now processes to 13:19:59 (was stopping at 9:43)

Closes #1565

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 08:37:52 +01:00
Carlos Fernandez
d52d26baf8 style: Format Rust code with cargo fmt
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 07:47:17 +01:00
Carlos Fernandez
3a852b7915 feat: Add --list-tracks option to list media file tracks
Add a new --list-tracks (-L) option that lists all tracks found in
media files without processing them. This is useful for exploring
media files before caption extraction.

Supports:
- Matroska (MKV/WebM) files
- MP4/MOV files
- MPEG Transport Stream files

The feature is implemented entirely in Rust with native parsers for
each format, avoiding dependency on external libraries.

Closes #1669

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 07:42:38 +01:00
Carlos Fernandez Sanz
c3f637a10e fix(rust): Handle NULL file pointer in ccxr_demuxer_open for UDP/TCP input 2025-12-19 07:44:16 -08:00
Carlos Fernandez Sanz
f3768625c6 fix(wtv): Set sync_pts alongside min_pts to prevent PTS jump detection 2025-12-19 07:43:39 -08:00
Carlos Fernandez
c733902473 fix(wtv): Set sync_pts alongside min_pts to prevent PTS jump detection
The previous WTV timing fix (commit 300f8ca6) set min_pts and pts_set=2
(MinPtsSet) but didn't set sync_pts. This caused the Rust timing code
to detect a massive PTS jump when processing WTV files with large
initial timestamps (e.g., files recorded at 18:38:23).

The PTS jump detection computes (current_pts - sync_pts), and with
sync_pts=0 but current_pts=6039323550 (18:38:23 in PTS units), the
difference exceeded MAX_DIF and triggered the jump handling, resulting
in empty output.

This fix sets sync_pts to the same value as min_pts when first
initializing timing, preventing the false PTS jump detection.

Test results:
- Before: WTV files with large initial PTS produced empty output
- After: Timestamps match expected ground truth exactly
  (e.g., 00:00:00,601 --> 00:00:02,801 for first caption)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 16:40:58 +01:00
Carlos Fernandez
6c44100f97 fix(rust): Handle NULL file pointer in ccxr_demuxer_open for UDP/TCP input
When using --udp or --tcp options, ccxr_demuxer_open() was called with
a NULL file pointer, causing a crash in CStr::from_ptr().

The fix checks if the file pointer is NULL before dereferencing it,
and uses an empty string for network input modes.

Fixes #1846

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 15:30:41 +01:00
Carlos Fernandez Sanz
a0593c60e3 fix: RCWT/WTV timing fixes, Latin-1 music note encoding 2025-12-19 06:25:05 -08:00
Carlos Fernandez
300f8ca65a fix(wtv,encoding): Fix WTV timing and Latin-1 music note encoding
WTV timing fix:
- Set min_pts on first valid timestamp to enable fts_now calculation
- Set pts_set = 2 (MinPtsSet) instead of 1 (Received)
- This fixes WTV files where all timestamps were clustered around 1 second
  instead of being spread across the actual video duration

Latin-1 encoding fix:
- Change music note substitution from pilcrow (0xB6) to '#' (0x23)
- Pilcrow caused grep to treat output files as binary
- '#' is a more recognizable substitute for the musical note character

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 14:00:35 +01:00
Carlos Fernandez
8988152fa5 fix(rcwt): Fix timestamp calculation for RCWT/BIN format files
The rcwt_loop() function set min_pts = 0 for RCWT files but did not
set pts_set = 2 (MinPtsSet). This caused the Rust timing code to skip
the fts_now calculation (which checks pts_set == MinPtsSet), resulting
in all captions having timestamps compressed near 0 instead of their
correct times spread across the file duration.

The fix adds pts_set = 2 after setting min_pts, which tells the timing
system that min_pts is valid and fts_now can be calculated properly.

Fixes Test 217 timing issue where:
- Before: 00:00:00,001 --> 00:00:00,091 (wrong)
- After:  00:00:02,402 --> 00:00:04,536 (correct)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 11:50:57 +01:00
Carlos Fernandez
78642bcf02 ci: Retrigger Sample Platform CI 2025-12-19 09:24:12 +01:00
Carlos Fernandez
0c0e44472d ci: Trigger verification run after merging PRs #1847 and #1848
This PR triggers a fresh CI run to verify the combined effect of:
- PR #1847: Hardsubx crash fix, memory leak fixes, rcwt exit code fix
- PR #1848: XDS empty content entries fix

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 07:08:59 +01:00
Carlos Fernandez Sanz
2060db99c8 fix(hardsubx): Fix heap corruption from Rust/C allocator mismatch 2025-12-18 22:02:30 -08:00
Carlos Fernandez Sanz
a299d06d97 fix(xds): Don't output empty XDS content entries 2025-12-18 22:02:04 -08:00
Carlos Fernandez
50b51e4234 fix(xds): Don't output empty XDS content entries
When outputting US TV Parental Guidelines ContentAdvisory XDS data,
the code was always calling xdsprint() for both the age rating and
the content flags (violence, language, etc). However, if there are
no content flags (e.g., for TV-G which has no additional advisories),
the content string is empty.

This caused duplicate XDS entries in the output - one with the age
rating and one with an empty string. The fix only outputs the content
string if it is not empty.

Fixes regression test 113 output mismatch.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 05:48:51 +01:00
Carlos Fernandez
0b74c9226a fix(rcwt): Fix incorrect exit code when captions are found in BIN format
The rcwt_loop function was returning exit code 10 (no captions) even
when CEA-608 captions were successfully extracted from RCWT/BIN format
files. This happened because CEA-608 decoding writes directly to the
encoder via printdata() without setting dec_sub->got_output.

Add a check after the main loop (similar to general_loop) that also
considers enc_ctx->srt_counter, enc_ctx->cea_708_counter, and
dec_ctx->saw_caption_block to properly detect when captions were found.

Fixes regression test 217 which was failing with exit code 10.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 05:40:52 +01:00
Carlos Fernandez
80957d645b fix(hardsubx): Fix heap corruption from Rust/C allocator mismatch
The hardsubx code was using C's free() on strings allocated by Rust's
CString::into_raw(). Since Rust and C use different memory allocators,
this caused heap corruption that manifested as garbage OCR output after
processing ~27 subtitle frames.

Changes:
- Export free_rust_c_string() from Rust as extern "C" function
- Declare free_rust_c_string() in hardsubx.h for C code
- Replace free(subtitle_text) with free_rust_c_string(subtitle_text)
  in hardsubx_decoder.c for Rust-allocated strings
- Fix memory leaks in process_hardsubx_linear_frames_and_normal_subs()
  where subtitle_text_hard and prev_subtitle_text_hard were not freed
- Remove dummy CI trigger file (no longer needed)

Testing:
- AddressSanitizer: No memory errors detected
- Valgrind: 0 bytes definitely lost, 0 bytes indirectly lost
- Manual testing: OCR output now correct for entire video duration

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 05:29:04 +01:00
Carlos Fernandez
80a117e643 fix(hardsubx): Fix memory leaks in hardsubx processing
- Free basefilename in _dinit_hardsubx (allocated by get_basename)
- Free subtitle_text after each frame processing iteration
- Free prev_subtitle_text when replaced and at end of function
- Free sws_ctx with sws_freeContext (was never freed)

Reduces memory leaks from 63,926 bytes to 0 bytes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 04:46:19 +01:00
Carlos Fernandez
63999369b7 fix(hardsubx): Fix multiple memory bugs causing crashes
1. Remove invalid free(tessdata_path) - probe_tessdata_location() returns
   a pointer to static strings or getenv() result, not heap memory.

2. Fix alloc-dealloc mismatch in OCR text handling:
   - TessBaseAPIGetUTF8Text() allocates with C++ operator new[]
   - The code was freeing with C free() causing allocator mismatch
   - Now properly copy string and use TessDeleteText() before returning
   - Unified all OCR text return paths to use Rust-allocated strings

3. Previous fix: freep(&lctx->dec_sub) instead of freep(lctx->dec_sub)

These fixes resolve Test 241 (Hardsubx) crash on Sample Platform.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 04:40:31 +01:00
Carlos Fernandez
0e815c6e2d fix(hardsubx): Fix crash in _dinit_hardsubx due to incorrect freep usage
The freep() function expects a pointer-to-pointer (void**) so it can
dereference, free, and NULL-out the pointer. The code was passing
lctx->dec_sub directly instead of &lctx->dec_sub.

This caused freep to interpret the first 8 bytes of the cc_subtitle
struct as a pointer and attempt to free() it, resulting in a crash
(SIGABRT/exit code 134) in the memory allocator.

Fixes Test 241 (Hardsubx) crash on Sample Platform.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 04:33:11 +01:00
Carlos Fernandez
0ef7227d7e ci: Add dummy C file to trigger Sample Platform CI
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 04:04:58 +01:00
Carlos Fernandez
2fa023b9fe ci: Add triage tracking file for December 2025 CI analysis
This PR triggers a fresh CI run to analyze all failing regression tests
and determine whether each needs a ground truth update or a code fix.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 04:01:18 +01:00
Carlos Fernandez Sanz
2f0770d45f docs: Update CHANGES.TXT with recent bug fixes 2025-12-18 04:20:41 -08:00
Carlos Fernandez
ee36ac1d4d docs: Update CHANGES.TXT with recent bug fixes
Add changelog entries for recent merged PRs:
- Fix: Garbled captions from HDHomeRun and I/P-only H.264 streams (#1109)
- Fix: Enable stdout output for CEA-708 captions on Windows (#1693)
- Fix: McPoodle DVD raw format read/write (#1524)
- Fix: Variable shadowing in general_loop
- Fix: Double-free crash in teletext cleanup
- Fix: Uninitialized memory and memory leaks (Valgrind)
- Fix: Dangling pointers in Rust FFI
- New: Teletext subtitle pages in -out=report (#1034)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 13:19:13 +01:00
Carlos Fernandez Sanz
e160a533b0 fix: McPoodle DVD raw format read/write (Issue #1524) 2025-12-18 04:16:47 -08:00
Carlos Fernandez Sanz
083c12698f fix: Enable stdout output for CEA-708 captions on Windows 2025-12-18 04:11:42 -08:00
Carlos Fernandez
88fbe9190a style: Fix formatting and clippy warnings
- Fix comment spacing (single space before //)
- Mark is_two_byte_loop_marker as #[cfg(test)] since it's only used in tests

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 13:08:21 +01:00
Carlos Fernandez
ac49bb5978 fix: McPoodle DVD raw format read/write (Issue #1524)
Reading:
- Migrate DVD raw parser from C to Rust (src/rust/src/demuxer/dvdraw.rs)
- Add FFI exports: ccxr_process_dvdraw(), ccxr_is_dvdraw_header()
- Handle both McPoodle's single-byte and legacy 2-byte loop markers
- Add 15 unit tests covering all edge cases

Writing:
- Fix LC3/LC4 constants from 2-byte to 1-byte to match McPoodle's format
- Output files now have identical size to McPoodle's original

Fixes #1524

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 13:03:29 +01:00
Carlos Fernandez Sanz
138ccd01c2 fix: Fix garbled captions from HDHomeRun and I/P-only H.264 streams 2025-12-18 04:01:44 -08:00
Carlos Fernandez
9fe2dab6d4 style: Remove unused mut from current_index variable
Fix clippy warning: variable does not need to be mutable.
The current_index variable is only assigned once during initialization
and never modified afterward.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 12:57:06 +01:00
Carlos Fernandez Sanz
a28561ad0d Merge pull request #1841 from CCExtractor/fix/general-loop-ret-shadowing
fix: Fix variable shadowing and teletext context refresh issues
2025-12-18 03:26:37 -08:00
Carlos Fernandez
c8f6b565fd fix: Fix garbled captions from HDHomeRun and I/P-only H.264 streams
For I/P-only streams (like HDHomeRun recordings), the caption buffer was
being flushed on every reference frame (I and P). Since ALL frames in these
streams are reference frames, this defeated the caption reordering mechanism,
causing garbled output.

The fix:
- Only flush the buffer and reset reference PTS on IDR frames (NAL type 5),
  not on P-frames
- Initialize currefpts on first frame to avoid huge indices at stream start
- Properly flush buffer and reset reference when large PTS gaps are detected

This allows P-frames to accumulate in the buffer and be sorted by their
PTS-based indices before output.

Fixes #1109

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 10:35:20 +01:00
Carlos Fernandez
442ce1015d fix: Fix variable shadowing and teletext context refresh issues
This commit fixes two issues uncovered during Sample Platform testing:

1. Variable shadowing in general_loop() (general_loop.c):
   - The inner `int ret = process_non_multiprogram_general_loop(...)`
     was shadowing the outer `ret` variable
   - This caused the return value to always be 0, making ccextractor
     report "No captions found" even when captions were extracted
   - Also added `ret = 1` when captions are detected via counters,
     needed for CEA-708 which writes directly via Rust

2. Missing private_data refresh in update_decoder_list_cinfo (lib_ccx.c):
   - After PAT changes, dinit_cap() frees the teletext context and
     NULLs dec_ctx->private_data
   - But update_decoder_list_cinfo() returned existing decoder without
     refreshing private_data from the new cap_info
   - This caused all subsequent teletext processing to be skipped
   - Fixed by updating dec_ctx->private_data when returning existing decoder

These fixes resolve Sample Platform test failures in CEA-708 and Teletext
categories where tests returned exit code 10 (no captions) unexpectedly.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 10:10:25 +01:00
Carlos Fernandez
e2dfdaa6a8 Merge branch 'master' into fix/issue-1693-stdout-crash
Resolved conflict in src/rust/src/lib.rs:
- Kept stderr target change from this branch (for --stdout option)
- Merged safety documentation from master
2025-12-18 09:18:50 +01:00
Carlos Fernandez Sanz
a0809caa94 fix(memory): Fix uninitialized memory and memory leaks found by Valgrind 2025-12-18 00:16:01 -08:00
Carlos Fernandez
859741a22c fix(rust): Remove unused import free_rust_c_string_array
This fixes the clippy error: "unused import: crate::utils::free_rust_c_string_array"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 07:41:29 +01:00
Carlos Fernandez
4429067965 fix(rust): Fix Drop compatibility and formatting issues
- demux.rs: Update dummy_demuxer() to explicitly initialize all fields
  instead of using ..Default::default(), which is not allowed when the
  struct implements Drop
- common.rs, demuxer.rs: Apply cargo fmt formatting fixes

This fixes the Rust test compilation error:
"cannot move out of type CcxDemuxer which implements the Drop trait"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 07:37:39 +01:00
Carlos Fernandez
d72646ac85 fix(memory): Fix XDS memory leak in rcwt_loop path
Add proper cleanup of xds_ctx in rcwt_loop() for --in=bin and --in=raw
formats. The general_loop() path already frees xds_ctx, but rcwt_loop()
was missing this cleanup, causing an 880-byte leak.

This fixes Valgrind tests 217 (--in=bin) and 218 (--in=raw).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 07:31:50 +01:00
Carlos Fernandez
4a304346c9 fix(memory): Fix XDS memory leaks in encoder and decoder cleanup
- XDS encoder leak: Free xds_str when skipping subtitles with invalid timestamps
- XDS decoder cleanup: Add proper cleanup for leftover XDS strings in dinit_cc_decode()
- Remove incorrect free(p) after write_xds_string() - the pointer is stored
  for later use by the encoder and must not be freed immediately
- Remove xds_ctx free from dinit_cc_decode() to avoid double-free

These fixes address the 100-byte XDS leak found in Valgrind test 114.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 16:54:38 +01:00
Carlos Fernandez
627e0855ce fix(memory): Fix 608 decoder memory leak in dec_sub.data
The embedded dec_sub struct in lib_cc_decode had its data field
allocated by write_cc_buffer() but never freed during cleanup.

Added cleanup in dinit_cc_decode() to:
- Free DVB bitmap data (data0/data1) if present
- Free the dec_sub.data field itself

This fixes ~1.7MB to ~2.6MB leaks seen in tests 89, 93, and 96.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 13:58:15 +01:00
Carlos Fernandez
7b1a169b8f fix(memory): Fix use-after-free in Teletext and uninitialized variables
This commit fixes several Valgrind-detected memory issues:

1. Use-after-free in Teletext during PAT changes:
   - When parse_PAT() calls dinit_cap() to reinitialize stream info,
     it freed the Teletext context but dec_ctx->private_data still
     pointed to the freed memory
   - Fixed by NULLing out dec_ctx->private_data in dinit_cap() when
     freeing shared codec private data
   - Also added NULL check in process_data() before calling teletext
     functions to gracefully handle freed contexts

2. Uninitialized variables in general_loop():
   - stream_mode, get_more_data, ret, and program_iter were declared
     without initialization
   - While logically set before use, Valgrind tracked them as
     potentially uninitialized through complex control flow
   - Fixed by initializing all variables at declaration

These fixes eliminate millions of Valgrind errors in teletext tests
(tests 78, 80) and uninitialized value warnings (tests 67, 84, 86).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 13:44:13 +01:00
Carlos Fernandez
3d5d8e2a0a fix(memory): Fix major memory leaks in Rust FFI demuxer and decoder
This commit fixes several significant memory leaks found by Valgrind testing:

1. Dtvcc::new encoder leak (decoder/mod.rs):
   - Previously always allocated a new encoder_ctx even when ctx.encoder
     was not null, then threw away the allocation
   - Fix: Only allocate when ctx.encoder is null
   - Impact: Eliminated 55MB-331MB leaks per video processing run

2. ccxr_demuxer_isopen optimization (demuxer.rs):
   - Previously copied entire demuxer structure just to check infd
   - Fix: Directly check (*ctx).infd != -1
   - Impact: Eliminated repeated allocations during file processing

3. ccxr_demuxer_close optimization (demuxer.rs):
   - Previously did full copy roundtrip (C->Rust->C) to close a file
   - Fix: Work directly on C struct, call close() and activity callback
   - Impact: Eliminated copy-related allocations and leaks

4. CcxDemuxer Drop implementation (common_types.rs):
   - pid_buffers and pids_programs contain raw pointers from Box::into_raw
   - These were never freed when CcxDemuxer was dropped
   - Fix: Implement Drop to free all non-null Box pointers
   - Impact: Eliminates remaining FFI-related leaks

Test results show dramatic improvement:
- Test 24: 55MB leak -> 0 bytes (PERFECT)
- Test 26: 9.75MB leak -> 0 bytes (PERFECT)
- Test 27: 237MB leak -> 0 bytes (PERFECT)
- Test 28: 331MB leak -> 0 bytes (PERFECT)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 12:48:51 +01:00
Carlos Fernandez
683468e233 fix(memory): Fix use-after-free and memory leaks in Rust FFI
This commit fixes critical memory issues found during comprehensive
Valgrind testing:

1. **Use-after-free in inputfile array** (common.rs):
   - Problem: `copy_from_rust` was called multiple times (parse_parameters,
     demuxer_open, demuxer_close), and each call freed and reallocated the
     inputfile array. C code holding references to the old array would then
     access freed memory.
   - Fix: Only set inputfile on the first call (when inputfile is null).
     Subsequent calls skip modifying inputfile since it shouldn't change
     during processing.

2. **Memory leak in enc_cfg strings** (common.rs):
   - Problem: Each call to `copy_from_rust` allocated new encoder config
     strings without freeing the old ones, causing 1,536 bytes leaked per
     demuxer open/close cycle.
   - Fix: Only set enc_cfg on the first call (when output_filename is null).
     Encoder config is static and doesn't need to be re-synced.

3. **Uninitialized memory in telxcc_init** (telxcc.c):
   - Problem: `malloc` was used to allocate TeletextCtx but not all fields
     were explicitly initialized, causing Valgrind to report 400+ errors
     about conditional jumps on uninitialized values.
   - Fix: Changed to `calloc` to zero-initialize all fields.

**Valgrind results improvement (Test 3):**
- Errors: 458 → 21 (95% reduction)
- Definitely lost: 2,304 → 768 bytes (67% reduction)
- Use-after-free bugs: Eliminated
- Double-free bugs: Eliminated

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 11:04:19 +01:00
Carlos Fernandez
89849d321f fix(memory): Fix uninitialized memory and memory leaks found by Valgrind
Addresses memory issues identified during Phase 5 (Runtime Analysis) of
the bug analysis plan using Valgrind memory checking.

## Changes

### C Code (Uninitialized Memory)
- ccx_demuxer.c: Use calloc() instead of malloc() in init_demuxer() to
  ensure all struct fields are zero-initialized before use
- lib_ccx.c: Use calloc() instead of malloc() in init_decoder_setting()
  for consistent initialization

### Rust FFI Code (Memory Leaks)
- utils.rs: Add helper functions for proper FFI string memory management:
  - free_rust_c_string(): Free a Rust-allocated CString
  - replace_rust_c_string(): Free old string before allocating new one
  - free_rust_c_string_array(): Free an array of Rust-allocated CStrings
- common.rs: Update copy_from_rust() to properly manage string memory:
  - Free old strings before allocating new ones for all string fields
  - Add free_encoder_cfg_strings() to clean up encoder config strings
  - Free old inputfile array before allocating new one

## Valgrind Results Comparison

| Metric              | Before    | After     | Improvement     |
|---------------------|-----------|-----------|-----------------|
| Definitely lost     | 2,371 B   | 1,536 B   | 35% reduction   |
| Indirectly lost     | 212 B     | 0 B       | 100% fixed      |
| Uninitialized errors| 131,095   | 0         | 100% fixed      |

The remaining 1,536 bytes are from services_charsets array in
EncoderConfig (low priority, rare use case).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 09:21:51 +01:00
Carlos Fernandez Sanz
588ad5260a fix(rust-ffi): Prevent dangling pointers in copy_from_rust 2025-12-17 00:07:27 -08:00
Carlos Fernandez Sanz
ebd8148cad Merge pull request #1838 from CCExtractor/fix/teletext-double-free-crash
fix(teletext): Prevent double-free crash in teletext cleanup
2025-12-17 00:06:32 -08:00
Carlos Fernandez
ba33f7572d fix(rust-ffi): Prevent dangling pointers in copy_from_rust
The `to_ctype()` implementations for `DecoderDtvccSettings` and
`Decoder608Settings` were creating temporaries on the stack and
returning pointers to them. These pointers became dangling after
the function returned, causing memory corruption when
`copy_from_rust()` was called.

This fix:
- Preserves the original C-managed `report` and `timing` pointers
  in `copy_from_rust()` instead of overwriting them with dangling
  pointers to temporaries
- Adds explicit `settings_dtvcc.timing = NULL` initialization in
  `init_options()` for completeness

Before this fix, valgrind reported:
- "Invalid write of size 4" in `dtvcc_init` (4016 bytes below stack
   pointer)
- "Invalid read" errors in `copy_to_rust` / `DecoderDtvccSettings::
   from_ctype`

After this fix, these critical memory corruption errors are resolved.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 09:05:48 +01:00
Carlos Fernandez
9cf96b1899 fix(teletext): Prevent double-free crash in teletext cleanup
This fixes a double-free bug that caused CCExtractor to crash with
exit code 134 (SIGABRT) when processing teletext streams.

## Root Cause

The teletext context (TeletextCtx) pointer was shared between two
structures:
- `dec_ctx->private_data` (decoder context)
- `cinfo->codec_private_data` (capture info in cinfo_tree)

When `general_loop()` ended, it called `telxcc_close()` which freed
the TeletextCtx and NULLed `dec_ctx->private_data`. However, the
shared pointer in `cinfo->codec_private_data` was NOT NULLed.

Later, during cleanup in `dinit_cap()`, the code would find the
non-NULL `cinfo->codec_private_data` and attempt to free it again,
causing a double-free crash.

## The Fix

After `telxcc_close()` frees the teletext context in `general_loop()`,
iterate through all cinfo entries and NULL out any that shared the
same pointer. This prevents `dinit_cap()` from attempting to free
already-freed memory.

## Regression

This bug was exposed by commit 7e1a01447 which added cleanup code
to `dinit_cap()` to free `codec_private_data`. The `telxcc_close()`
call in `general_loop()` has existed since 2015, but the double-free
only became possible after the new cleanup code was added.

## Testing

Validated fix against all 27 teletext-related CI tests that were
failing with exit code 134:

Teletext section (21 tests): 63-83 - all PASS
DVB section: 18, 19 - all PASS
Other teletext tests: 224, 234, 235, 236 - all PASS

Verified with valgrind that no "Invalid free" or "double free"
errors occur after the fix.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 08:46:37 +01:00
Carlos Fernandez Sanz
0b3ad40377 Merge pull request #1837 from x15sr71/fix/atsc-vct-xmltv-mapping
[FIX]: Add ATSC VCT virtual channel numbers and call signs to XMLTV output
2025-12-16 22:29:04 -08:00
Chandragupt Singh
ac72625030 Fix ATSC XMLTV output to include VCT virtual channels and call signs 2025-12-17 10:49:41 +05:30
Carlos Fernandez Sanz
f6cb862dcb bump MSRV from 1.54.0 to 1.87.0 (rust) 2025-12-15 23:25:22 -08:00
Carlos Fernandez Sanz
53c0f56b6f Merge pull request #1833 from CCExtractor/dependabot/github_actions/actions/upload-artifact-6
chore(deps): bump actions/upload-artifact from 5 to 6
2025-12-15 23:07:50 -08:00
Carlos Fernandez Sanz
62272e7be6 [FIX] Correct typos in warning message and code comment
[FIX] Correct typos in warning message and code comment
2025-12-15 23:06:59 -08:00
Carlos Fernandez Sanz
a7e05c265c fix(ocr): Improve DVB subtitle OCR quality (fixes #243)
fix(ocr): Improve DVB subtitle OCR quality (fixes #243)
2025-12-15 23:05:58 -08:00
Carlos Fernandez Sanz
9ce13cf45f FIX]: Restore XMLTV generation for ATSC EIT/VCT streams and correct EIT bounds checks
[FIX]: Restore XMLTV generation for ATSC EIT/VCT streams and correct EIT bounds checks
2025-12-15 13:27:41 -08:00
Chandragupt Singh
e0ac99a241 fix(atsc): restore XMLTV generation and ATSC EPG parsing 2025-12-16 01:46:28 +05:30
GAURAV KARMAKAR
6ebf98ea4a Fix typos in encoder warning and comment 2025-12-16 00:59:45 +05:30
dependabot[bot]
9372e15024 chore(deps): bump actions/upload-artifact from 5 to 6
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5 to 6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-15 18:02:19 +00:00
Carlos
7e1a01447a fix(ocr): Improve DVB subtitle OCR quality (fixes #243)
This commit addresses Issue #243 where DVB subtitles from Spanish
broadcasts were producing corrupt/garbled OCR output like
"alajentiegaranual dep jemios" instead of "a la entrega anual de premios".

Root cause analysis:
1. Image preprocessing was degrading quality - pixContrastNorm was
   causing issues for some DVB sources
2. Default quantization mode (ocr_quantmode=1) was too aggressive,
   reducing images to just 3 colors which lost important detail

Changes:
- Remove pixContrastNorm calls from ocr.c (both main OCR and color
  detection passes) - these were causing more harm than good
- Change default ocr_quantmode from 1 to 0 (no quantization) in both
  C code (ccx_common_option.c) and Rust code (options.rs)
- Add NULL checks in dvbsub_close_decoder() and telxcc_close() for
  safety
- Add proper cleanup of codec_private_data pointers in lib_ccx.c and
  ts_info.c to prevent double-free crashes

Testing performed:
- Test 21 (English DVB): Completes in ~1 second with good OCR quality
- Test 239 (DVB timing): All 8 subtitles have correct timing
- Spanish DVB (Issue #243): Now produces readable text like
  "¡Bienvenidos a la entrega anual de premios" instead of garbage

Users can still use --quant 1 to restore the old quantization behavior
if needed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 11:51:30 +01:00
Carlos Fernandez Sanz
b728ddadfa fix: Comprehensive bug fixes - Phases 2-4 (Memory, Buffer, Rust FFI)
Lots of sanitation work - always free stuff, validate buffer sizes, etc.
2025-12-15 02:50:06 -08:00
Carlos Fernandez Sanz
300541b873 Merge pull request #1809 from Rahul-2k4/master
Improve -out=report to show detected Teletext subtitle pages (Fixes #1034)
2025-12-14 23:36:41 -08:00
Carlos Fernandez Sanz
2f1c1bf227 Merge pull request #1721 from Ari1009/mcc_encoder
fix: MCC encoder 16-bit sequence
2025-12-14 23:27:08 -08:00
Carlos Fernandez Sanz
0bcb532428 Merge pull request #1829 from CCExtractor/fix/autoconf-hardsubx-tesseract
build(autoconf): add tesseract/leptonica linking for HARDSUBX
2025-12-14 23:18:12 -08:00
Carlos
d8698dc9cb build(autoconf): add tesseract/leptonica linking for HARDSUBX
This is the autoconf equivalent of the CMake fix in PR #1760.

When building with HARDSUBX enabled but OCR disabled, the autoconf
build system was missing explicit tesseract/leptonica linking in the
HARDSUBX block. While configure.ac sets OCR_IS_ENABLED when HARDSUBX
is enabled (so it would work via the OCR block), this change makes
the dependency explicit and consistent with the CMake fix.

Related: PR #1760, Issue #1719

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 08:12:16 +01:00
Carlos Fernandez Sanz
4cc9231fc8 Merge pull request #1760 from DhanushVarma-2/fix-tesseract-linking-1719
build: add tesseract library linking for hardsubx feature
2025-12-14 23:08:00 -08:00
Carlos
d202a66fd0 style(rust): Apply cargo fmt formatting
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 07:07:41 +01:00
Carlos
d8048bc95a fix(rust): Complete Phase 4 - FFI safety and documentation
Phase 4 of the bug analysis cycle addresses all Rust/FFI boundary issues:

Safety Documentation:
- Added # Safety docs to all 83 production FFI functions
- lib.rs: ccxr_init_logger, ccxr_close_handle
- decoder/encoding.rs: 4 G0/G1/G2/G3 conversion functions
- decoder/service_decoder.rs: ccxr_flush_decoder
- hardsubx/imgops.rs: rgb_to_hsv, rgb_to_lab
- hardsubx/utility.rs: convert_pts_to_ns/ms/s

Panic Prevention (FFI function bodies):
- hardsubx/decoder.rs: Replaced 8 .try_into().unwrap() calls with
  safe `as` casts to prevent potential panics across FFI boundary
- libccxr_exports/net.rs: Replaced expect() with safe error handling
- libccxr_exports/mod.rs: Removed panic!/expect(), use defaults
- libccxr_exports/time.rs: Replaced try_into().unwrap() with unwrap_or()

Clippy Fixes:
- Fixed 72 Clippy warnings across the codebase
- Replaced assert!(false) with unreachable!()
- Added #[allow] attributes for acceptable test code patterns

All 269 tests pass, Clippy reports 0 warnings.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 07:03:25 +01:00
Carlos
af3ab5acd4 fix(buffer): Replace unsafe string functions with safe alternatives
Phase 3: Buffer overrun fixes

Changes:
- Replace 17 sprintf calls with snprintf
- Replace 3 strcpy calls with memcpy (known length)
- Replace 9 strcat calls with safer alternatives (snprintf, memcpy, strncat)
- Fix telxcc.c buffer size for page number formatting
- Add bounds checking to eia608_to_str function

Files modified:
- ocr.c: 7 sprintf→snprintf, 2 strcat→snprintf
- ts_tables_epg.c: 4 sprintf→snprintf, 1 strcat→snprintf
- ccx_encoders_spupng.c: 4 sprintf→snprintf, 1 strcpy→memcpy, 2 strcat→strncat/memcpy
- ccx_encoders_splitbysentence.c: 2 sprintf→snprintf (commented debug code)
- utility.c: 2 strcpy→memcpy, 4 strcat→snprintf/memcpy
- telxcc.c: increased buffer size from 4 to 8 bytes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 06:33:17 +01:00
Carlos
90519e2296 fix(memory): Fix memory issues in final batch of files (Batch 2.7)
Files fixed:
- hardsubx.c: Add free() calls before return NULL at lines 247, 255;
  add null check for dec_sub malloc; free tessdata_path
- ccx_gxf.c: Fix unsafe realloc pattern for ctx->cdp
- wtv_functions.c: Add null checks for malloc calls at lines 143, 192,
  283, 384
- dvd_subtitle_decoder.c: Fix memset before null check; add null checks
  for rect->data0 and rect->data1; add null checks in init_dvdsub_decode
- ts_tables.c: Add null check for PID_buffers malloc; add null check for
  buffer malloc; fix unsafe realloc pattern
- myth.c: Fix unsafe realloc pattern for desp buffer
- ffmpeg_intgr.c: Fix memory leaks in init_ffmpeg error paths; add proper
  cleanup labels; properly allocate codec context instead of using codecpar

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 06:17:45 +01:00
Carlos
494b14b651 fix(memory): Fix memory issues in helpers, splitbysentence, and output
- ccx_encoders_helpers.c:
  - add_word(): Fix unsafe realloc pattern, preserve original pointer
  - shell_sort(): Add null check for temp buffer allocation

- ccx_encoders_splitbysentence.c:
  - init_sbs_context(): Add null checks for context and buffer allocations
  - sbs_append_string(): Fix unsafe realloc pattern for buffer
  - sbs_append_string(): Add null check for cc_subtitle allocation

- output.c:
  - writeraw(): Fix unsafe realloc pattern, preserve original pointer
    and set to NULL on failure

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 06:07:58 +01:00
Carlos
5b286c5b8d fix(memory): Fix potential memory leaks in encoder files
- ccx_encoders_ssa.c: Fix combined malloc check pattern
  - Check each allocation separately
  - Free first allocation if second fails before calling fatal

- ccx_encoders_webvtt.c: Fix 2 combined check patterns
  - write_stringz_as_webvtt: Separate checks with proper cleanup
  - write_cc_bitmap_as_webvtt: Separate calloc checks with cleanup

- ccx_encoders_smptett.c: Fix combined malloc check pattern
  - Check each allocation separately
  - Free first allocation if second fails before calling fatal

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 06:04:53 +01:00
Carlos
ea4f884b9d fix(memory): Fix unsafe realloc patterns in asf_functions, telxcc, and ccx_encoders_srt
- asf_functions.c: Fix 2 unsafe realloc patterns
  - Use temporary pointer to preserve original buffer reference
  - Free original buffer before calling fatal on allocation failure

- telxcc.c: Fix 2 unsafe realloc patterns in teletext buffer functions
  - page_buffer_add_string: Use safe realloc pattern with temp pointer
  - ucs2_buffer_add_char: Use safe realloc pattern with temp pointer

- ccx_encoders_srt.c: Fix potential memory leak in write_stringz_as_srt
  - Check each allocation separately
  - Free successful allocation before fatal if second allocation fails

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 06:01:36 +01:00
Carlos
3b0a63d9c6 fix(memory): Fix memory leaks and unsafe realloc patterns in lib_ccx, utility, avc_functions
- lib_ccx.c: Fix memory leaks in init_libraries error paths
  - Add proper cleanup for report_608, EPG buffers, and ctx when
    init_decoder_setting fails
  - Add comprehensive cleanup at end: label when init_ctx_outbase fails

- utility.c: Fix unsafe realloc in str_reallocncat
  - Preserve original pointer and free it on realloc failure
  - Prevents memory leak when realloc returns NULL

- avc_functions.c: Fix unsafe realloc patterns in user_data_registered_itu_t_t35
  - Use temporary pointer for realloc result
  - Free original buffer before calling fatal on allocation failure
  - Fixes two instances of unsafe realloc pattern

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 05:58:20 +01:00
Carlos
390c96f00d fix(memory): Fix memory leaks and unsafe realloc patterns in multiple files
Batch 2.2 memory fixes:

dvb_subtitle_decoder.c:
- Fix memory leak in write_dvb_sub: free rect->data1 and rect before fatal
  when data0 allocation fails

general_loop.c:
- Fix unsafe realloc in rcwt_loop: use temp variable to preserve original
  parsebuf pointer on failure
- Fix memory leak: free parsebuf on early return in rcwt_loop

ts_functions.c:
- Fix unsafe realloc in copy_payload_to_capbuf: use temp variable to
  preserve original cinfo->capbuf on failure
- Fix unsafe realloc in hauppauge buffer handling: free original buffer
  before fatal on failure

ccx_decoders_608.c:
- Fix two unsafe realloc patterns in write_cc_buffer_as_transcript and
  write_cc_buffer_to_gui: use temp variable to preserve original sub->data
  on failure

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 05:52:12 +01:00
Carlos
95f6f09659 fix(memory): Fix memory leaks in ocr.c and ts_tables_epg.c
In ocr.c:
- Fix realloc failure leak in search_language_pack (free dirname)
- Fix malloc failure leaks in ocr_bitmap (free histogram, iot, mcit)
- Fix realloc failure leak for new_text_out
- Fix multiple allocation failure paths in ocr_rect with proper cleanup

In ts_tables_epg.c:
- Fix malloc failure leak in EPG_ATSC_decode_multiple_string (free event_name)
- Fix realloc failure leak in parse_EPG_packet (free buffer)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 05:46:52 +01:00
Carlos Fernandez Sanz
42885caedd fix(dvb): Multiple fixes for DVB subtitles - timing, OCR quality, memory access bugs (#224) (#1826)
* fix(dvb): Multiple fixes for DVB subtitle extraction from Chinese broadcasts (#224)

This commit addresses multiple issues with DVB subtitle extraction reported in #224:

1. **PMT parsing crash fix** (ts_tables.c):
   - Added minimum length check (16 bytes) to prevent out-of-bounds access
   - Added bounds check before memcpy to prevent buffer overflow when section > 1021 bytes

2. **Negative subtitle timing fix** (general_loop.c):
   - For DVB subtitle streams, properly initialize min_pts from audio/subtitle PTS
   - This fixes the issue where all timestamps were negative (~95000 seconds off)

3. **OCR improvements** (ocr.c):
   - Fixed ignore_alpha_at_edge() which could create invalid crop windows
   - Added image inversion for DVB subtitles (light text on dark background)
     to improve Tesseract OCR accuracy
   - Added contrast normalization to further improve character recognition
   - Fixed nofontcolor check to respect --no-fontcolor parameter
   - Added iteration safety limit in color detection loop

4. **--ocrlang parameter fix** (Rust files):
   - Changed ocrlang from Language enum to String to accept Tesseract language
     names directly (e.g., "chi_tra", "chi_sim", "eng")
   - Added case-insensitive matching for --dvblang parameter
   - Added better error messages for invalid language codes

Tested with 12GB Chinese DVB broadcast file:
- Timing: All timestamps now positive (0.235s, 2.594s, etc.)
- OCR: ~80-90% accuracy with chi_tra traineddata (improved from ~70%)
- No crashes during full file processing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(ocr): Fix crashes in DVB subtitle color detection

Two issues fixed in the OCR color detection code:

1. Tesseract crash during iteration:
   - The color detection pass used raw color images without preprocessing
   - Tesseract expects dark text on light background, but DVB subtitles
     have light text on dark background
   - Added grayscale conversion, inversion, and contrast enhancement
     (same preprocessing as the main OCR pass)

2. Heap corruption in histogram calculation:
   - The histogram loop had no bounds checking on array accesses
   - Tesseract could return invalid bounding boxes causing buffer overflows
   - Added validation of bounding box coordinates before processing
   - Added safe index checking for copy->data and histogram arrays

Also added skip_color_detection label for clean error handling and
proper cleanup of the preprocessed image.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(dvb): Fix zero-duration subtitles and overlaps during PTS jumps

Add start_pts field to cc_subtitle struct to track raw PTS values
independent of FTS timeline resets. Modify end_time calculation in
dvbsub_handle_display_segment() to cap duration at 4 seconds when
PTS jumps cause timeline discontinuities, preventing zero-duration
and overlapping subtitles.

Also update .gitignore to exclude plans/ directory and temp files.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 20:03:55 -08:00
Carlos Fernandez Sanz
8d95ad0e7b chore: Apply code formatting and update changelog (#1825)
- Apply clang-format to all C/H files in src/
- Apply cargo fmt to Rust code
- Update Cargo.lock with latest compatible dependency versions
- Add 24 new entries to CHANGES.TXT for recent fixes and features

Changes in CHANGES.TXT cover:
- CEA-708 bounds checks and UTF-16BE encoding fixes
- New --ttxtforcelatin option for Teletext
- TS files without PAT/PMT fallback support
- Timing accuracy improvements across MP4/MPEG/TS
- Memory safety improvements (null checks, buffer overruns)
- Multi-file processing fixes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 13:34:16 -08:00
Carlos Fernandez Sanz
1f0980185f fix(rust): Add bounds checks to prevent panic on malformed CEA-708 data (#1817)
* fix(rust): Add bounds checks to prevent panic on malformed CEA-708 data

Fixes #1616 - Segmentation fault when extracting from MP4 remuxed from HLS

The CEA-708 decoder could panic when processing truncated or malformed
caption data blocks:

1. Fixed EXT1 command handling in process_service_block():
   - Changed &block[1..] to &block[(i+1)..] for correct slice offset
   - Added bounds check before accessing the next byte after EXT1

2. Added bounds checks in handle_extended_char():
   - Check for empty block before accessing block[0]
   - Check block.len() >= 2 before accessing block[1] for C3 commands

3. Removed unnecessary `as i64` cast in es/pic.rs to fix clippy warning

Added 4 unit tests to verify the bounds checking:
- test_handle_extended_char_empty_block
- test_handle_extended_char_c3_insufficient_bytes
- test_process_service_block_ext1_at_end
- test_process_service_block_ext1_with_truncated_c3

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(rust): cast c_long to i64 in pic.rs for Windows compatibility

On Windows, c_long is i32 (32-bit) while on Linux it's i64 (64-bit).
The addition of fts_at_gop_start + frame_offset_ms was failing on Windows
because fts_at_gop_start (c_long = i32) couldn't be added to frame_offset_ms (i64).

Added explicit cast to i64 with #[allow(clippy::unnecessary_cast)] since
the cast is necessary for Windows even though it's redundant on Linux.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 07:47:47 -08:00
Carlos Fernandez Sanz
6c764aa56c fix: Correct is_decoder_processed_enough() multiprogram logic and suppress false warnings (#1823)
Fixes #1701

The `is_decoder_processed_enough()` function had a bug where it would always
return FALSE in multiprogram mode due to the condition:
  `dec_ctx->processed_enough == CCX_TRUE && ctx->multiprogram == CCX_FALSE`

This caused the "Error in switch_to_next_file()" warning to trigger incorrectly
for files without captions or in multiprogram mode.

Changes:
- Fix `is_decoder_processed_enough()` in C and Rust:
  - In single-program mode: return TRUE if ANY decoder has processed enough
  - In multiprogram mode: return TRUE only if ALL decoders have processed enough
- Add check for empty decoder list in `switch_to_next_file()`:
  - If no decoders exist (no captions found), suppress the premature ending warning
  - This is a normal condition, not an error
- Update Rust tests to verify the new behavior

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 07:45:16 -08:00
Carlos Fernandez Sanz
a0129df16c fix(708): Write consistent 2-byte UTF-16BE encoding for CEA-708 captions (#1820)
* fix(708): Write consistent 2-byte UTF-16BE encoding for CEA-708 captions

Previously, the write_utf16_char (C) and write_char (Rust) functions
wrote 1 byte for ASCII characters (high byte = 0) and 2 bytes for
non-ASCII characters. This created an invalid mix of 8-bit and 16-bit
values that iconv/encoding_rs couldn't convert properly when UTF-16BE
encoding was specified.

The fix always writes 2 bytes per character, ensuring consistent
UTF-16BE encoding. This allows iconv to properly convert the data to
UTF-8, fixing garbled output for Japanese and Chinese captions.

Before fix (garbled):
人々が私を知‰挰弰栰䴰Ź섰漠時間管理につい‰晦<U+F830>䐰昰䐰縰

After fix (correct):
人々が私を知 ったとき、私は 時間管理につい て書いています

Fixes #1451

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* test(708): Update write_char test to expect 2-byte UTF-16BE output

The test was checking for the old (incorrect) behavior where ASCII
characters were written as 1 byte. The fix for issue #1451 correctly
changed write_char to always write 2 bytes for proper UTF-16BE encoding.
Updated the test to match this correct behavior.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 07:42:46 -08:00
Carlos Fernandez Sanz
d2ab31fe38 fix(teletext): Add --ttxtforcelatin option to force Latin G0 charset (#1821)
Some broadcast streams incorrectly signal Cyrillic character set (via
X/28 or M/29 packets) when the actual content is Latin text. This causes
garbled output where Latin text like "No. Not back then, anyway." appears
as Cyrillic "Но. Нот бацк тхен, анiваi."

This fix adds a new --ttxtforcelatin option that forces the teletext G0
character set to Latin, ignoring any Cyrillic designation in the stream.

Root cause: The broadcast contained triplet 0x1290 which has bits 10-13
set to 0x1 (Cyrillic family) and bits 7-9 set to 0x5 (Ukrainian option),
causing CCExtractor to use CYRILLIC3 charset instead of Latin.

Usage: ccextractor input.ts --ttxtforcelatin -o output.srt

Before fix (without option):
  Subtitle 3: Но. Нот бацк тхен, анiваi.

After fix (with --ttxtforcelatin):
  Subtitle 3: No. Not back then, anyway.

Fixes #1395

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 07:42:06 -08:00
Carlos Fernandez Sanz
3f6656176e fix(ts): Add fallback for TS files without PAT/PMT tables (#1822)
Some DVR recordings (e.g., Channel Master DVR+) create transport stream
files that contain valid video and audio data but lack PAT (Program
Association Table) and PMT (Program Map Table). Without these tables,
CCExtractor couldn't identify which PIDs contain video streams with
embedded captions.

This change adds a fallback mechanism that:
1. Enables packet analysis mode when no PAT is found after reading ~1000
   TS packets (188KB)
2. Detects video streams by analyzing PES headers (stream_id 0xE0-0xEF)
3. Identifies stream type (MPEG-2 vs H.264) from elementary stream data
4. Registers detected video streams for caption extraction
5. Also detects GA94 caption markers to identify caption-carrying PIDs

The fix allows CCExtractor to extract CEA-608/708 captions from TS files
without PAT/PMT, matching the behavior when FFmpeg is enabled.

Fixes #805

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 07:40:52 -08:00
Carlos Fernandez Sanz
f2f63ed65f fix(timing): Set pts_set to MinPtsSet after PTS jump to continue fts_now updates (#1824)
When a PTS discontinuity (jump) is detected, the code updates fts_offset
and min_pts to establish a new timeline. However, it was not setting
pts_set back to MinPtsSet, which meant fts_now calculation (which only
runs when pts_set == MinPtsSet) would stop working. This caused all
timestamps after the PTS jump to be stuck.

This fixes issue #1277 where DVD VOB files with PTS discontinuities
(common at chapter boundaries) would stop extracting captions after
about 6 minutes. Version 0.84 worked correctly, but 0.85+ had this
regression.

Closes #1277

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-14 07:36:01 -08:00
Carlos Fernandez Sanz
3738540804 style: use CCX_STREAM_TYPE_VIDEO_HEVC enum instead of raw 0x24 (#1819)
Follow-up to PR #1769 - use the defined enum constant for HEVC stream
type (0x24) instead of magic numbers for better code maintainability.

Also simplifies the case statement in get_printable_stream_type() by
removing redundant assignment since the enum value passes through
unchanged.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 03:55:38 -08:00
Carlos Fernandez Sanz
31c6e94e25 fix(memory): Add null checks for unchecked memory allocations (#1815)
Add proper null checks after malloc/calloc/realloc calls to prevent
potential NULL pointer dereferences on out-of-memory conditions.

Files fixed:
- general_loop.c: Add null checks for line buffer and parsebuf; remove
  duplicate allocation that shadowed outer variable (memory leak fix)
- ccx_encoders_webvtt.c: Add null check for color_events/font_events
- ccx_decoders_isdb.c: Add null check for text->buf before dereference
- dvb_subtitle_decoder.c: Move null check before memset
- mp4.c: Add null check for dec_sub->data before memcpy
- ccx_decoders_608.c: Add null check for decoder context
- ccx_decoders_xds.c: Add null check for string buffer
- asf_functions.c: Add null check after struct initialization with malloc
- ccx_dtvcc.c: Move null check before dereferences (was checking after use)
- lib_ccx.c: Fix memset-before-check ordering; add checks for pesheaderbuf
  and DVB context allocations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 03:55:06 -08:00
Carlos Fernandez Sanz
33f41f6045 fix(rust): Add null checks and handle invalid UTF-8 in FFI functions (#1816)
- ccxr_process_cc_data: Add null pointer checks for dec_ctx, data, and
  dec_ctx.dtvcc before dereferencing. Also check cc_count > 0.
- ccxr_parse_parameters: Add null check for argv pointer and use
  to_string_lossy() instead of expect() to handle invalid UTF-8
  gracefully without panicking.

These changes prevent potential crashes when FFI functions are called
with invalid arguments from C code.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 03:48:29 -08:00
Chandragupt Singh
137719ebea [FIX]: Add HEVC/H.265 stream type recognition to prevent crashes on ATSC 3.0 streams (#1769)
* Add basic HEVC (0x24) TS stream detection to avoid unknown buffer type errors

* docs: update CHANGES.TXT with HEVC/H.265 stream type fix entry
2025-12-14 03:25:05 -08:00
Carlos
ecb0780af5 fix: Enable stdout output for CEA-708 captions on Windows
Fixes #1693 - ccextractorwinfull.exe can't print captions to stdout

The CEA-708 decoder crashed on Windows when using --stdout because the
dtvcc_writer was not properly initialized for stdout output:

1. Fixed Windows stdout handle initialization in ccx_encoders_common.c:
   - Use GetStdHandle(STD_OUTPUT_HANDLE) instead of NULL for fhandle
   - This allows the Rust writer to detect stdout mode properly

2. Changed env_logger target from Stdout to Stderr in lib.rs:
   - Debug messages no longer pollute stdout when using --stdout
   - This prevents mixing debug output with subtitle content

3. Removed redundant debug statement in service_decoder.rs:
   - The bare `debug!("{}", self.current_window)` was noisy and
     duplicated by a more detailed debug statement below it

Added tests:
- test_writer_output_with_valid_fd: Verifies stdout mode works
- test_writer_output_missing_filename_and_fd: Verifies proper error handling

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 12:09:24 +01:00
Carlos Fernandez Sanz
abce0864a5 fix(rust): prevent panics in timing code when processing multiple files
fix(rust): prevent panics in timing code when processing multiple files
2025-12-14 02:17:29 -08:00
Carlos Fernandez Sanz
9ff46656be fix(timing): correct caption start/end times to match FFmpeg in mp4 / mpeg / ts 2025-12-14 02:13:03 -08:00
Rahul Tripathi
446923c79d Merge pull request #3 from Rahul-2k4/copilot/apply-clang-format-to-source-files
[FIX] Apply clang-format to ensure CI formatting checks pass
2025-12-14 15:11:57 +05:30
copilot-swe-agent[bot]
cde9e1f842 Initial plan 2025-12-14 09:34:22 +00:00
Rahul Tripathi
6c75b26484 Merge branch 'CCExtractor:master' into master 2025-12-14 14:47:03 +05:30
Rahul Tripathi
9c4d5a8a58 patch on teletext
Added conditional check for printing notice about teletext pages based on file report settings.
2025-12-14 14:45:04 +05:30
Carlos
a49ebf4230 fix(rust): cast c_long to i64 for cross-platform compatibility
On Windows, c_long is i32, while on Linux it's i64. This causes
a type mismatch when adding fts_at_gop_start (c_long) to
frame_offset_ms (i64). Fix by explicitly casting to i64.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 09:58:55 +01:00
Carlos
7b8533a2dc Merge branch 'master' into fix/caption-timing-accuracy 2025-12-14 09:58:42 +01:00
Carlos Fernandez Sanz
134cd75d3b Merge pull request #1811 from CCExtractor/fix/multi-file-processing
fix(rust): correctly count and store multiple input files
2025-12-14 00:47:07 -08:00
Carlos
80e21171b1 style: apply cargo fmt formatting
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 09:43:42 +01:00
Carlos
0b262d0e17 fix(rust): prevent panics in timing code when processing multiple files
Replace `.unwrap()` and `.expect()` calls with safe alternatives to prevent
Rust panics when processing multiple files with different characteristics
(e.g., DVD-type followed by HDTV-type).

Changes:
- Use `unwrap_or(0)` for all type conversions that could fail
- Handle RwLock poisoning gracefully in apply_timing_info/write_back_from_timing_info
- Add fps validation and millis capping in GopTimeCode::new()
- Add fallback calculation in ccxr_calculate_ms_gop_time when GopTimeCode
  creation fails

Fixes #1377

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 09:39:44 +01:00
Rahul Tripathi
f579cbe45d Merge branch 'CCExtractor:master' into master 2025-12-14 14:02:16 +05:30
Carlos Fernandez Sanz
1a83913540 Merge pull request #1806 from CCExtractor/fix/ttxt-timestamp-milliseconds
fix(parser): use HHMMSSFFF format for ttxt output timestamps
2025-12-14 00:11:08 -08:00
Carlos
075ae04f1d fix(rust): correctly count and store multiple input files
Fix two bugs that prevented multi-file processing from working:

1. In common.rs: `options.inputfile.iter()` was iterating over the
   Option itself (yielding 0 or 1 items) instead of the Vec contents,
   causing num_input_files to always be 1.

2. In parser.rs: append_file_to_queue() was using vec.len() as the
   index for new files after resizing with empty strings, causing
   files to be placed at positions 0, 10, 20... instead of 0, 1, 2...

Fixes #1810

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 08:52:51 +01:00
Carlos
d4949ccfa3 style: apply clang-format and cargo fmt formatting fixes
Fix formatting issues detected by CI:
- C files: Tab alignment, trailing whitespace, blank line cleanup
- Rust: Import statement grouping in pic.rs
- Cargo.lock: Remove duplicate bindgen dependency entries

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 18:41:42 +01:00
Carlos
588c981184 docs: update timing verification plan with Fix 7 results
- Document Fix 7: MP4 c608 track timing and garbage frame detection
- Mark all regressions as fixed or documented as known limitations
- Update status to "Ready for Merge"
- MPEG-PS 66ms offset documented as known limitation (FFmpeg uses
  different timing reference for MPEG-PS vs TS containers)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 18:38:34 +01:00
Carlos
941b88f3f9 fix(timing): handle MP4 c608 tracks and improve garbage frame detection
- Fix MP4 c608/c708 caption tracks by setting frame type to I-frame
  before calling set_fts(). Without video frames, frame type would stay
  Unknown and min_pts would never be set, causing broken timestamps.

- Fix premature pts_set = MinPtsSet assignment. Now only set after
  min_pts is actually set, preventing fts_now calculation with
  uninitialized min_pts (0x01FFFFFFFF) which caused negative timestamps.

- Add garbage frame detection threshold (100ms). When an I-frame arrives:
  - If gap between pending_min_pts and I-frame PTS > 100ms: use I-frame
    PTS (garbage leading frames from truncated GOP)
  - If gap <= 100ms: use pending_min_pts (valid B-frames)

- Track pending_min_pts for all frames (not just unknown type) to enable
  proper garbage vs valid B-frame detection.

Results:
- 5df914ce...mp4: 666ms -> 0ms (FIXED)
- c032183e...ts: 284ms -> 0ms (FIXED)
- addf5e2f...ts: 68ms -> ~1ms (FIXED)
- 80848c45...mpg: remains 66ms (FFmpeg uses different reference for MPEG-PS)
- da904de3...mpg: remains 66ms (FFmpeg uses different reference for MPEG-PS)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 18:35:15 +01:00
Carlos
071d017b27 docs: update timing verification plan with Fix 6 results
- Added Fix 6: Elementary stream frame-by-frame timing
- Updated Category 3 testing results:
  - dc7169d7...h264: FIXED (~500ms, acceptable for roll-up)
  - 6395b281...asf: FIXED (1ms)
  - 0069dffd...mpg: Comparison invalid (mixed language CC)
  - b2771c84...mp4: No captions in file

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 13:55:20 +01:00
Carlos
65d9a7ed1a fix(timing): update fts_now for each frame in elementary streams
For elementary streams with GOP timing (use_gop_as_pts=1), fts_now was
only updated when a GOP header was parsed, not for each frame. This
caused all frames within a GOP to have the same timestamp, resulting
in broken caption timing (1ms, 9ms, 17ms instead of proper times).

The fix calculates fts_now for each frame based on:
  fts_at_gop_start + (frames_since_last_gop * 1000 / fps)

Test results for dc7169d7...h264 (raw MPEG-2 elementary stream):
- Before: 1ms, 9ms, 17ms, 25ms (broken)
- After: 2867ms, 4634ms, 6368ms (correct range)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 13:51:59 +01:00
Carlos
54df50f4fe fix(timing): preserve CR time during pop-on to roll-up transition
When transitioning from pop-on to roll-up mode, the first CR command
(with only 1 line visible, changes=0) was resetting ts_start_of_current_line
to -1. This caused the next caption's start time to be set when characters
were typed (~133ms later), not when the CR command was received.

The fix preserves the CR time when rollup_from_popon=1 and changes=0,
ensuring the caption start time matches when the display state changed.

Test results:
- c83f765c...ts: 134ms offset → 1ms (fixed)
- 725a49f8...mpg: 133ms offset → 0ms (fixed)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 13:37:57 +01:00
Carlos
bc5d605543 fix(timing): handle pop-on to roll-up mode transition timing
When transitioning from pop-on to roll-up mode, CCExtractor was setting
the caption start time when the first character was typed. FFmpeg uses
the time when the display state changed to show multiple lines. This
caused the first roll-up caption after a mode switch to be timestamped
too early.

Changes:
- Add rollup_from_popon flag to track mode transitions
- Reset ts_start_of_current_line on mode switch
- Defer start time until CR causes scrolling in transition mode
- Use ts_start_of_current_line when buffer scrolls during transition

Test results for 725a49f8...mpg:
- Before: 484ms early
- After: 133ms late (~4 frames, acceptable)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 13:21:20 +01:00
Carlos
a1a0094167 fix(timing): defer min_pts until frame type is known
The previous timing fixes were being bypassed because set_fts() is called
multiple times per frame - first from the PES/TS layer (with unknown frame
type) and later from the ES parsing layer (with known frame type). The first
call was setting min_pts before we knew whether it was an I-frame.

Changes:
- When frame type is unknown, track PTS in pending_min_pts but DON'T set min_pts
- Only set min_pts when frame type is known AND it's an I-frame
- Added unknown_frame_count for fallback handling of H.264 streams
- After 100+ calls with unknown frame type, use pending_min_pts as fallback

Test results:
- 8e8229b88bc6...mpg: 101ms -> 1ms offset ✓
- c032183ef018...ts: 284ms -> 0ms offset ✓
- add511677cc42...vob: 366ms -> 34ms offset ✓

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 12:12:49 +01:00
Carlos
5b8d8a72d8 fix(timing): add frame type tracking for future timing improvements
Add seen_known_frame_type and pending_min_pts fields to track frame
types during initial stream parsing. This infrastructure supports
distinguishing between MPEG-2 streams (where frame types are set) and
H.264 in MPEG-PS (where frame types remain unknown).

Current behavior maintains compatibility by allowing min_pts to be set
from any frame type, which correctly handles both stream types and
matches FFmpeg timing output.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 11:58:23 +01:00
Carlos
621871eb7c fix(timing): skip leading non-I-frames when setting min_pts
Streams recorded mid-broadcast often start with trailing B/P frames from
a previous GOP. These frames have earlier PTS values than the first
decodable I-frame.

Previously, CCExtractor set min_pts from the first PES packet with a PTS,
which could be an undecodable B/P frame. FFmpeg's cc_dec uses the first
decoded frame (necessarily an I-frame) as its timing reference.

This caused consistent timing offsets. For example, c032183ef01...ts had
a 284ms offset because:
- First PES packet PTS: 2508198438
- First I-frame PTS: 2508223963
- Difference: 25525 ticks = 284ms

Changes:
- timing.rs: Only set min_pts when current_picture_coding_type == IFrame
- ccx_decoders_common.c: Don't increment cb_field counters for container
  formats (CCX_H264, CCX_PES) since frame PTS is already correct
- sequencing.c: Include CCX_PES in reset_cb logic alongside CCX_H264

Test results for c032183ef01...ts:
- Before: CCExtractor 1,836ms vs FFmpeg 1,552ms = 284ms offset
- After: CCExtractor 1,552ms vs FFmpeg 1,552ms = 0ms offset

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 11:29:07 +01:00
Carlos Fernandez Sanz
ffcb5fe149 Merge pull request #1802 from CCExtractor/fix/utility-buffer-overruns
fix(utility): prevent buffer overruns and add OOM checks in change_filename
2025-12-13 01:36:57 -08:00
Carlos Fernandez Sanz
1b0808b4f3 Merge pull request #1807 from CCExtractor/fix/phase3-buffer-safety-medium-priority
fix(lib_ccx): replace unsafe string functions with bounds-checked versions
2025-12-13 01:25:25 -08:00
Carlos
68da0a044d style: fix clang-format issues
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 08:38:23 +01:00
Carlos
87b0d22057 fix(ts_tables_epg): add NULL checks and fix memory leaks
- EPG_output_live: add NULL checks for filename/finalfilename malloc,
  add fopen failure check
- EPG_DVB_decode_string: add NULL checks for decode_buffer and out
  malloc
- EPG_decode_content_descriptor: add NULL check for categories malloc
- EPG_decode_parental_rating_descriptor: add NULL check for ratings
  malloc
- EPG_decode_extended_event_descriptor: add NULL checks for net and
  extended_text malloc
- EPG_ATSC_decode_multiple_string: add NULL checks for event_name and
  text malloc
- parse_EPG_packet: add NULL check for buffer malloc, fix unsafe
  realloc that lost original pointer on failure
- EPG_decode_short_event_descriptor: fix memory leak - free event_name
  on early return
- EPG_DVB_decode_EIT: fix memory leak - call EPG_free_event on early
  return

All OOM conditions now use fatal(EXIT_NOT_ENOUGH_MEMORY, ...) following
the project's coding patterns.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 08:38:23 +01:00
Carlos
af5e36cdab style: fix clang-format issues in macro definitions
Fix macro formatting to have 'do' and '{' on separate lines and
align backslashes consistently, as required by clang-format.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 08:38:23 +01:00
Carlos
8329257b99 fix(708_output): replace sprintf with snprintf for buffer safety
Replace all sprintf calls with snprintf to prevent potential buffer
overflows in CEA-708 output functions. Key changes:

- dtvcc_change_pen_colors: add bounds checking for font color tags
- dtvcc_change_pen_attribs: add bounds checking for italic/underline tags
- dtvcc_write_srt: track buffer length with snprintf
- dtvcc_write_transcript: add bounds checking for CC/mode labels
- dtvcc_write_sami_header: use snprintf macro for all SAMI tags
- dtvcc_write_sami_footer: use snprintf with length check
- dtvcc_write_sami: add bounds checking for sync tags
- dtvcc_write_scc_header: use snprintf for SCC header
- add_needed_scc_labels: add buffer size parameter for safe writes
- dtvcc_write_scc: use snprintf macro for all SCC formatting
- dtvcc_writer_init: use snprintf for filename suffix

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 08:38:23 +01:00
Carlos
1869c4c713 fix(mcc_encoder): prevent buffer overruns and add OOM checks
- Add NULL checks after malloc calls for compressed_data_buffer and buff_ptr
- Replace sprintf with snprintf for all string formatting operations
- Replace strcat with bounds-checked direct character assignment
- Replace vsprintf with vsnprintf in debug_log function
- Replace sprintf loop in random_chars with direct character lookup table
- Increase buffer sizes for date_str (50->64), time_str (30->32), tcr_str (25->32)
- Initialize tcr_str in default case to prevent uninitialized use
- Add lib_ccx.h include for fatal() function declaration

Functions modified:
- mcc_encode_cc_data: OOM check + sprintf -> snprintf + strcat -> direct assignment
- generate_mcc_header: sprintf -> snprintf for uuid_str, date_str, time_str, tcr_str
- add_boilerplate: OOM check for buff_ptr
- random_chars: sprintf -> direct character lookup (more efficient)
- debug_log: vsprintf -> vsnprintf + safer strlen check

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 08:38:23 +01:00
Carlos
b3c3bdcdac fix(ocr): add NULL checks and fix memory leaks
- search_language_pack: add NULL check after strdup(), fix unsafe
  realloc() that lost original pointer on failure
- init_ocr: fix memory leak where ctx wasn't freed on early return
  when tessdata not found, add NULL checks for strdup() calls
- ocr_bitmap: fix memory leak when pixCreate partially fails, add
  missing boxDestroy for crop_points on early return, add NULL checks
  for histogram/iot/mcit allocations, fix unsafe realloc() calls,
  add NULL check for text_out strdup
- ocr_rect: add NULL check for copy allocation, initialize copy->data
  to NULL to prevent freep on uninitialized pointer, add NULL check
  for copy->data allocation
- paraof_ocrtext: use fatal() on malloc failure for consistent OOM
  handling

All OOM conditions now use fatal(EXIT_NOT_ENOUGH_MEMORY, ...) following
the project's coding patterns.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 08:38:23 +01:00
Carlos
6e295ac374 fix(ccx_encoders_spupng): add NULL checks and fix memory leaks
This commit addresses multiple memory safety issues in ccx_encoders_spupng.c:

**NULL pointer dereference fixes (crash prevention):**

1. write_cc_bitmap_as_spupng() line 440: Added NULL check after malloc
   for pbuf - previously would crash on memset if allocation failed.

2. write_image() line 541: Added NULL check after malloc for row buffer
   with proper cleanup via goto finalise.

3. center_justify() line 611: Added NULL check after malloc for
   temp_buffer - previously would crash immediately on use.

4. utf8_to_utf32() line 718: Added NULL check after calloc for
   string_utf32 - previously would crash on use by iconv.

5. spupng_export_string2png() line 780: Fixed existing NULL check that
   printed error but did not return/exit - code would continue to
   memset(NULL, ...) causing a crash.

**Memory leak fixes:**

6. spupng_export_string2png() line 789: Fixed leak where buffer was not
   freed when strdup(str) failed and function returned early.

7. spupng_export_string2png() line 901: Fixed leak on realloc failure
   where buffer, tmp, and string_utf32 were leaked. Now properly frees
   all three before calling fatal().

All fatal() calls include diagnostic information (function name and
bytes requested where applicable) to aid debugging OOM conditions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 08:38:23 +01:00
Carlos
468bd2c156 style: fix clang-format issues in macro definitions
Fix macro formatting to have 'do' and '{' on separate lines and
align backslashes consistently, as required by clang-format.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 08:31:10 +01:00
Carlos
bcf7eb2a50 fix(708_output): replace sprintf with snprintf for buffer safety
Replace all sprintf calls with snprintf to prevent potential buffer
overflows in CEA-708 output functions. Key changes:

- dtvcc_change_pen_colors: add bounds checking for font color tags
- dtvcc_change_pen_attribs: add bounds checking for italic/underline tags
- dtvcc_write_srt: track buffer length with snprintf
- dtvcc_write_transcript: add bounds checking for CC/mode labels
- dtvcc_write_sami_header: use snprintf macro for all SAMI tags
- dtvcc_write_sami_footer: use snprintf with length check
- dtvcc_write_sami: add bounds checking for sync tags
- dtvcc_write_scc_header: use snprintf for SCC header
- add_needed_scc_labels: add buffer size parameter for safe writes
- dtvcc_write_scc: use snprintf macro for all SCC formatting
- dtvcc_writer_init: use snprintf for filename suffix

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 08:31:10 +01:00
Carlos
54c7dfa45f fix(mcc_encoder): prevent buffer overruns and add OOM checks
- Add NULL checks after malloc calls for compressed_data_buffer and buff_ptr
- Replace sprintf with snprintf for all string formatting operations
- Replace strcat with bounds-checked direct character assignment
- Replace vsprintf with vsnprintf in debug_log function
- Replace sprintf loop in random_chars with direct character lookup table
- Increase buffer sizes for date_str (50->64), time_str (30->32), tcr_str (25->32)
- Initialize tcr_str in default case to prevent uninitialized use
- Add lib_ccx.h include for fatal() function declaration

Functions modified:
- mcc_encode_cc_data: OOM check + sprintf -> snprintf + strcat -> direct assignment
- generate_mcc_header: sprintf -> snprintf for uuid_str, date_str, time_str, tcr_str
- add_boilerplate: OOM check for buff_ptr
- random_chars: sprintf -> direct character lookup (more efficient)
- debug_log: vsprintf -> vsnprintf + safer strlen check

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 08:31:10 +01:00
Carlos
984123521d fix(ocr): add NULL checks and fix memory leaks
- search_language_pack: add NULL check after strdup(), fix unsafe
  realloc() that lost original pointer on failure
- init_ocr: fix memory leak where ctx wasn't freed on early return
  when tessdata not found, add NULL checks for strdup() calls
- ocr_bitmap: fix memory leak when pixCreate partially fails, add
  missing boxDestroy for crop_points on early return, add NULL checks
  for histogram/iot/mcit allocations, fix unsafe realloc() calls,
  add NULL check for text_out strdup
- ocr_rect: add NULL check for copy allocation, initialize copy->data
  to NULL to prevent freep on uninitialized pointer, add NULL check
  for copy->data allocation
- paraof_ocrtext: use fatal() on malloc failure for consistent OOM
  handling

All OOM conditions now use fatal(EXIT_NOT_ENOUGH_MEMORY, ...) following
the project's coding patterns.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 08:31:10 +01:00
Carlos
a2cb65f181 fix(ccx_encoders_spupng): add NULL checks and fix memory leaks
This commit addresses multiple memory safety issues in ccx_encoders_spupng.c:

**NULL pointer dereference fixes (crash prevention):**

1. write_cc_bitmap_as_spupng() line 440: Added NULL check after malloc
   for pbuf - previously would crash on memset if allocation failed.

2. write_image() line 541: Added NULL check after malloc for row buffer
   with proper cleanup via goto finalise.

3. center_justify() line 611: Added NULL check after malloc for
   temp_buffer - previously would crash immediately on use.

4. utf8_to_utf32() line 718: Added NULL check after calloc for
   string_utf32 - previously would crash on use by iconv.

5. spupng_export_string2png() line 780: Fixed existing NULL check that
   printed error but did not return/exit - code would continue to
   memset(NULL, ...) causing a crash.

**Memory leak fixes:**

6. spupng_export_string2png() line 789: Fixed leak where buffer was not
   freed when strdup(str) failed and function returned early.

7. spupng_export_string2png() line 901: Fixed leak on realloc failure
   where buffer, tmp, and string_utf32 were leaked. Now properly frees
   all three before calling fatal().

All fatal() calls include diagnostic information (function name and
bytes requested where applicable) to aid debugging OOM conditions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 08:31:10 +01:00
Carlos Fernandez Sanz
fe7a4b3f45 Merge pull request #1799 from CCExtractor/fix/ts-tables-epg-memory-safety
fix(ts_tables_epg): add NULL checks and fix memory leaks
2025-12-12 23:30:02 -08:00
Carlos Fernandez Sanz
d4ec0fe49b Merge pull request #1800 from CCExtractor/fix/708-output-buffer-safety
fix(708_output): replace sprintf with snprintf for buffer safety
2025-12-12 23:24:26 -08:00
Carlos Fernandez Sanz
4a98bf5290 Merge pull request #1804 from CCExtractor/fix/mcc-encoder-buffer-overruns
fix(mcc_encoder): prevent buffer overruns and add OOM checks
2025-12-12 23:23:25 -08:00
Carlos Fernandez Sanz
249cac359f Merge pull request #1798 from CCExtractor/fix/ocr-memory-safety
fix(ocr): add NULL checks and fix memory leaks
2025-12-12 23:21:11 -08:00
Carlos
69e521b320 fix(timing): correct caption start/end times to match video frame PTS
The get_visible_start() and get_visible_end() functions were adding a
cb_field offset (cb_field * 1001/30 ms) to caption timestamps. This
offset was designed for broadcast MPEG-TS streams where caption data
arrives continuously at field rate (59.94 fields/sec).

However, for container formats like MP4, all caption data for a video
frame is bundled together and should use the frame's PTS directly. The
offset was causing caption start times to be ~300ms (9 frames) later
than the actual video frame timestamp.

Root cause analysis:
1. Previous caption ends → get_visible_end() returns inflated time
   due to cb_field offset → minimum_fts set to this inflated value
2. New caption starts → get_visible_start() constrained by
   minimum_fts + 1 → start time incorrectly pushed forward

Fix:
- Add new Rust FFI functions ccxr_get_visible_start() and
  ccxr_get_visible_end() that return base FTS (fts_now + fts_global)
  without the cb_field offset
- Update C wrappers to call the new Rust functions
- Update Rust decoder timing to use base FTS

Verification against ffmpeg:
- Before fix: 00:16:06,799 (300ms late)
- After fix:  00:16:06,499 (matches ffmpeg exactly)
- ffmpeg ref: 00:16:06,499

The get_fts() function is unchanged - it still returns the
offset-adjusted time for use cases that need it (like extraction
time boundary checking).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 08:01:29 +01:00
Carlos
8af19df556 fix(lib_ccx): replace remaining unsafe string functions with bounds-checked versions
Replace sprintf/strcpy with snprintf/memcpy in LOW priority files:
- general_loop.c: proper buffer allocation with OOM check, snprintf
- ccx_encoders_g608.c: snprintf with sizeof for timeline buffer
- lib_ccx.c: fix buffer size calculation, add missing null check, snprintf
- ccx_common_timing.c: snprintf with documented max size for time functions
- ts_functions.c: snprintf with sizeof in debug code
- matroska.c: bounded memcpy to prevent overflow from malformed language codes
- output.c: snprintf with known allocated size

This completes Phase 3.1 of the buffer safety audit.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 07:10:54 +01:00
Carlos
bff08bec9e fix(encoders): replace unsafe string functions with bounds-checked versions
Replace sprintf/strcpy/strcat with snprintf/strncat/memmove in:
- ccx_encoders_common.c: 4 sprintf -> snprintf
- ccx_encoders_helpers.c: 3 strcat -> strncat, 1 strcpy -> memcpy
- telxcc.c: 3 sprintf -> snprintf
- asf_functions.c: 3 sprintf -> snprintf
- ccx_encoders_ssa.c: 3 sprintf -> snprintf
- ccx_encoders_curl.c: 1 sprintf -> snprintf, strcpy+strcat -> snprintf with OOM check
- ccx_encoders_splitbysentence.c: 1 strcpy -> memmove (overlapping memory fix), 2 strcat -> strncat

This is part of Phase 3.1 of the buffer safety audit, addressing MEDIUM priority files.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 07:00:44 +01:00
Carlos
a66fb8c661 fix(utility): prevent buffer overruns and add OOM checks in change_filename
- Add NULL checks after malloc calls for temp_encoder, current_name, and newname
- Replace sprintf with snprintf for safe string formatting
- Replace strcpy/strcat with strncpy and snprintf to prevent buffer overflows
- Increase buffer sizes from 6/10/15 to 16 chars to safely hold extension numbers
- Use proper size tracking with filename_len and buffer size variables

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 06:46:28 +01:00
Carlos Fernandez Sanz
042716adde fix(xds_decoder): prevent buffer overruns and fix sprintf logic bug (#1803)
- Replace sprintf with snprintf for all string formatting operations
- Replace strcpy/strcat chains with snprintf for bounds-safe concatenation
- Replace strcpy with strncpy + null terminator for fixed-size buffers
- Fix bug in xds_do_private_data: sprintf in loop was overwriting instead
  of appending hex bytes to output string

Functions modified:
- xds_do_copy_generation_management_system: 3 sprintf -> snprintf
- xds_do_content_advisory: 5 sprintf -> snprintf, strcpy/strcat chain fixed
- xds_do_current_and_future: strcpy -> strncpy for program description
- xds_do_channel: strcpy -> strncpy for network name
- xds_do_private_data: fixed loop to properly append hex bytes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-12 21:40:54 -08:00
Carlos
1342e4edee fix(ocr): add NULL checks and fix memory leaks
- search_language_pack: add NULL check after strdup(), fix unsafe
  realloc() that lost original pointer on failure
- init_ocr: fix memory leak where ctx wasn't freed on early return
  when tessdata not found, add NULL checks for strdup() calls
- ocr_bitmap: fix memory leak when pixCreate partially fails, add
  missing boxDestroy for crop_points on early return, add NULL checks
  for histogram/iot/mcit allocations, fix unsafe realloc() calls,
  add NULL check for text_out strdup
- ocr_rect: add NULL check for copy allocation, initialize copy->data
  to NULL to prevent freep on uninitialized pointer, add NULL check
  for copy->data allocation
- paraof_ocrtext: use fatal() on malloc failure for consistent OOM
  handling

All OOM conditions now use fatal(EXIT_NOT_ENOUGH_MEMORY, ...) following
the project's coding patterns.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 06:26:59 +01:00
Carlos
4d1d874243 fix(ccx_encoders_spupng): add NULL checks and fix memory leaks
This commit addresses multiple memory safety issues in ccx_encoders_spupng.c:

**NULL pointer dereference fixes (crash prevention):**

1. write_cc_bitmap_as_spupng() line 440: Added NULL check after malloc
   for pbuf - previously would crash on memset if allocation failed.

2. write_image() line 541: Added NULL check after malloc for row buffer
   with proper cleanup via goto finalise.

3. center_justify() line 611: Added NULL check after malloc for
   temp_buffer - previously would crash immediately on use.

4. utf8_to_utf32() line 718: Added NULL check after calloc for
   string_utf32 - previously would crash on use by iconv.

5. spupng_export_string2png() line 780: Fixed existing NULL check that
   printed error but did not return/exit - code would continue to
   memset(NULL, ...) causing a crash.

**Memory leak fixes:**

6. spupng_export_string2png() line 789: Fixed leak where buffer was not
   freed when strdup(str) failed and function returned early.

7. spupng_export_string2png() line 901: Fixed leak on realloc failure
   where buffer, tmp, and string_utf32 were leaked. Now properly frees
   all three before calling fatal().

All fatal() calls include diagnostic information (function name and
bytes requested where applicable) to aid debugging OOM conditions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 06:26:59 +01:00
Carlos
155f56ede7 style: fix clang-format issues in macro definitions
Fix macro formatting to have 'do' and '{' on separate lines and
align backslashes consistently, as required by clang-format.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 06:24:27 +01:00
Carlos
fb49d9460d fix(708_output): replace sprintf with snprintf for buffer safety
Replace all sprintf calls with snprintf to prevent potential buffer
overflows in CEA-708 output functions. Key changes:

- dtvcc_change_pen_colors: add bounds checking for font color tags
- dtvcc_change_pen_attribs: add bounds checking for italic/underline tags
- dtvcc_write_srt: track buffer length with snprintf
- dtvcc_write_transcript: add bounds checking for CC/mode labels
- dtvcc_write_sami_header: use snprintf macro for all SAMI tags
- dtvcc_write_sami_footer: use snprintf with length check
- dtvcc_write_sami: add bounds checking for sync tags
- dtvcc_write_scc_header: use snprintf for SCC header
- add_needed_scc_labels: add buffer size parameter for safe writes
- dtvcc_write_scc: use snprintf macro for all SCC formatting
- dtvcc_writer_init: use snprintf for filename suffix

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 06:24:27 +01:00
Carlos
37fed5e5b5 fix(mcc_encoder): prevent buffer overruns and add OOM checks
- Add NULL checks after malloc calls for compressed_data_buffer and buff_ptr
- Replace sprintf with snprintf for all string formatting operations
- Replace strcat with bounds-checked direct character assignment
- Replace vsprintf with vsnprintf in debug_log function
- Replace sprintf loop in random_chars with direct character lookup table
- Increase buffer sizes for date_str (50->64), time_str (30->32), tcr_str (25->32)
- Initialize tcr_str in default case to prevent uninitialized use
- Add lib_ccx.h include for fatal() function declaration

Functions modified:
- mcc_encode_cc_data: OOM check + sprintf -> snprintf + strcat -> direct assignment
- generate_mcc_header: sprintf -> snprintf for uuid_str, date_str, time_str, tcr_str
- add_boilerplate: OOM check for buff_ptr
- random_chars: sprintf -> direct character lookup (more efficient)
- debug_log: vsprintf -> vsnprintf + safer strlen check

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 06:23:45 +01:00
Carlos
7113036719 fix(parser): use HHMMSSFFF format for ttxt output timestamps
The Rust parser was incorrectly setting date_format to HHMMSS (no
milliseconds) instead of HHMMSSFFF (with milliseconds) for --out=ttxt.

This bug was introduced in PR #1619 when porting the parser to Rust.
The original C code correctly used ODF_HHMMSSMS which includes
milliseconds in the timestamp format (HH:MM:SS,mmm).

Before: 10:25:16 (missing milliseconds)
After:  10:25:16,000 (correct format matching original C behavior)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 06:21:09 +01:00
Carlos Fernandez Sanz
d93d6731ba fix(encoders): replace sprintf/strcpy with bounds-checked versions (#1805)
Replace unsafe string functions with safer alternatives:
- ccx_encoders_sami.c: sprintf -> snprintf (10 fixes)
- ccx_encoders_srt.c: sprintf -> snprintf (6 fixes)
- mp4.c: sprintf/strcpy/strcat -> snprintf (6 fixes, including
  buffer overflow fix in format_duration where 20-byte buffer
  was too small for long duration strings)
- ccx_encoders_webvtt.c: sprintf -> snprintf (6 fixes), plus:
  - Fixed malloc size bug (+4 instead of +5 for null terminator)
  - Added OOM checks for css_file_name and outline_css_file
  - Fixed memory leaks (css_file_name and outline_css_file not freed)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-12 21:16:20 -08:00
Carlos Fernandez Sanz
77e1dff779 fix(smptett): replace unsafe string operations with bounds-checked versions (#1801)
Replace sprintf, strcpy, and strcat calls with snprintf and bounds-checked
operations to prevent potential buffer overflows. Key changes:

- write_stringz_as_smptett: use snprintf for timestamp formatting
- write_cc_bitmap_as_smptett: use snprintf with INITIAL_ENC_BUFFER_CAPACITY
- write_cc_buffer_as_smptett:
  - Add NULL checks for malloc allocations
  - Track buffer size and use snprintf throughout
  - Replace strcpy/strcat chains with bounds-checked memcpy/snprintf
  - Use snprintf for style tag and color code formatting

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-12 21:15:39 -08:00
Carlos Fernandez Sanz
58dedba93f fix(scc): Always emit position codes at start of caption (fixes #1776) (#1791)
* fix(scc): Always emit position codes at start of caption (fixes #1776)

The SCC encoder was initializing current_row=14 and current_column=0,
which caused the first position code (PAC) to be skipped when caption
content started at row 14 (the last row), column 0. This happened because
the condition checking if row/column changed would be false.

For example, a caption starting at row 15 (1-indexed), column 0 should
output the PAC code 9470/{1500} but this was being omitted.

Fix by initializing current_row and current_column to UINT8_MAX, which
is an impossible value that will never match any valid row (0-14) or
column (0-31), ensuring the position code is always written for the
first character of each caption.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(rust): Remove unused assignments to fix clippy warnings

Remove unnecessary `time_show.time_in_ms += 1000 / 29.97` operations
that were restoring values that were never read afterwards.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-12 21:13:02 -08:00
Carlos
9eb266914a fix(ts_tables_epg): add NULL checks and fix memory leaks
- EPG_output_live: add NULL checks for filename/finalfilename malloc,
  add fopen failure check
- EPG_DVB_decode_string: add NULL checks for decode_buffer and out
  malloc
- EPG_decode_content_descriptor: add NULL check for categories malloc
- EPG_decode_parental_rating_descriptor: add NULL check for ratings
  malloc
- EPG_decode_extended_event_descriptor: add NULL checks for net and
  extended_text malloc
- EPG_ATSC_decode_multiple_string: add NULL checks for event_name and
  text malloc
- parse_EPG_packet: add NULL check for buffer malloc, fix unsafe
  realloc that lost original pointer on failure
- EPG_decode_short_event_descriptor: fix memory leak - free event_name
  on early return
- EPG_DVB_decode_EIT: fix memory leak - call EPG_free_event on early
  return

All OOM conditions now use fatal(EXIT_NOT_ENOUGH_MEMORY, ...) following
the project's coding patterns.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 02:00:22 +01:00
Carlos Fernandez Sanz
1510396aa0 fix(ccx_decoders_common): add NULL checks and fix memory safety issues (#1796)
- Add NULL checks after malloc calls in copy_encoder_context(),
  copy_decoder_context(), copy_subtitle(), and init_cc_decode()
- Fix buffer overflows in copy_encoder_context() where string
  allocations were missing +1 for null terminator
- Call fatal(EXIT_NOT_ENOUGH_MEMORY, ...) on allocation failure
  following the pattern used in matroska.c
- Initialize pointers to NULL after memcpy to prevent use of
  stale pointers from the copied structure
- Prevent null pointer dereference in init_cc_decode() when dtvcc_init
  returns NULL

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-12 16:01:47 -08:00
dependabot[bot]
a7dfaea559 chore(deps): bump actions/cache from 4 to 5 (#1790)
Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-12 14:31:22 -08:00
Carlos Fernandez Sanz
e8383c84ee fix(rust): remove unused assignments in tv_screen.rs (#1795)
Remove three unused assignments to `time_show.time_in_ms` that were
flagged by Clippy as "value assigned is never read".

The pattern was: subtract frame delay, use the value, then restore it.
However, since `time_show` is not used after the match statement, the
restoration assignments were unnecessary dead code.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-12 13:56:03 -08:00
Carlos Fernandez Sanz
810c869bc5 fix(dvb_subtitle_decoder): add NULL checks after malloc calls (#1794)
* fix(matroska): add memory safety checks and fix memory leaks

This commit addresses multiple memory safety issues in the Matroska
parser identified through static analysis (cppcheck).

## Null pointer dereference after malloc (15 fixes)

Added null checks after all malloc/calloc calls to prevent crashes
when memory allocation fails:

- read_byte_block(): line 28
- read_bytes_signed(): line 38
- generate_timestamp_ass_ssa(): line 267
- parse_segment_cluster_block_group_block(): lines 306, 361
- parse_segment_cluster_block_group_block_additions(): line 405
- parse_segment_cluster_block_group(): line 476
- parse_segment_track_entry(): lines 958, 973
- parse_private_codec_data(): line 1019
- generate_filename_from_track(): line 1167
- ass_ssa_sentence_erase_read_order(): line 1191
- save_sub_track(): lines 1264, 1271, 1303, 1310
- matroska_loop(): lines 1496, 1505

## Buffer overflow fixes (3 fixes)

- generate_timestamp_ass_ssa(): Increased buffer from 15 to 32 bytes,
  changed sprintf to snprintf. GCC warned output could be 11-23 bytes.
- save_sub_track(): Increased number[] buffer from 9 to 16 bytes,
  changed sprintf to snprintf.
- generate_filename_from_track(): Now calculates required buffer size
  dynamically instead of using fixed 200 bytes.

## Memory leak fixes (7 fixes)

- parse_ebml(): Fixed leak of read_vint_block_string() return value
- parse_segment_info(): Fixed 4 leaks of read_vint_block_string()
  returns (filename, title, muxing_app, writing_app)
- parse_segment_track_entry(): Added free(lang) before reassignment
- save_sub_track(): Fixed leak where text pointer was advanced,
  losing original allocation

## Realloc error handling (3 fixes)

Fixed realloc calls to use temporary variable, preventing loss of
original pointer if realloc fails:

- parse_segment_cluster_block_group_block(): line 366
- parse_segment_cluster_block_group(): line 475
- parse_segment_track_entry(): line 973

## Use-after-free fix (1 fix)

- matroska_loop(): Saved avc_track_number and dec_sub.got_output
  before calling matroska_free_all(), then used saved values

## Missing free fixes (2 fixes)

- free_sub_track(): Added free(track->sentences) for the array itself
- matroska_free_all(): Added free(mkv_ctx->sub_tracks) for the array

## Other improvements

- Initialized sub_track->sentences to NULL in parse_segment_track_entry()
  to ensure safe NULL check in free_sub_track()

All changes use EXIT_NOT_ENOUGH_MEMORY (exit code 500) for
out-of-memory conditions, consistent with the rest of the codebase.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(dvb_subtitle_decoder): add NULL checks after malloc calls

Add missing NULL checks for 9 malloc() calls in the DVB subtitle decoder
that could cause crashes or undefined behavior if memory allocation fails.

All checks use fatal(EXIT_NOT_ENOUGH_MEMORY, ...) to terminate gracefully
with an appropriate error message, consistent with the approach used in
matroska.c and other parts of the codebase.

Affected functions and allocations:
- dvbsub_init_decoder(): DVBSubContext allocation
- dvbsub_parse_clut_segment(): DVBSubCLUT allocation
- dvbsub_parse_region_segment(): DVBSubRegion, pbuf, DVBSubObject,
  and DVBSubObjectDisplay allocations
- dvbsub_parse_page_segment(): DVBSubRegionDisplay allocation
- write_dvb_sub(): cc_bitmap (rect), data1, and data0 allocations
- dvbsub_handle_display_segment(): private_data allocation

This also fixes a potential memory leak in write_dvb_sub() where rect
and rect->data1 would be leaked if the rect->data0 allocation failed
(previously returned -1 without cleanup, now terminates via fatal()).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-12 13:49:09 -08:00
Carlos Fernandez Sanz
b32c120e89 fix(matroska): add memory safety checks and fix memory leaks (#1792)
This commit addresses multiple memory safety issues in the Matroska
parser identified through static analysis (cppcheck).

## Null pointer dereference after malloc (15 fixes)

Added null checks after all malloc/calloc calls to prevent crashes
when memory allocation fails:

- read_byte_block(): line 28
- read_bytes_signed(): line 38
- generate_timestamp_ass_ssa(): line 267
- parse_segment_cluster_block_group_block(): lines 306, 361
- parse_segment_cluster_block_group_block_additions(): line 405
- parse_segment_cluster_block_group(): line 476
- parse_segment_track_entry(): lines 958, 973
- parse_private_codec_data(): line 1019
- generate_filename_from_track(): line 1167
- ass_ssa_sentence_erase_read_order(): line 1191
- save_sub_track(): lines 1264, 1271, 1303, 1310
- matroska_loop(): lines 1496, 1505

## Buffer overflow fixes (3 fixes)

- generate_timestamp_ass_ssa(): Increased buffer from 15 to 32 bytes,
  changed sprintf to snprintf. GCC warned output could be 11-23 bytes.
- save_sub_track(): Increased number[] buffer from 9 to 16 bytes,
  changed sprintf to snprintf.
- generate_filename_from_track(): Now calculates required buffer size
  dynamically instead of using fixed 200 bytes.

## Memory leak fixes (7 fixes)

- parse_ebml(): Fixed leak of read_vint_block_string() return value
- parse_segment_info(): Fixed 4 leaks of read_vint_block_string()
  returns (filename, title, muxing_app, writing_app)
- parse_segment_track_entry(): Added free(lang) before reassignment
- save_sub_track(): Fixed leak where text pointer was advanced,
  losing original allocation

## Realloc error handling (3 fixes)

Fixed realloc calls to use temporary variable, preventing loss of
original pointer if realloc fails:

- parse_segment_cluster_block_group_block(): line 366
- parse_segment_cluster_block_group(): line 475
- parse_segment_track_entry(): line 973

## Use-after-free fix (1 fix)

- matroska_loop(): Saved avc_track_number and dec_sub.got_output
  before calling matroska_free_all(), then used saved values

## Missing free fixes (2 fixes)

- free_sub_track(): Added free(track->sentences) for the array itself
- matroska_free_all(): Added free(mkv_ctx->sub_tracks) for the array

## Other improvements

- Initialized sub_track->sentences to NULL in parse_segment_track_entry()
  to ensure safe NULL check in free_sub_track()

All changes use EXIT_NOT_ENOUGH_MEMORY (exit code 500) for
out-of-memory conditions, consistent with the rest of the codebase.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-12 13:29:55 -08:00
Vidit
3d7553349f remove label -without-rust (#1780)
* fix minor issue

* remove -without-rust

* fixed
2025-12-09 20:38:55 +05:30
Rahul Tripathi
d524a0247f Merge pull request #2 from Rahul-2k4/copilot/fix-teletext-page-detection-issue-1034 2025-12-09 13:00:03 +05:30
copilot-swe-agent[bot]
f30f276456 Apply code style fixes from clang-format
Co-authored-by: Rahul-2k4 <216878448+Rahul-2k4@users.noreply.github.com>
2025-12-09 06:28:15 +00:00
copilot-swe-agent[bot]
17a8e1ec7b Remove unintended Cargo.lock changes
Co-authored-by: Rahul-2k4 <216878448+Rahul-2k4@users.noreply.github.com>
2025-12-09 06:23:19 +00:00
copilot-swe-agent[bot]
ebe25af476 Fix indentation to use tabs consistently
Co-authored-by: Rahul-2k4 <216878448+Rahul-2k4@users.noreply.github.com>
2025-12-09 06:16:17 +00:00
copilot-swe-agent[bot]
1f7120f32f Apply teletext page detection fix from fix branch
Co-authored-by: Rahul-2k4 <216878448+Rahul-2k4@users.noreply.github.com>
2025-12-09 06:15:23 +00:00
copilot-swe-agent[bot]
9e9023c258 Initial plan 2025-12-09 06:05:32 +00:00
Dhanush
b2930178be Fix G608 output extra NULL character (#1777) (#1786)
Co-authored-by: dhanush varma <dhanushvarma@dhanushs-MacBook-Air.local>
2025-12-08 20:37:29 -08:00
rudera-byte
759c3f5d41 fix: Issue #1162 TESSDATA_PREFIX requires path separator at its end (#1674) 2025-12-09 04:30:26 +05:30
moveman
3c51fb6536 Handle row_count decrease (#1702)
Co-authored-by: ewong <Edmond.Wong@harmonicinc.com>
Co-authored-by: Prateek Sunal <prtksunal@gmail.com>
Co-authored-by: Carlos Fernandez Sanz <carlos@ccextractor.org>
2025-12-09 04:19:13 +05:30
Deepnarayan Sett
494df3edae [FEAT] added demuxer and file_functions module (#1662)
* feat: added demuxer module

* Cargo Lock Update

* Completed file_functions and demuxer

* Completed file_functions and demuxer

* written extern functions for demuxer

* Removed libc completely, added tests for gxf and ported gxf to C

* Hardsubx error fixed

* Fixing format issues

* clippy errors fixed

* fixing format issues

* fixing format issues

* Windows failing tests

* Windows failing tests

* demuxer: added demuxer data transfer functions and removed some structs

* made Demuxer and File Functions

* Minor formatting changes

* Minor Rebasing changes

* demuxer: format rust and unit test rust checks

* C formatting

* Windows Failing test

* Windows Failing test

* Update CHANGES.TXT

* Update CHANGES.TXT

* Windows Failing Tests

* Windows Failing Tests

* Problem in Copy to Rust and some typos that copilot review suggested

* Minor Formatting Error

* Windows Failing Regressions

* Windows Failing Regressions

* Minor Comment Change

* Data transfer module for DemuxerData added and more rustlike syntax to ctorust.rs

* Minor Formatting Changes

* demuxer: Rebase and a few tweaks to file_functions

* demuxer: Minor Formatting Error

* [FIX] 134 Codes in XDS and General Tests (#1708)

* Made pointers valid in Unit Tests of Decoder

* fix: test_do_cb

* Copilot Suggestions

* Suggestions about Redundancy

* Suggestions about Redundancy

* [FEAT] Add `bitstream` module in `lib_ccxr` (#1649)

* feat: Add bitstream module

* run code formatters

* Run cargo clippy --fix

* Run cargo fmt --all

* refactor: remove rust pointer from C struct

* feat: Add bitstream module

* run code formatters

* Run cargo clippy --fix

* Run cargo fmt --all

* refactor: remove rust pointer from C struct

* Added Bitstream to libccxr_exports

* Minor Formatting Issue

* Bitstream: Removed redundant CType

* bitstream: recommended changes for is_byte_aligned

* bitstream: recommended changes for long comments

* bitstream: comment fix

* bitstream: removed redundant comparism comments

---------

Co-authored-by: Deepnarayan Sett <depnra1@gmail.com>
Co-authored-by: Deepnarayan Sett <71217129+steel-bucket@users.noreply.github.com>

* demuxer: minor formatting changes

* Demuxer: Changes to mistakes in CHANGES.txt

* Demuxer: Removed extra newline in ccextractor.c

* Demuxer: Changes to Encoding resolved

* Demuxer: Moved CCX_NOPTS to common structs and some changes to Demuxer Data regd. MPEG_CLOCK_FREQ

* some refactoring to CCX_NOPTS

* Demuxer: Minor Mistake regarding CHANGES.txt

* Demuxer: Unit test rust failing because of CCX_NOPTS

* Demuxer: changed common_structs to common_types

* Demuxer: Removed redundant libraries from Cargo.toml and moved tempfile to dev-dependencies

* Demuxer: Removed to_vec function and renamed PSIBuffer/PMTEntry from_ctype functions

* Demuxer:  Renamed Stream_Type, improved Time complexity of the default() function and removed redundant comments

* Demuxer:  Removed two repeated code blocks and removed redundant comments

* Demuxer:  Removed two code blocks

* Demuxer: Review Changes

* Demuxer: Removed redundant tests

* Update src/rust/src/demuxer/demux.rs

Co-authored-by: Prateek Sunal <prtksunal@gmail.com>

* Demuxer: Errors due to Rebase

* Demuxer: Removed get_stream_mode

* Demuxer: Errors due to rebasing and removing redundant CType Functions

* Demuxer: Failing ES regressions

* Demuxer: MythTV failing regression

* Demuxer: Removed redundant comments

* Demuxer: Unplugged ES for now

* Demuxer: Replugged in ES

* Demuxer: Formatting error

* Demuxer: Windows failing CI

* Demuxer: Windows failing CI

* Demuxer: Windows failing Regressions

* Demuxer: Formatting

* Demuxer: Minor Cargo Clippy change

* Demuxer: running regressions again

* Demuxer: Cargo Lockfile Change

* Demuxer: running regressions again

* Demuxer: running regressions again

---------

Co-authored-by: Swastik Patel <swastikpatel29@gmail.com>
Co-authored-by: Prateek Sunal <prtksunal@gmail.com>
2025-12-08 22:26:20 +05:30
Carlos Fernandez Sanz
810e02f7fa Fix Issue#1235: Sanitize XML comment to prevent invalid token errors (#1783)
Original description:

Pull Requests Description :
Added logic to detect and replace any occurrence of "--" in comments with a single "-" to ensure valid XML.
Used a bulk write ('fwrite') to efficiently handle portions of the string that don't contain invalid sequences.
Ensured that comments are written correctly without altering the original structure of the code.
Updated function 'write_spucomment' to handle the sanitization process efficiently.
2025-12-07 22:41:11 -08:00
dependabot[bot]
2720448e87 chore(deps): bump actions/checkout from 4 to 6 (#1766)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-07 18:54:15 -08:00
dependabot[bot]
5fceac5e90 chore(deps): bump actions/upload-artifact from 4 to 5 (#1757)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-07 18:53:35 -08:00
Carlos Fernandez Sanz
60ae6fb760 [FIX] Fix Windows build by updating vcpkg baseline and other packages (#1778)
* [FIX] Update vcpkg baseline and use forked rsmpeg for FFmpeg 7

Update vcpkg baseline from Feb 2024 to Dec 2025 to resolve libxml2
hash mismatch. GitLab regenerates archives dynamically, causing
SHA512 verification failures with old baselines.

Switch to CCExtractor's forked rsmpeg (github.com/CCExtractor/rsmpeg)
which pins rusty_ffmpeg to 0.16.4 for FFmpeg 7.1 compatibility.
This provides consistent FFmpeg 7 support across all platforms.

Changes:
- Update vcpkg baseline in workflow and vcpkg.json
- Use forked rsmpeg from git for all platforms
- Use ffmpeg7_1 feature instead of ffmpeg6/ffmpeg8
- Use link_vcpkg_ffmpeg for Windows

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Enable use_prebuilt_binding feature for rsmpeg

This ensures consistent FFmpeg 7 API signatures across all platforms,
regardless of the system FFmpeg version installed. Ubuntu's FFmpeg 6
has different function signatures than FFmpeg 7.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Standardize on FFmpeg 6.1.1 across all platforms

Use FFmpeg 6 consistently:
- Linux: uses apt packages (libavcodec-dev, etc.) which provide FFmpeg 6
- Windows: vcpkg baseline pinned to FFmpeg 6.1.1 (commit 5a58e645)
- macOS: uses system FFmpeg 6

This ensures consistent behavior and API compatibility across all platforms.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Use platform-appropriate FFmpeg versions

- Linux: FFmpeg 6 (from Ubuntu apt packages)
- Windows: FFmpeg 7 (from vcpkg with recent baseline)
- macOS: FFmpeg 7 (from Homebrew)

This fixes the Windows build which was failing due to vcpkg
baseline hash mismatch for libxml2 in older baselines.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Use FFmpeg 7 with prebuilt bindings for Linux

Use ffmpeg7 feature everywhere and use_prebuilt_binding for Linux
to ensure FFmpeg 7 API signatures regardless of system FFmpeg version.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix library names for Windows build with updated vcpkg

- Update leptonica library name from 1.83.1 to 1.85.0
- Update tesseract library name from tesseract53 to tesseract55 (v5.5.1)
- Update libiconv library names: charset.lib -> libcharset.lib, iconv.lib -> libiconv.lib

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix iconv library name for vcpkg static build

vcpkg libiconv for x64-windows-static produces only iconv.lib
with charset functionality bundled in, not separate libcharset.lib
and libiconv.lib files.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix iconv library names: use charset.lib and iconv.lib

Restores the correct vcpkg libiconv library names:
- charset.lib (libcharset library)
- iconv.lib (libiconv library)

These are the original names from vcpkg libiconv package for x64-windows-static.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* try: New Hash

Updated the builtin baseline hash for ccextractor.

* Remove charset.lib and iconv.lib from dependencies

The project has its own win_iconv.c implementation in src/thirdparty/win_iconv/
which provides iconv functionality. With the updated vcpkg baseline (ab2977be),
the libiconv library doesn't produce charset.lib or libcharset.lib files.

FFmpeg is also built with --disable-iconv in this vcpkg configuration, so
the external iconv libraries are not needed by any of the vcpkg dependencies.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Deepnarayan Sett <71217129+steel-bucket@users.noreply.github.com>
2025-12-07 13:20:41 -08:00
dhanush varma
c9d80e12b8 bump: update MSRV from 1.54.0 to 1.87.0
- Update all build configuration files to require Rust 1.87.0+
- Add clippy.toml with MSRV configuration as requested
- Maintain modern Rust features like is_multiple_of()
- Fixes build compatibility issue #1765
2025-11-23 00:10:04 +05:30
dhanush varma
a0aa9e4616 fix(rust): revert is_multiple_of to maintain MSRV 1.54.0
- Reverts is_multiple_of(2) to stable % 2 == 0 check to maintain
  compatibility with Rust 1.54.0 (project MSRV)
- Adds clippy.toml with msrv = '1.54.0' to prevent Clippy from
  suggesting APIs that aren't available in the MSRV

Fixes: #1765
2025-11-21 22:39:26 +05:30
dhanush varma
1515f5c1be build: add tesseract library linking for hardsubx feature
Fixes #1719 - build was failing with --enable-hardsubx due to missing
tesseract library linking. Added pkg_check_modules for tesseract and
leptonica in the HARDSUBX section of CMakeLists.txt.

Tested with: cmake -DWITH_HARDSUBX=ON -DWITH_OCR=ON -DWITH_FFMPEG=ON
2025-11-08 11:42:54 +05:30
Prateek Sunal
42d750950a [FIX] add mac-ocr-hardsubx workflow & ffmpeg variants support (#1745)
## Fix
- Update params and there doc

## Mac OS:
- Fix FFMpeg, tesseract compilation
- Re-add Mac os build hardsubx workflow

## FFMpeg used in workflow:
- MacOS: `8.*`
- Windows: `6.*` (pinned VCPKG supports this)
- Linux: `6.*` (Latest ubuntu runner supports this)
2025-11-03 23:47:42 +05:30
Deepnarayan Sett
5338c15f8d fix: Cargo Clippy failing on 1.91 (#1758) 2025-10-31 23:38:10 -07:00
Hridesh MG
ee232b5ded bump version 0.94 -> 0.95 (#1751) 2025-10-26 20:19:55 +05:30
pszemus
654d00a54e [FIX] Rust: fix unsetting source udp address when not specified by the user (#1750)
* Rust: fix unsetting source udp address when not specified by the user

* Rust: Fix `--udp [[src@]host:]port` parameter
2025-10-22 12:44:55 +05:30
pszemus
d86ee721df Rust: fix setting psm (#1752) 2025-10-22 12:44:45 +05:30
Chandragupt Singh
da03c1ec9d Fix ARM64 build: c_char initialization (#1756) 2025-10-22 12:44:34 +05:30
Deepnarayan Sett
ebd8252b88 Fix: Rust Clippy failing on 1.90 (#1753)
* Fix: Rust Clippy failing on 1.90

* Fix: Format Sourcecode in ES
2025-09-29 19:29:05 -07:00
rboy1
1c7e2a0995 [FIX] Fixed issue with cross compiling using MINGW-w64 (#1731)
* Fixed issue with cross compiling using MINGW-w64

* Update ts_tables_epg.c

* Update ccx_encoders_common.h

* Update ccx_common_platform.h

* Update ts_tables_epg.c

formatting changes a recommended by the clang test

---------

Co-authored-by: Prateek Sunal <prtksunal@gmail.com>
2025-09-13 23:08:14 +05:30
Hridesh MG
fb6a8301f6 fix: ocr luminance calculation fix (#1746) 2025-09-13 23:04:06 +05:30
pszemus
f2168b4c79 dockerfile: fix gpac version to 2.4.0 (#1747)
GPAC renamed its libraries to `libgpac.so.13` causing image build  to fail:

```
Error: building at STEP "COPY --from=builder /usr/local/lib/libgpac.so.12 /usr/local/lib/": checking on sources under "/home/pszemus/.local/share/containers/storage/overlay/faa4f2b5c39251a5cf42a97234d2d5652336a2388c96a64d85fc1922c4c43a71/merged": copier: stat: "/usr/local/lib/libgpac.so.12": no such file or directory
```
so let's fix the gpac version to the latest release (2.4.0)
2025-09-13 23:03:21 +05:30
Deepnarayan Sett
24f718427f [Rust] Fixes to Net Module (#1725)
* chore(cargo): Add dependencies

* feat: Create new module `net` in lib_ccxr

feat: Create new module `net` in lib_ccxr

* feat: Add block related functionality in `block.rs`

* feat: Add `target.rs` module for sending data blocks related functions

* feat(modules): Add all necessary modules

* feat: Add `source.rs` module for reading data blocks related functions from source

* feat: Add C equivalent functions in rust

* feat(module): Add `net` module in `libccxr_export`

* chore(cargo): Update Cargo.lock

* feat: Add C equivalent code in `libccxr_exports` & use in `networking.c`

* chore: Remove unused imports

* chore(clippy): Fix clippy warnings

* Net Module: Fixes in parser.rs - removed an extra check

* Net Module: Fixes in block.rs - fixed formatting issues

* Net Module: Fixes in source.rs - rewrote UDP implementation and a few other fixes

* Net Module: Fixes in target.rs - fixed formatting issues

* Net module: Rebasing and formatting changes

* Net module: Clashing names after rebase

* Net module: Clippy errors

---------

Co-authored-by: IshanGrover2004 <groverishan2004@gmail.com>
2025-09-06 22:11:17 +05:30
Deepnarayan Sett
c2a1f0d91f [Rust]Ported ES Module to Rust (#1736)
* Ported ES Module to Rust

* Windows Failing CI

* ES module: Clippy changes

* ES module: Cmake failing CI

* ES module: Cmake failing CI

* ES Module: Fixed mistake in read_gop_info

* ES Module: Minor mistakes in pic.rs and seq.rs

* ES Module: Goptime regression failing

* ES Module: Windows failing CI

* ES Module: ASCII value change in userdata.rs

* ES Module: Formatting issues
2025-09-06 22:11:03 +05:30
Deepnarayan Sett
12a27f34a0 [Rust]Ported AVC Module to Rust (#1730)
* AVC Module: ported AVC Module to Rust

* AVC module: Minor semantic changes

* AVC Module: Failing CI

* AVC Module: SIMD Optimisations

* AVC Module: Optimization in SEI

* AVC Module: removed panic
2025-09-06 20:18:20 +05:30
Deepnarayan Sett
ba59eb0887 [FEAT] Removed C code already ported to Rust (#1738)
* Removal: Removed redundant C code already ported to Rust

* Removal: C formatting

* Removal: More Removal and CI issues in Mac

* Removal: CI issues in Mac

* Removal: Changes due to Rebase

* Removal: Failing CI on mac

* Removal: Failing regression test on dvdraw
2025-09-06 20:16:39 +05:30
Hridesh MG
3f441150b4 Fix Hardsubx OCR (#1741)
* fix: hardsubx segmentation fault

* fix: hardsubx garbage output

* chore: enable hardsubx on test builds
2025-09-02 13:58:02 +05:30
Hridesh MG
f09b6ff446 fix: ocrlang argument not working (#1742) 2025-09-02 03:40:23 +05:30
Hridesh MG
8c23447d35 Merge pull request #1740 from hrideshmg/fix_windows_dvb
Fix DVB Regressions on windows
2025-09-02 03:17:44 +05:30
Deepnarayan Sett
4b5f68a6a4 [FEAT] Remove share module (#1737)
* replaced nanomsg with nanomsg_sys

* feat: Share Module - squash commits

* Share Module: Added Documentation

* Share Module: Removed Sharing Service

* Share: formatting issues

* Share: failing CI

* Share: failing CI

* Share: Removed protobuf

* Share Module: Update CHANGES.txt

* Share Module: Update Cargo.lock

* Share Module: Update CHANGES.txt

* Share Module: Update Cargo.toml

* Share Module: Update Cargo.toml
2025-08-24 23:23:44 +05:30
dmo
25a447d42e Fix build with ffmpeg 8 (#1739) 2025-08-24 23:22:21 +05:30
Hridesh MG
7eba462b67 fix: unicode encoding regression (#1733) 2025-08-24 20:40:10 +05:30
Hridesh MG
a34ba0f6b7 fix: rust bitstream segfault (#1732) 2025-08-24 20:37:30 +05:30
rboy1
1ac3f05765 [FIX] Regression bug failing to compile with ENABLE_FFMPEG (#1728)
* Fix hardsubx_decoder.c compilation with ENABLE_FFMPEG

Fix unresolved function reference when compiling with ENABLE_FFMPEG

* Fix regression compilation ffmpeg_intgr.c to support ffmpeg 5

Fix regression bug for compiling with ENABLE_FFMPEG and ffmpeg 5, introduced in https://github.com/CCExtractor/ccextractor/issues/1418

* Update CHANGES.TXT

* Update ffmpeg_intgr.c

Update for changes to FFMPEG 5 API
2025-08-24 20:34:39 +05:30
Hridesh MG
39e051b731 fix: dvd regressions (#1714)
* fix: dvd regressions

* chore: fix clippy errors
2025-08-18 20:07:10 +05:30
Hridesh MG
7d95b0574d fix: CEA-708 segmentation faults on MP4 files (#1729)
* fix: CEA-708 segmentation faults on MP4 files

* chore: fix clippy errors
2025-08-18 20:04:48 +05:30
Hridesh MG
6300bb7bca refactor: remove api structures (#1722)
* refactor: remove api structures

* docs: add change to changes.txt
2025-08-11 07:48:38 +05:30
Deepnarayan Sett
afde4d601f feat(rust): Added Encoder Module (#1710)
* Added Encoder Module

* Encoder: Windows Compatibility

* Encoder: C formatting

* Encoder: recommended changes to the encoding module - logic reduction

* Encoder: Minor stylistic change

* Encoder: Review changes, renamed Line21 to Ascii

* Encoder: Slight modification in C version of write_cc_buffer_as_simplexml

* Encoder: Renamed 2 files

* Encoder: Minor Capitalization Change

* Encoder: Review Suggestions
2025-08-06 14:44:13 +05:30
Ari1009
5a016d09b1 fix: MCC encoder 16-bit sequence 2025-07-29 13:25:09 +05:30
Hridesh MG
b63a29cd2e fix: elementary stream regressions 2025-07-24 12:36:14 +02:00
Swastik Patel
81fdecd5af [FEAT] Add bitstream module in lib_ccxr (#1649)
* feat: Add bitstream module

* run code formatters

* Run cargo clippy --fix

* Run cargo fmt --all

* refactor: remove rust pointer from C struct

* feat: Add bitstream module

* run code formatters

* Run cargo clippy --fix

* Run cargo fmt --all

* refactor: remove rust pointer from C struct

* Added Bitstream to libccxr_exports

* Minor Formatting Issue

* Bitstream: Removed redundant CType

* bitstream: recommended changes for is_byte_aligned

* bitstream: recommended changes for long comments

* bitstream: comment fix

* bitstream: removed redundant comparism comments

---------

Co-authored-by: Deepnarayan Sett <depnra1@gmail.com>
Co-authored-by: Deepnarayan Sett <71217129+steel-bucket@users.noreply.github.com>
2025-07-07 04:41:31 +05:30
Deepnarayan Sett
099fa059c7 [FIX] 134 Codes in XDS and General Tests (#1708)
* Made pointers valid in Unit Tests of Decoder

* fix: test_do_cb

* Copilot Suggestions

* Suggestions about Redundancy

* Suggestions about Redundancy
2025-07-07 04:38:45 +05:30
Hridesh MG
e663eca763 fix: XDS segmentation faults (#1707)
* fix: XDS segmentation faults

* fix: memory leaks in unit tests for service decoder
2025-06-29 20:12:47 -07:00
Hridesh MG
77b93e5ced fix: cargo tests failing on windows (#1704) 2025-06-29 23:07:09 +05:30
Deepnarayan Sett
2260165682 Fixed Clippy Errors on 1.88 (#1706) 2025-06-26 16:35:44 -07:00
Hridesh MG
715597e325 fix: trigger windows builds in PRs (#1705) 2025-06-26 16:34:38 -07:00
Hridesh MG
407d0f4e93 fix: windows builds not triggering on rust changes 2025-05-20 09:43:27 +02:00
Deepnarayan Sett
9d1718f85f Fix Unit Test Rust based on the new changes on Rust 1.86.0 (#1694) 2025-05-18 19:39:11 +05:30
Hridesh MG
5b327c78fa fix: replace iconv with encoding_rs 2025-05-04 23:00:08 +02:00
Yasser
17247daf8b [IMPROVEMENT] Refactor and optimize Dockerfile (#1696)
* [FIX] Corrected bitness check for 64-bit systems

* Improve Dockerfile: cleanup, parallel build, and remove redundancies
- Replaced cd with WORKDIR for clarity and Docker best practices.
- Removed unused LIB_CLANG_PATH export, as it only affected a single build layer; the library is automatically detected during build.
- Parallelized the GPAC build using make -j$(nproc).
- Removed redundant CMD instruction, as ENTRYPOINT already defines the container's execution command.

* [DOCS] Update CHANGES.TXT for Dockerfile improvements

---------

Co-authored-by: AhmedYasserrr <ahmdyasrj@gamil.com>
2025-04-27 11:30:25 -07:00
Vatsal Keshav
888ffa4ee0 fix prepoc dir for compilation on mac silicon - autogen, cmake, build.command (#1688)
Co-authored-by: vats004 <=>
2025-04-10 22:44:08 -07:00
Yasser
3851d24315 [FIX] Corrected bitness check for 64-bit systems (#1680)
Co-authored-by: AhmedYasserrr <ahmdyasrj@gamil.com>
2025-03-30 11:15:59 -07:00
Vatsal Keshav
e597f01994 fix(rust): replaced deprecated std::intrinsics with std::ptr (#1668) 2025-03-30 00:54:53 +05:30
tank0nf
b62027a0ae [FIX] Issue#1665 Enhanced Matroska Language Tag Handling (#1671)
* fix unknown element for IETF tag

* added documentation changes

* added formatting for clang-format
2025-03-23 00:12:23 -07:00
Hridesh MG
9685ad6149 [FIX] DVB OCR: Memory Leak & Quantization Issues (#1675)
* fix: do not free ocr text before return

* fix(OCR): erode and dilate function
2025-03-22 16:53:16 -07:00
Hridesh MG
d7231d4567 fix: CMake builds failing due to oudated corrosion (#1677) 2025-03-21 19:06:14 -07:00
Hridesh MG
a84256da01 fix: debugdvb arg typo (#1673) 2025-03-14 05:39:10 -07:00
jstrot
9e2a594bca fix(ocr_bitmap): out of buffer memory copying the "last font tag" & use memmove (#1586)
* ASAN: process_spu copies overlapping buffers

* ocr_bitmap: Make sure there is enough room for the last_font_tag

* Update CHANGES.TXT

* Baseline formatting fixes

* fixup! Baseline formatting fixes

* fixup! fixup! Baseline formatting fixes

* Fix rust comment formatting

* cxx_options.copy_from_rust: Avoid "mutable reference to mutable static" warning
2025-03-11 19:21:33 +05:30
Mohd Umar Khan
fc01fa05bd Update dockerfile (#1652)
added /usr for three libs
2025-03-09 16:41:54 -07:00
hjrgrn
9ea3c9fd41 [FIX] Fix vulnerability in url crate (#1670)
* Update url crate

* Fix vulnerability discovered with `cargo-audit` by upgrading `url` crate to version `2.5.4`

* Update url crate in lib_ccxr submodule

* Fix vulnerability discovered with `cargo-audit` by upgrading `url` crate to version `2.5.4`

* Update Cargo.toml

* Update Cargo.toml with latest compatible version of every crate
2025-03-09 16:40:43 -07:00
dmo
d276fb17f7 Add support leptonica >= 1.83 (#1645) 2025-03-01 12:36:33 -08:00
Vatsal Keshav
8c90bda9a2 fix : ccxr compilation on macos (#1661) 2025-02-23 10:48:49 -08:00
Punit Lodha
27e1a3c849 Pass raw pointer to avoid mut ref to global variable warning 2025-02-22 17:50:11 +01:00
canihavesomecoffee
0912ac8de0 fix: fix clippy warning/error in lib_ccxr 2025-02-22 11:55:39 +01:00
canihavesomecoffee
65a0348b4f fix: fix 2 rust clippy warnings/errors 2025-02-22 11:55:39 +01:00
canihavesomecoffee
564795cdd3 fix: reformat C code according to latest clang-format guidelines 2025-02-22 11:55:39 +01:00
tank0nf
ffe075b1f3 [IMPROVEMENT] Clarify CEA-608/708 Subtitle Extraction Behavior #1448 (#1663)
* made changes to the file src/lib_ccx/params.c

* made changes to the help message.
2025-02-14 08:20:36 -08:00
Colin Cogle
b08c5faa74 Fix compile-time issue involving implicit declaration of mapclut_paletee() (#1648)
* Fix implicit declaration error on some systems.

This commit fixes a compile-time error regarding an implicit declaration
of mapclut_paletee() on some compilers and compiler versions.  Notably,
Arch Linux and Ubuntu 24.10 seem to be affected.

The error resolved is:

```
../src/lib_ccx/ocr.c: In function 'ocr_rect':
../src/lib_ccx/ocr.c:922:9: error: implicit declaration of function 'mapclut_paletee' [-Wimplicit-function-declaration]
  922 |         mapclut_paletee(palette, alpha, (uint32_t *)rect->data1, rect->nb_colors);
      |         ^~~~~~~~~~~~~~~
```

This was resolved by `#include`-ing "ccx_encoders_spupng.h" in the file
src/lib_ccx/ocr.c.  Thanks to GitHub user @steel-bucket for sharing the
fix in this issue's comments.

Fixes: #1646

* Update CHANGES.TXT.

Mention the fix for #1646.

Fixes: #1646
2024-11-27 11:47:41 -08:00
Ishan Grover
cbd8e27fe3 [FEAT] Add timing module in lib_ccxr (#1640)
* feat: Add new module for timings functionality

* feat: Add timing functionality in `timing.rs` module

* feat: List all module & function conversion

* chore: Clippy fixes

* feat: Equivalent `ccx_common_timing.h` functions in rust module

* feat: Add static constants & include struct in `build.rs`

* feat: Add extern C functions

* feat: Include & use rust extern functions in C

* fix: Windows build

* fix: Windows build

---------

Co-authored-by: Prateek Sunal <prtksunal@gmail.com>
2024-09-14 11:50:21 +02:00
Neo2SHYAlien
349020ece9 Add flag for Page Segmentation Modes control (#1601)
* Add flag for Page Segmentation Modes control

I added an flag --psm for controlling PSM (Page Segmentation Modes) in Tesseract. The default option (3) gives me quite bad results. When I use 6, 11, or 12 for Bulgarian, it gives me much better OCR results. I haven't tested other languages yet, but I expect improvements as well if other mode is used.

* feat: add psm for rust parser

* fix: add psm to options

* fix: add default value of psm to 3

* fix: correct type of ocr oem

* fix(rust): use fatal! instead of exit

---------

Co-authored-by: Prateek Sunal <prtksunal@gmail.com>
2024-09-03 19:09:56 +02:00
Prateek Sunal
1a13bbb071 [FIX] Issues in Tests (#1638)
* fix: add ucla checks for millis_separator

* fix: reassign back profane and capitalization lists to c

* fix: C formatting

* fix(rust): clippy warnings
2024-09-02 22:09:17 +02:00
Prateek Sunal
90f9f0a183 [FEAT] add teletext and encoders_helpers module (#1635)
* create lib_ccxr and libccxr_exports

* add bits and levenshtein module

* add log module

* add encoding module

* add common constants module

* add time units module

* add options module

* add teletext module

* chore: remove outdated

* chore: update lock files

* chore: fix naming

* fix: reference to TeletextConfig

* fix: issue with ts_forced_program default value

* fix: use correct definition

* chore: lint warnings

* fix: example code

* fix(rust): adjust defaults, more accurate logging, use safe functions, add encoders_helper module

* fix: tests and formatting

* fix: allow hex values for streamtype

* chore: format files

* fix: naming of fields and docs

* fix: defaults for options

* fix: memory leak in vector to string

* fix(c): init logger before running parser

---------

Co-authored-by: Elbert Ronnie <elbert.ronniep@gmail.com>
2024-08-27 15:21:25 +05:30
Prateek Sunal
98a85e1be3 [rust] add options module (#1632)
* create lib_ccxr and libccxr_exports

* add log module

* add encoding module

* add common constants module

* add time units module

* add options module

* chore: update Cargo lock files

* fix: remove duplicacy

* fix: doc error

* fix: errors

* fix: remove time folder

* chore: lint fix

* chore: lint fix

* fix: errors

* fix: add time mod to utils

* fix: unreachable code

* fix: logging function

* chore: update lock file

* chore: remove duplicate comment

* feat: blend parser and options

* chore: lint fix

* chore: lint fix

* fix: imports

* fix: error in version

* chore: lint fixes

* chore: more lint fixes

* fix: error in svc

* chore: remove from options function

---------

Co-authored-by: Elbert Ronnie <elbert.ronniep@gmail.com>
2024-08-19 22:04:01 +05:30
dependabot[bot]
92f2ce0fa0 chore(deps): bump actions/cache from 3 to 4 (#1633)
Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-12 23:42:44 +05:30
Emily
b92ca87835 [IMPROVEMENT] Use Corrosion to build Rust code (#1630) 2024-08-12 16:35:32 +02:00
dependabot[bot]
8d4fdd7f3e Bump actions/cache from 3 to 4 (#1613)
Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-12 19:36:24 +05:30
dependabot[bot]
b679215752 Bump microsoft/setup-msbuild from 1.3.1 to 2.0.0 (#1614)
Bumps [microsoft/setup-msbuild](https://github.com/microsoft/setup-msbuild) from 1.3.1 to 2.0.0.
- [Release notes](https://github.com/microsoft/setup-msbuild/releases)
- [Changelog](https://github.com/microsoft/setup-msbuild/blob/main/building-release.md)
- [Commits](https://github.com/microsoft/setup-msbuild/compare/v1.3.1...v2.0.0)

---
updated-dependencies:
- dependency-name: microsoft/setup-msbuild
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-12 19:34:29 +05:30
Mykhailo Yavorskyi
25e8b3642d [IMPROVEMENT] Ignore version check on mxf essence container (#1631)
* Ignore version check on mxf essence container

* Fix codestyle

* Update Changelog
2024-08-11 14:08:26 -07:00
Ishan Grover
f8001ae295 [FEATURE] Create unit test for rust code (#1615)
* feat: Add new function to allocate any object to heap with zero allocated

* feat: Add unit tests for `decoder/commands.rs`

* docs: Mention about PR in changelogs

* feat: Add unit tests for `decoder/windows.rs`

Refactor the code and use Default where needed
Implement `PartialEq` also

* fix: Intialise tmp extern C values for easy mocking

* feat: Add unit tests for `decoder/timing.rs`

* feat: Add unit tests for `decoder/output.rs`

* feat: Add unit tests for `decoder/mod.rs`

* feat: Add unit tests for `decoder/tv_screen.rs`

* feat: Add unit tests for `lib.rs`

* fix: Failing test

* feat: [WIP] Add unit tests for `decoder/service_decoder.rs`

* feat: Add unit tests for `decoder/service_decoder.rs`

* feat: Add unit tests for `hardsubx/imgops.rs`

* feat: Add unit tests for `hardsubx/utility.rs`

* fix: cargo clippy

* fix: doctest for `lib_ccxr` module

* feat: Add test `lib_ccxr/util/mod.rs`

* feat: Add test `lib_ccxr/util/levenshtein.rs`

* feat: Add test `lib_ccxr/util/bits.rs`

* feat: Add test `lib_ccxr/time/units.rs`

* chore: Change function name

* fix: Failing of missing values `tlt_config`

* ci: Run unit test cases in `lib_ccxr` module also

* ci: Run clippy & fmt in `lib_ccxr` module also

* chore(clippy): Fix clippy warnings
2024-08-11 12:14:47 +02:00
Ishan Grover
5f9b395bc6 [FEAT] Add encoding module in lib_ccxr (#1628)
* feat: Add new module `encoding`

* feat: Add code for `encoding.rs`

A module for working with different kinds of text encoding formats

* feat: Add code for function `line21_to_utf8`

* feat: Add code for remaining todos function
2024-08-10 13:09:12 +02:00
Prateek Sunal
9340cc7df6 [rust] add parser (#1619)
* feat: unpack gpac

* fix: linux ci

* fix: mac build

* fix: remove unused [no ci]

* fix: ignore config.h [no ci]

* temp commit, will drop this soon

* fix: install gpac

* fix: gpac

* fix: formatting

* fix: preproccessor directive

* fix: comment display version for now

* fix: display dlls code

* fix: bundle vcruntime in hardsubx windows

* fix: again

* fix: erros in ci

* fix: ci

* fix: add vcruntime in additional dependencies

* fix: try to copy vcruntime after build

* fix: space in runtime library

* fix: remove for now [no ci]

* fix: things in vcxproj

* fix: ci for leptonica sys

* fix: docs

* fix: copy dlls on post build event

* fix: copy vcruntime after build

* feat: add arguments through clap

* fix: type of some arguments

* fix: "-" and "--" in comments

* fix: format files

* fix: add argument parsing till mkvlang

* fix: one todo item

* chore: lint fixes

* fix: nocodec value

* fix: for nocodec

* fix: add cfg feature for hardsubx

* feat: complete till startcreditstext

* fix: add more notes, args: option affect processed

* feat: port all till network stuff

* fix: complete almost all argument parsing

* fix: error free code

* fix: complete params port

* fix: hardsubx erros

* feat: clean up main function

* fix: pr reviews

* fix: make input,output function better

* fix: variant not used warning

* fix: warnings

* fix: all clippy warnings

* feat: add tests

* feat: add tests

* chore: lint fixes

* fix: move unit tests to correct folder

* fix: remove unncessary files

* fix: make function for parse_args

* fix: review changes

* fix: Impl CcxOptions whenever I could

* fix: try to convert rust to c

* chore: push c code

* fix: add more rust to c conversions

* fix: use set methods for bitfield

* fix: errors

* fix: arguments parsing

* fix: all issues

* fix: many errors

* chore: lint fix

* fix: err

* fix: unsafe function error

* fix: unsafe warning

* fix: safety lint

* chore: add docs

* fix: windows build

* fix: function

* fix: dependencies

* fix: set_binary_mode

* chore: lint fix

* fix: set_binary_mode for windows

* fix: error

* fix: undefined reference error

* chore: remove comment

* fix: output field

* chore: fix lint

* fix: ru1, ru2, ru3

* fix: undef before

* fix: parameter and update deps

* chore: update vcpkg

* feat: add release-with-debug profile

* fix; uncomment code

* fix: update visual studio to 2022

* chore: update docs

* fix: use default vcpkg

* fix: caching logic on release ci

* fix: vcpkg caching

* fix: add setup vcpkg

* chore: remove unneccesary formatting

* fix: Always write 2 bytes for UTF-16BE

* fix: formatting

* feat: add rest of the notes to bring continuity

* fix: remove extra line

* fix: add hardsubx note

* fix: source code format error

* chore: lint fixes acc to rustfmt

* feat: add unit test ci

* fix: conversion of strings, add file queue handling

* fix: decoder cfg

* fix: update dependencies

* chore: lint fix

* chore: add safety doc

* fix: default value for CcxOptions

* fix(rust): default value for teletext

* fix: leptonica version for windows

* fix: format errors

* fix: workflow

* Revert "fix: leptonica version for windows"

This reverts commit 461ef55e7b.

* fix: pin ffmpeg to 6 for mac

* fix(parser): default values and unwrap's

* fix(parser): hardsubx fixes

* chore(parse): lint fixes

* fix(windows): switch back to sdk 2019

* fix(workflow): windows workflow revert

* fix(windows): revert to old files which were working before

* fix(workflow): pin vcpkg packages

* chore(rust): downgrade leptonica

* fix(windows): move vcpkg.json to correct place

* fix(windows): improve vcxproj

* fix(windows): workflow

* fix(windows): workflow

* fix(windows): workflow clone from vcpkg everytime

* fix(workflow): error

* fix(workflow): don't skip building vcpkg

* fix: remove depth from vcpkg

* temporary commit

* fix(windows): pin gpac and use local vcpkg manifest properly

* fix(windows): install vcpkg dependencies manually

* fix(windows): update dll names

* fix(windows); dependencies copy

* fix(windows): don't continue on error for release

* fix(macos): build ffmpeg for mac workflow

* fix: move ffmpeg to current workspace

* fix: re-add profile for windows

* fix: pkg config for mac

* fix(mac): use ffmpeg@6 from brew

* fix(macos): there is no ffmpeg_prebuilt

* fix(macos): specify ffmpeg pkg config

* fix(macos): globally define pkg config

* fix(macos): add ffmpeg include and libs dir

* fix(macos): include ffmpeg headers in makefile

* fix: include ffmpeg libraries and include directories

* fix: try to manually specify ffmpeg header in rust

* fix: also include leptonica headres

* fix: leptonica name

* fix: test

* fix: string null when output_filename is empty

* fix: error

* fix: remove cflgas

* fix(mac): disable cmake ocr hardsubx

* chore: update gitignore

* fix: null if string is empty

* fix: allow --in

* chore: bump version to 1.0 in rust

* chore: add space to trigger sp

* fix: don't panic with rust

* fix: add double dashes to indicate parameters

* chore: update CHANGES.txt

* fix: test

* fix(workflow): update workflow name

* fix(rust): linux output_filename in sampleplatform

* fix(rust): parser default values

* fix(rust): exit with MalformedParameter instead of panic

* fix(decoder): revert always write 2 bytes

* chore(rust): format

* chore: update lock file

* fix(test): test lib_ccxr and rename to test

* fix(mac): remove failing cmake_ocr test

* fix: ci errors

* fix: feature related changes

* fix: trim down default features

* fix: don't check clippy for all features
2024-08-10 12:55:21 +02:00
Ishan Grover
90204d4cc6 [DOCS] Add C to Rust code migration guide (#1629)
* docs: Add c-to-migration guide docs

* docs: Update suggested typos in `docs/Rust_migration_guide.md`

Co-authored-by: Punit Lodha <48253287+PunitLodha@users.noreply.github.com>

---------

Co-authored-by: Punit Lodha <48253287+PunitLodha@users.noreply.github.com>
2024-08-07 12:08:24 +02:00
Ishan Grover
34bb9dd20d [FEATURE]: Create Docker image for CCExtractor (#1611)
* docs: Create a README for docker image usage

* docs: Update `COMPILATION.md` for adding docker instruction

* docs: Add detailed docker building & usage guide

* feat: Add dockerfile

* feat: Make dockerfile to build CCExtractor

* fix: dockerfile

* feat: Optimize docker image size

* docs: fix some commands usage

* docs: Mention docker image creation in CHANGES.txt

* docs: Update readme to remove dockerhub method
2024-07-16 20:17:57 -07:00
Ishan Grover
8d9bf42be2 [FEAT] Add time units module in lib_ccxr (#1623)
* chore: Add cargo dependencies

* feat: Make time module in `lib_ccxr`

* feat: Add conversion guide in `time/mod.rs` module & Create `units` module

* feat: Add time units code

* feat: Make time module in `lib_ccxr/util` & Add helper function

* feat: Add utils time related functions

* feat: Add extern functions in `libccxr_exports`

* feat: Add extern functions in C and use in proper place

* docs: Mention in Changelogs
2024-07-17 00:04:48 +02:00
Ishan Grover
8e4c07ed97 [FEAT] Add bits and levenshtein module in lib_ccxr (#1627)
* feat: Add 2 new modules

* feat: Add `levenshtein` module & code

* feat: Add `bits` module & code

* feat: Add `extern "C"` function which are equivalent in C-RUST

* feat: Call extern ccxr_ functions in C code

* docs: Mention in Changelogs
2024-07-16 20:00:15 +02:00
Ishan Grover
cf9c9dde53 [FEAT] Add constants module in lib_ccxr (#1624)
* feat: Add common module

common module is made for all `ccx_common_*` files

* feat: Add constants module within common module

Used to have all constants enums listed in ccx_common_constants C file

* feat: Add all constants, enums in rust equivaleent to `ccx_common_constansts` C file

* docs: Mention in Changelogs

* docs: Add more conversion data
2024-07-16 18:12:03 +02:00
Ishan Grover
f5da158935 [FEAT] Add log module in lib_ccxr (#1622)
* chore: Add bitflags crate as dependency

* feat: Add function to initialize Rust logger using options in C

* feat: Add new module `log`

* refactor: Add ccx_s_option into list of bindgen struct

* feat: Add Initialize logger function

* feat: All logging functions & macros

* chore: Fix clippy

* docs: Mention in Changelogs

* chore: format issue fix

* fix: Remove activity_header from rust & use initially to print in C

* refactor: Remove debugging statements

* fix: Add `\n` in info!
2024-07-16 17:45:24 +02:00
Ishan Grover
f12f12b916 [FEAT] Create lib_ccxr and libccxr_exports (#1621)
* create lib_ccxr and libccxr_exports

* chore: Fix bindgen crate version

* chore: Fix rsmpeg crate version

* docs: Add PR info in Changelogs

---------

Co-authored-by: Elbert Ronnie <elbert.ronniep@gmail.com>
2024-07-03 10:31:39 -07:00
Ishan Grover
d6ccf1bfcb [FEATURE] Port 708 decoder encoding module to RUST (#1607)
* feat: Add `decoder/encoding` new module

This `decoder/encoding.rs` file will contain the content of
`lib_ccx/ccx_708_decoder_encoding.c` file

* feat: Add encoding functions

* feat: Add conditional compilation to include Rust functions

* fix: conditional compilation logic

* refactor: Use of match statement instead of if-else

* fix: Calling C function for rust

* feat: Enable `derive_default` feature
2024-05-29 09:28:24 +02:00
Prateek Sunal
8e3b145477 [FIX (Windows)] CI build (#1612) 2024-05-28 21:13:05 +02:00
Ishan Grover
5748042f6d [FIX] Unexpected behavior of get_write_interval (#1609)
* fix: Unexpected behavior of get_write_interval

Adresses Issue#1606

* docs: Add changes to `CHANGES.TXT`
2024-05-24 11:20:48 -07:00
Sberm
3f504412f5 Add gpac package in compilation guide on Archlinux (#1605) 2024-04-04 21:07:39 -07:00
superbonaci
312d10c001 Update COMPILATION.MD: Add gpac-devel dependency for RHEL/Fedora (#1602) 2024-03-24 10:34:20 -07:00
Ishan Grover
f08febfd61 [FEATURE] Create linux AppImage for building CCExtractor (#1592)
* feat!: Add script for building AppImage

* chore(delete): Remove `build-static.sh` file

* refactor: Add link for logo photo

* chore: Replace dead link
2024-03-03 14:59:44 -08:00
Ishan Grover
89a12a7dd0 Bump rsmpeg to latest version for ffmpeg bindings (#1600)
* chore(deps): bump `rsmpeg` to latest version

* docs: Mention in CHANGES.TXT
2024-03-03 08:58:20 -08:00
Ishan Grover
2ada36d50e [FEATURE] Add SCC support to CEA-708 decoder (#1595)
* feat: Add timing functions for SCC format in C & Rust

* feat: Add SCC support to Rust 708 decoder

* feat: Add SCC support to C 708 decoder

* docs: fix symbol in scc_time format

* chore: clippy fixes

* docs: Add new feature in Changelog

* fix: update SCC timing functions according to need

* feat: Add new member(old caption end time) for overlapping situations

* fix: update SCC timing functions according to need

* feat: Add support for overlapping captions situations

* fix: frame formula for timings

* feat: Add support for orientation of subtitles in C

by adding necessary labels needed for it

* feat: Add support for orientation of subtitles in Rust

by adding necessary labels needed for it

* docs: Add info for scc labels

* chore: clippy fixes

* docs: Add what `add_needed_scc_labels` do and correct parameters name
2024-02-17 17:58:01 -08:00
dependabot[bot]
2d2a210c54 Bump actions/cache from 3 to 4 (#1589)
Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-04 20:02:21 +01:00
dependabot[bot]
deaa4a68e0 Bump microsoft/setup-msbuild from 1.3.1 to 2.0.0 (#1593)
Bumps [microsoft/setup-msbuild](https://github.com/microsoft/setup-msbuild) from 1.3.1 to 2.0.0.
- [Release notes](https://github.com/microsoft/setup-msbuild/releases)
- [Changelog](https://github.com/microsoft/setup-msbuild/blob/main/building-release.md)
- [Commits](https://github.com/microsoft/setup-msbuild/compare/v1.3.1...v2.0.0)

---
updated-dependencies:
- dependency-name: microsoft/setup-msbuild
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-04 19:59:52 +01:00
Prateek Sunal
f449d06cd1 chore: lint fixes acc to rustfmt (#1598) 2024-02-04 19:57:04 +01:00
Asher
c550726778 Typo in compilation docs (#1588)
* Typo in compilation docs

* [Fix] Deprecated leptonica name

With version 1.84.0, the library is changed from `liblept` to
`libleptonica`.
http://www.leptonica.org/source/version-notes.html
2024-01-15 00:50:36 -08:00
Prateek Sunal
bce63b88dc [FIX] Compatibility of Arguments in C (#1564)
* feat: breaking all parameters

* fix: some parameters

* fix: many things

* fix: error

* fix: -h

* fix: more parameters

* fix: add dash to help commands

* fix: help for output-field

* fix: single dash

* fix: --out and --in

* fix: move notes to the end of help menu

* fix: final changes to notes

* fix: extra spacing

* fix: wrong formatting of parenthesis
2024-01-14 09:47:13 -08:00
dependabot[bot]
63a259a313 Bump actions/checkout from 3 to 4 (#1567)
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-09 20:01:49 +01:00
dependabot[bot]
eef2591c25 Bump actions/upload-artifact from 3 to 4 (#1587)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-09 20:00:59 +01:00
dependabot[bot]
870e8bb6ac Bump AButler/upload-release-assets from 2.0 to 3.0 (#1577)
Bumps [AButler/upload-release-assets](https://github.com/abutler/upload-release-assets) from 2.0 to 3.0.
- [Release notes](https://github.com/abutler/upload-release-assets/releases)
- [Commits](https://github.com/abutler/upload-release-assets/compare/v2.0...v3.0)

---
updated-dependencies:
- dependency-name: AButler/upload-release-assets
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-08 19:33:21 +01:00
Vitaly Lysenkov
d2f17deb2c **[FIX]** fix infinite loop in MP4 file type detector and processor (#1566)
* Update stream_functions.c: fix MP4 file type detector

On bad inputs containing e.g. the following sequence of bytes within the first 1MiB "ff ff ff ff 6d 65 74 61" `detect_stream_type` was executing an infinite loop because "ff ff ff ff" was interpreted as a length of the candidate "meta" MP4 box, caused the size_t overflow inside `isValidMP4Box` which pointed `nextBoxLocation` to the previous byte and the execution flow processed the same "meta" again.

* Update CHANGES.TXT

* Treat a candidate MP4 box as invalid instead of bailing out

* Fix stuck mp4 processing in `process_avc_sample`

On corrupted inputs it could read data past the sample end and also get stuck in an infinite loop.

* Fix the stats code to not count zero-sized NALs and avoid dereferencing memory past the NAL end

* Add comment.

* Format changes
2024-01-08 19:30:14 +01:00
Om Thorat
376ff83161 [FIX] Compilation.md - Added a note for Ubuntu 23.10 (#1581)
* [FIX] Added a note for Ubuntu 23.10

libgpac-dev isn't available on Ubuntu 23.10 (Mantic) added a note instructing to build it from source instead.

* [FIX] Added build instructions for Ubuntu 23.10 and later

libgpac-dev isn't available in Ubuntu 23.10 and later, hence causing the build to fail. added the instructions to build it from source.
2023-12-11 05:26:06 -08:00
Prateek Sunal
79aaf86593 [FIX] #1549 Configure Script (#1574)
* fix: #1549 backticks

* fix: use single equal to
2023-10-23 07:24:48 -07:00
Prateek Sunal
280939df75 [FIX] Windows CI (#1568)
* fix: undef before

* chore: bump rust packages

* chore: update vcpkg
2023-09-12 15:30:52 +00:00
Prateek Sunal
af6308b167 [IMPROVEMENT] Mac CI (#1546)
* feat: unpack gpac

* fix: linux ci

* fix: mac build

* fix: remove unused [no ci]

* fix: ignore config.h [no ci]

* temp commit, will drop this soon

* fix: install gpac

* fix: gpac

* fix: formatting

* fix: preproccessor directive

* fix: comment display version for now

* fix: display dlls code

* fix: bundle vcruntime in hardsubx windows

* fix: again

* fix: erros in ci

* fix: ci

* fix: add vcruntime in additional dependencies

* fix: try to copy vcruntime after build

* fix: space in runtime library

* fix: remove for now [no ci]

* fix: things in vcxproj

* fix: ci for leptonica sys

* fix: docs

* fix: copy dlls on post build event

* fix: copy vcruntime after build

* feat: mac ci

* fix: ci dependencies

* fix: more depdendencies

* fix: libavcodec not found

* fix: include directories in mac

* fix: error in endif()
2023-08-18 20:16:45 +00:00
Prateek Sunal
aa4a76a941 [FEAT] Use system gpac library instead of vendoring gpacmp4 (#1535)
* feat: unpack gpac

* fix: linux ci

* fix: mac build

* fix: remove unused [no ci]

* fix: ignore config.h [no ci]

* temp commit, will drop this soon

* fix: install gpac

* fix: gpac

* fix: formatting

* fix: preproccessor directive

* fix: comment display version for now

* fix: display dlls code

* fix: bundle vcruntime in hardsubx windows

* fix: again

* fix: erros in ci

* fix: ci

* fix: add vcruntime in additional dependencies

* fix: try to copy vcruntime after build

* fix: space in runtime library

* fix: remove for now [no ci]

* fix: things in vcxproj

* fix: ci for leptonica sys

* fix: docs

* fix: copy dlls on post build event

* fix: copy vcruntime after build
2023-08-17 20:03:03 +00:00
Prateek Sunal
35e73c1c90 [FIX] Rename generic bitstream.h to cc_bitstream.h #1436 (#1543)
* fix: rename bitstream

* fix: update vcpkg commit hash

* fix: try to fix the linker error
2023-07-05 03:52:51 -07:00
Willem
5b7666965f Cleanup vs configs (#1539)
* Delete (probably) wrongly committed vs config file

* Remove Nuklear GUI

* Clean up SLN configs (Reduce to 64 bit full debug & release)

* Sync bat scripts, prepare to move

* Build rust in release when release

* Update changelog

* Delete rustx86.bat
2023-05-29 18:34:15 +00:00
Prateek Sunal
3efb2b1a68 [FIX] Update Windows build (#1540)
* fix: update windows ci

* fix: update docs for compilation

* fix: build runtime library
2023-05-22 15:08:52 +02:00
Elbert Ronnie
6bcc53ecf9 Provide unique values to enums (#1538) 2023-05-21 08:35:45 -07:00
Mohnish Deshpande
7b873e1902 Fix typo in ffmpeg_intgr.h (#1527) 2023-04-09 11:04:26 -07:00
Elbert Ronnie
005ef5a731 [FIX] Incorrect skipping of packets (#1528)
* don't skip entire packet on undefined window

* always clear packet before starting new one

* mention in CHANGES.TXT
2023-04-09 11:03:26 -07:00
Prateek Sunal
72e769b145 fix: update vcpkg ref (#1529) 2023-04-09 01:35:54 -07:00
Daniel Houck
cf2d207ba1 Fix McPoodle broadcast raw format output (#1523)
The broadcast raw format *must* contain data from onely one field, or
neither `ccextractor` nor McPoodle's tools can actually read it.  Since
we don't actually get XDS data from `writeraw`, there's no reason to
keep the call for field 2.
2023-03-30 08:08:34 -07:00
Elbert Ronnie
d768474e50 [FIX] encoding of solid block in latin-1 and unicode (#1522)
* Fix encoding of solid block in latin1 and unicode
2023-03-29 16:06:09 -07:00
Daniel Houck
4a7dd139ec [FIX] #1520 keep webvtt-full formatting in sync (#1521) 2023-03-27 16:24:00 -07:00
Chidam
fa85a5270d [FIX] #1516 in webvtt added support to two-three-four utf-8 bytes (#1518)
* in webvtt added support to two-three-four utf-8 bytes
2023-03-26 18:39:46 -07:00
Willem
7994096669 Apply formatting (again) (#1519) 2023-03-26 09:39:20 -07:00
Punit Lodha
d379d72685 Add avfilter for hardsubx (#1514) 2023-03-22 17:12:56 -07:00
Donough Liu
9b2215d9c2 hardsubx: Add missing -lavfilter for hardsubx linking (#1513) 2023-03-22 12:18:35 -07:00
Carlos Fernandez Sanz
29562759d2 Specify POSIX locale for numerics 2023-03-22 09:22:47 -07:00
Carlos Fernandez Sanz
0b6a8987ca Fix memory leak processing mp4 files with GPAC (with sample from #1410) 2023-03-21 21:47:57 -07:00
Carlos Fernandez Sanz
a679aadd3a Fix ocr.c writing outside allocated memory #1251 2023-03-21 21:25:15 -07:00
Carlos Fernandez Sanz
77b9696a37 Fix memory leaks (#1511) 2023-03-21 21:13:42 -07:00
Carlos Fernandez Sanz
f21d9e8737 Add address sanitizer on debug build 2023-03-21 20:06:20 -07:00
ziexess
fb3da4cd3a add erosion then dilation after quantization (#1510) 2023-03-21 14:01:59 -07:00
Prateek Sunal
b983de6a54 [IMPROVEMENT] Make Environment variables for Hardsubx optional (#1508)
* feat: automatically link ffmpeg

* fix: ci

* chore: documentation update for vcpkg and hardsubx

* fix: add ffmpeg5 feature

* fix: remove ffmpeg5 feature

* fix: update rsmpeg
2023-03-21 09:53:55 -07:00
Punit Lodha
260052b68c update compilation docs for hardsubx (#1507) 2023-03-20 07:06:39 -07:00
Apteryks
8105bc0b73 linux/configure.ac: Fix tesseract conditional problem. (#1504)
Fixes #1503.

Using tesseract-ocr's stock pkg-config, it would produce an error due to
unquoted whitespace:

  $ test ! -z `pkg-config --libs-only-l --silence-errors tesseract`
  bash: test: syntax error: `-larchive' unexpected

* linux/configure.ac: Use a positive test, and double-quote the $() command
substitution.

Co-authored-by: Carlos Fernandez Sanz <carlos@ccextractor.org>
2023-03-17 07:56:41 -07:00
Apteryks
ea4998f635 linux/Makefile.am: Add missing generated header. (#1505)
This header is generated by the pre-build.sh script.  The compilation
fails if it is missing.

* linux/Makefile.am (ccextractor_SOURCES): Add
../src/lib_ccx/compile_info_real.h.
2023-03-17 07:54:49 -07:00
Archit Bhonsle
cb496a7119 [IMPROVEMENT] getting rid of the warnings during rust builds (#1497) 2023-03-16 00:13:00 +01:00
Prateek Sunal
79958f7393 [IMPROVEMENT] Update documentation for windows build (#1498)
* fix: update instructions for FFMpeg on windows

* fix: update docs in COMPILATION.md

* fix: error in doc
2023-03-13 15:17:30 -07:00
Prateek Sunal
0264e7da2b [IMPROVEMENT] Update Rust and fix windows build (#1480)
* fix: bump leptonica-sys to 0.4.3 and update Cargo.lock

* fix: bump rust version to 1.57.0 and build vcpkg for window hardsubx builds

* fix: add Bcrypt dependency

* fix: switch to rust stable

* chore: bump package versions

* fix: try to remove i686 to fix error

* fix: install tesseract and lint fixes

* fix: try using ffmpeg the third

* fix: include headers

* fix: add rsmpeg

* fix: switch default triplet to static md

* fix: import errors

* fix: directory path

* fix: pre build commands

* fix: update vcxproj

* fix: linux ci

* fix: ci fixes

* chore: lint fixes

* fix: error

* fix: copy include files

* fix: ci error

* fix: link swresample lib

* fix: some errors

* fix: include directory path and include all libraries

* fix: try to add library directories

* fix: fixes in libraries

* fix: formatting ci

* fix: mflat errors

* fix: libcurl

* fix: preprocessor definitions

* fix: add libcrypto

* fix: remove lib_hash to fix conflicts (we have libcrypto already)

* fix: add avcodec and avformat dependencies on windows

* fix: add remaining deps that may fix the build

* fix: add crypt depdency

* fix: rename conflicting names

* Revert "fix: remove lib_hash to fix conflicts (we have libcrypto already)"

This reverts commit f57ff716ed.

* fix: prefix with CC_

* fix: post build actions

* fix: ocr error

* Revert "fix: ocr error"

This reverts commit 92599454b6.

* fix: xcopy error

* fix: generated file name for x64

* fix: ocr error

* fix: add item group at top to see if it works

* fix: remove unwanted headers, removed \\ from VCPKG_ROOT, remove unwanted includes in vcxproj

* fix: add libpng for non hardsubx, comment the broken ocr code again

* fix: libpng path

* feat: add lib png headers in ClCompile

* fix: png.h not found

* fix: last try for ocr fix

* fix: libpng not found

* fix: cl compile headers

* fix: libpng and ocr

* fix: libpng error

* fix: redefinition error

* fix: zlib for non hardsubx

* fix: lib names

* fix: zlib.h not found
2023-03-12 13:45:21 -07:00
Archit Bhonsle
257388bad3 reverting names of the secondary linux build scripts (#1496) 2023-03-12 11:23:28 -07:00
Archit Bhonsle
1604572995 [IMPROVEMENT] linux/build script revamp (#1494)
* improving `linux/build` script

* docs for the improved `linux/build` script
2023-03-12 08:38:06 -07:00
Ibrahim M. Akrab
9125165231 [FIX] tesseract 5.x traineddata location in ocr (#1493)
* fix traineddata location with tesseract version 5.x in ocr

* Add the fix to changelog
2023-03-10 11:14:36 -08:00
Prateek Sunal
b1cbfcea9b fix: ffmpeg 5 and tesseract 5 compatibility (#1479)
* fix: replace deprecated `codec` property with `codecpar`

* fix: replace deprecated method `avcodec_decode_video2` with `avcodec_receive_frame` and `avcodec_send_packet`

* Update CHANGES.TXT

* fix: remove deprecated `av_register_all` function

* fix: formatting

* fix: add support for tesseract 5

* fix: tesseract v5

* fix: hardsubx codec context error

* fix: lint const warning
2023-03-08 12:14:53 -08:00
Prateek Sunal
8bb52fa6d5 fix: broken -hardsubx flag (#1491) 2023-03-08 10:27:38 -08:00
Archit Bhonsle
7bd3f7e788 Adding Arch Linux instructions and other minor fixes to COMPILATION.MD (#1482) 2023-03-07 19:57:19 -08:00
Elbert Ronnie
f4bf40b05d Fix missing # in color attribute of font tag (#1486)
Co-authored-by: Elbert Ronnie <elbertronnie@gmail.com>
2023-03-07 11:01:21 -08:00
dependabot[bot]
b488126d09 Bump microsoft/setup-msbuild from 1.1.3 to 1.3.1 (#1475)
Bumps [microsoft/setup-msbuild](https://github.com/microsoft/setup-msbuild) from 1.1.3 to 1.3.1.
- [Release notes](https://github.com/microsoft/setup-msbuild/releases)
- [Changelog](https://github.com/microsoft/setup-msbuild/blob/main/building-release.md)
- [Commits](https://github.com/microsoft/setup-msbuild/compare/v1.1.3...v1.3.1)

---
updated-dependencies:
- dependency-name: microsoft/setup-msbuild
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-06 18:17:48 +00:00
Willem
1c6160f548 Run clang-format on all source files (#1465) 2022-12-14 22:17:57 +00:00
abhi-kr-2100
40145abccf [FIX] Fix issue #1453: Respect -stdout if multiple CC tracks are found in a Matroska input file (#1460)
* Respect `-stdout` if multiple CC tracks are found

When passed the `-stdout` flag, CCExtractor should write the
subtitles to standard output, instead of an output file.

However, as noted in Issue #1453, CCExtractor doesn't
respect the `-stdout` flag when multiple CC tracks are present in
a Matroska input file (usually .mkv).

This commit ensures that output is written to standard output if `-
stdout` is present even if the input file is a Matroska container
with multiple CC tracks.

Signed-off-by: Abhishek Kumar <abhi.kr.2100@gmail.com>

* Mention fixing of issue #1453 in changelog

Signed-off-by: Abhishek Kumar <abhi.kr.2100@gmail.com>

* Correctly spell Matroska

Signed-off-by: Abhishek Kumar <abhi.kr.2100@gmail.com>

Signed-off-by: Abhishek Kumar <abhi.kr.2100@gmail.com>
2022-12-14 13:46:16 -08:00
emkman99
492f0d5197 [FIX] WebVTT X-TIMESTAMP-MAP header placement (#1463) (#1464)
* [FIX] WebVTT X-TIMESTAMP-MAP header placement (#1463)
* Fixed --no-timestamp-map flag
* Disable X-TIMESTAMP-MAP by default
* X-TIMESTAMP-MAP is only part of the HLS spec, and is not valid WebVTT, so it should be disabled by default.
* Write second WebVTT newline when timing info is missing
2022-12-14 13:44:17 -08:00
dependabot[bot]
4b0928ad9b Bump microsoft/setup-msbuild from 1.0.2 to 1.1.3 (#1456)
Bumps [microsoft/setup-msbuild](https://github.com/microsoft/setup-msbuild) from 1.0.2 to 1.1.3.
- [Release notes](https://github.com/microsoft/setup-msbuild/releases)
- [Changelog](https://github.com/microsoft/setup-msbuild/blob/master/building-release.md)
- [Commits](https://github.com/microsoft/setup-msbuild/compare/v1.0.2...v1.1.3)

---
updated-dependencies:
- dependency-name: microsoft/setup-msbuild
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-01 09:38:16 +01:00
Shashwat Singh
0e3dfdc73b [WIP] Port hardsubx classifier (#1446)
* add tesseract-sys in dependencies of rust modules

* add appropriate feature flags and required packages to cargo toml

* expose classifier

* Redefine structs that are required for hardsubx

Note: rust-bindgen isn't being used directly for this because it will also redefine structures of leptonica, tesseract, and ffmpeg and we don't want that.
We want to use definitions of structs as in the rust interfact libraries we are importing

* write code to generate bindings for mprint

* - write a function to convert rust strings to c strings
- write a memory safe wrapper to mprint that uses above function

* - add helper function to deal with tess strings in a memory safe manner
- port get_ocr_text_simple
- port get_ocr_text_wordwise

* improve conversion of C string to Rust string by using built-in functions

* replace mprint usage with warn!

* port get_ocr_text_letterwise

* remove redundant mprint function

* improve readability _tess_string_helper by using more general variable names inside

* make get_ocr_text_simple call get_ocr_text_simple_threshold to remove redundant codefix bugs

* remove manual definition of cc_subtitle and use bindgen bindings

* style changes to rust hardsubx classifier

* add get_ocr_text_letterwise_threshold and make get_ocr_text_letterwise call it appropriately

* move hardsubx context struct to mod.rs

* add get_ocr_text_wordwise_threshold and make get_ocr_text_wordwise call it

* use the ffmpeg-sys definition of Pix

* hide ported functions under macros

* use the AVPacket from bindings and not ffmpeg to make compatibility work for now.
TODO: rewrite init_hardsubx and also deal with the ffmpeg stuff when that is done

* improce _tess_string_helper by using appropriate built-in functions

* linter recommended changes

* clang style change

* fix loop bug that didn't allow for re-evaluation of it on usage of continue statement

* start porting of decoder with the _process_frame_color_basic function and related code

* hide the C version of _process_frame_color_basic behind an #ifdef

* add _process_frame_tickertext

* hide the C version of _process_frame_tickertext behind ifdef and add #[no_mangle] to the rust version

* check if word is empty as soon as word is detected

* port _process_frame_white_basic

* hide the C version _process_frame_white_basic behind compiler macros

* stylistic changes

* safety docs for hardsubx classifier

* safety docs for decoder as of now

* safe docs for utils.rs

* style changes

* format and style changes

* modify safety docs

* formatting fix
2022-10-24 08:13:28 +02:00
Willem
4cb474c5a3 Update build_windows.yml 2022-07-18 20:54:40 +00:00
Willem
19f6ef43ef Update build_linux.yml 2022-07-18 20:51:22 +00:00
Willem
4dbcbe083e Update build_linux.yml 2022-07-18 20:50:15 +00:00
Willem
2a9a922d1a Update build_linux.yml 2022-07-18 20:46:50 +00:00
Willem
0d3e1d003d Update build_linux.yml
Try to fix bad behaviour for pushes
2022-07-18 20:43:26 +00:00
Shashwat Singh
170066f046 Port hardsubx utility (#1443)
* set up bindings conversion of hardsubx utility functions (and structs) and set up the module

* add low level ffmpeg rust binding

* Methods ported:

- convert_pts_to_ns
- convert_pts_to_ms
- convert_pts_to_s

A pure rust method was added called _edit_distance_rec that implements levenstein distance calculation using recursion and dynamic programming

The port of edit_distance_rec is simply a wrapper that calls above function.

This redundancy won't be nevessary as more downstream modules are ported to Rust

* put C code of hardsubx_utility under define rust flag

* run formatter

* make compilation of hardsubx rust modules conditional on the HARDSUBX and the OCR flags. Make ffmpeg a conditional dependency based on those flags

* remove namespaced dependency in cargo because that is a nightly feature

* add conditioal compilatio of ffmpeg related bindigs in build.rs

* make clang argument of -DENABLE_HARDSUBX conditional on cargo feature of hardsubx_ocr

* enable specific relevant features for ffmpeg-sys-next

* enable hardsubx_ocr feature in windows build

* add build feature in ffmpeg-sys-next

* ffmpeg build feature is conditional on platform

* Revert "ffmpeg build feature is conditional on platform"

This reverts commit e456fee942.

This is because conditional features do not work in cargo toml

* install yasm in the linux build github action for ocr and hardsubx enabled cmake

* turn globals to locals to reduce code

* remove redundant attributes

* style changes

* make import of ffmpeg-sys-next conditional on hardsubx_ocr flag

* add --all-features flag in clippy for github workflow

* run formatter

* fix clippy command

* install yasm as part of rust format build check

* install libtesseract-dev etc. for clippy build test

* readability change

* declare the function edit_distance as unsafe

* remove commented code

* formatting changes

* combine declaration and assignment

* add build command for building hardsubx rust

context to issue: #1445

* make hardsubx rust work with autoconf build. For issue: #1445

* update autoconf for mac for issue #1445
2022-07-13 14:36:30 +05:30
Punit Lodha
0bd213e789 Fix file extension for IDX files (#1444)
* Fix file extension

* Vobsub not supported

* Fix formatting

* More formatting

Co-authored-by: Punit Lodha <punitlodha@pm.com>
2022-07-09 19:04:01 +05:30
Carlos Fernandez Sanz
4712d85190 Maybe make format checker happy? 2022-07-05 14:05:17 -07:00
dependabot[bot]
d95a3b3354 Bump regex from 1.5.4 to 1.5.6 in /src/rust (#1440)
Bumps [regex](https://github.com/rust-lang/regex) from 1.5.4 to 1.5.6.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.5.4...1.5.6)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-18 11:23:03 +05:30
nikolabr
39724fe6a7 [FIX] Fix issue #1421 (#1431)
* [Fix] Fix issue #1421

* Fix header offset
2022-06-17 18:12:23 +00:00
Shashwat Singh
0f90afaa1b Port hardsubx imgops (#1439)
* add hardsubx rust module and expose it

* port rgb_to_hsv to rust

* add dependency fast-math and extern it

* port rgb_to_lab to rust

also make preprocessor to not allow compilation of hardsubx_imgops
if WITHOUT_RUST is OFF

* improve if-else constructs for readability

* unroll  macros that were only used once and remove their definition

* Improve readability of rgb_to_lab function (and fixes)

The function in Rust behaves slightly differently than its C counterpart

* remove fast math library, use palette library and rewrite imgops using it

* run formatter

* replace destructuring assignment statement with normal assignment statements because of build rust compiler issues

* run formatter on C code for imgops

* remove extern for modules because it is not required

* improve comment placement in rust imgops

Co-authored-by: Punit Lodha <48253287+PunitLodha@users.noreply.github.com>
2022-06-15 10:35:03 +05:30
Shashwat Singh
689d92ab59 put generated files of the rust project in the .gitignore (#1441) 2022-06-07 19:50:35 +00:00
dependabot[bot]
ca303d6942 Bump actions/upload-artifact from 2 to 3 (#1430)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2 to 3.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-11 09:48:03 +02:00
Shashwat Singh
6a9a16e611 add option to extract closed captions and burnt in subs in the same pass (#1422)
* [NEW] add functionality to allow extraction of cc and burnt-in subs in the same pass
- add flag under hardsubx called -hcc that calls this method
- minor refactoring of moving some code from general_loop to a new function
- appropriate addition to the header files to expose certain methods

* add change log

* run clang formatter
2022-03-27 07:51:23 -07:00
dependabot[bot]
30bc27aa0c Bump actions/cache from 2 to 3 (#1424)
Bumps [actions/cache](https://github.com/actions/cache) from 2 to 3.
- [Release notes](https://github.com/actions/cache/releases)
- [Commits](https://github.com/actions/cache/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-21 21:27:00 +00:00
Aditya Pratap Singh
c3fc323150 [IMPROVEMENT] Deprecated the --with-gui flag for linux/configure and mac/configure (#1415)
* Deprecated the --with-gui flag for linux/configure and mac/configure

* Update docs/CHANGES.TXT

Co-authored-by: Willem <github@canihavesome.coffee>

Co-authored-by: Willem <github@canihavesome.coffee>
2022-03-07 13:20:11 +01:00
Willem
b5fe0609fc Update build_windows.yml 2022-03-02 14:31:48 +01:00
Punit Lodha
0a4049c97c Fix clippy warning and Use rust 1.56.0 for CI (#1420)
* Fix cippy warning

* Use rust 1.56.0 for CI

Co-authored-by: Punit Lodha <punitlodha@pm.com>
2022-03-02 14:16:29 +01:00
dependabot[bot]
6e4ac56e9c Bump actions/checkout from 2.4.0 to 3 (#1419)
Bumps [actions/checkout](https://github.com/actions/checkout) from 2.4.0 to 3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2.4.0...v3)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-01 18:51:56 +00:00
Shashwat Singh
e6503d5c81 [FIX] segmentation fault when using hardsubx (#1417)
* Fix segmentation fault when using hardsubx
* initialize library before hardsubx call
2022-02-21 09:14:34 -08:00
Willem
1717cbb44d Update CHANGES.TXT 2022-01-24 17:54:00 +00:00
Arpan Kapoor
caa960e657 Fix #1407 (#1409) 2022-01-24 17:52:19 +00:00
Willem
290e2f10f9 Update debian.sh 2021-12-23 19:41:44 +00:00
Willem
325464f793 Update ccextractor.spec 2021-12-23 19:41:20 +00:00
Willem
f533a53902 Update PKGBUILD
Update PKGBUILD based on https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=ccextractor
2021-12-23 19:40:23 +00:00
Punit Lodha
97b381a2b0 Switch to rustc 1.56.0 (#1404)
* Update CHANGES.TXT

* Update release flow

* use 1.56.0 compiler as 1.57.0 is bugged

Co-authored-by: PunitLodha <punitlodha@pm.com>
2021-12-15 17:03:45 +00:00
Punit Lodha
03b0749e91 Update release flow (#1403)
* Update CHANGES.TXT

* Update release flow

Co-authored-by: PunitLodha <punitlodha@pm.com>
2021-12-15 16:41:11 +00:00
Carlos Fernandez Sanz
7bcdd6729f Bump version 0.93 -> 0.94 2021-12-14 09:46:01 -08:00
Punit Lodha
3dd3d5f6aa Update CHANGES.TXT (#1402)
Co-authored-by: PunitLodha <punitlodha@pm.com>
2021-12-14 09:37:23 -08:00
Ritesh Maurya
ba37cc41c8 Update COMPILATION.MD (#1401)
Most of the users use Ubuntu 18.04 and later, so added the `libtesseract-dev`  rather than `tesseract-ocr-dev` in the bash command so new people don't run into any errors as the NOTE was written after the command.
2021-12-13 08:29:53 -08:00
Punit Lodha
6efa41a7e6 Extract 708 subs by default (#1398)
* Extract 708 subs by default

* fix fmt
2021-12-05 06:21:34 -08:00
Manolis Miminas
9b90c91f07 Update COMPILATION.MD (#1397)
Add missing slash character.
2021-12-01 12:16:07 +01:00
Carlos Fernandez Sanz
35936618e3 Display explicit message if text:text is found 2021-11-21 10:16:07 -08:00
Carlos Fernandez Sanz
e98a584e98 Exit build if rust part fails 2021-11-21 09:31:05 -08:00
Punit Lodha
1a8c8a86f3 Check start/end at param before encoding DVB subs (#1396) 2021-11-21 07:13:48 -08:00
Punit Lodha
57663b8cf1 Fix Carriage Return command (#1394)
* Fix Carriage Return command

* fix fmt

* Fix rollup
2021-11-20 09:29:19 -08:00
Willem
2b3d759e20 Update CHANGES.TXT
Add links to GH issues for 2 improvements in new version
2021-11-20 16:25:27 +00:00
Punit Lodha
ed1b5dddce Update windows build (#1393)
* Compile rust in a pre-build event

* Add msbuild to windows compilation docs

* Update CHANGES.TXT
2021-11-14 10:03:39 -08:00
Punit Lodha
86fede6af8 Fix negative delay bug, and other miscellaneous changes (#1392)
* Add message for detected version

* Update rust build scripts for windows

* Fix bug with negative delay values

* fix formatting
2021-11-13 06:38:50 -08:00
dependabot[bot]
68e6390c76 Bump actions/checkout from 2.3.4 to 2.4.0 (#1388)
Bumps [actions/checkout](https://github.com/actions/checkout) from 2.3.4 to 2.4.0.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2.3.4...v2.4.0)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-10 07:03:06 +00:00
Hugh Mackworth
0ebeec4183 Repair Mac Build processes (#1390)
* Fix Mac Build processes

For all:
  Add Neon files to libpng for Apple Silicon
  Update compilation.md documentation

For autoconf:
  Make Linux and Mac Makefile.am and configure.ac identical
  Fix wrong location for zvbi/bcd.h in both Mac/Linux

For cmake::
  Include GPAC config for Darwin in Mac version

For mac/build.command:
  Update for new zvbi location

* Update CHANGES.TXT for Mac Build commit
2021-11-09 17:30:21 -08:00
Punit Lodha
8c10ded107 Add check for MSRV and update compilation docs (#1387)
* Add check for MSRV

* Update docs

* fix docs
2021-10-28 09:08:50 -07:00
Punit Lodha
3a1851f904 Make rust decoder default (#1375)
* Use rust by default and add -WITHOUT_RUST flag

* Fix for shell and autoconf builds

* change directory for version check

* change to  staticlib

* Update windows to build rust

* fix formatting

* add information about 708 decoder in version flag

* revert file mode to 644

* Use x86 for OCR releases

* fix flushing bug

* fix formatting

* update lib names

* remove bazel

* update changelog
2021-10-15 08:15:51 -07:00
Punit Lodha
50aceb45fb remove default BOM from windows (#1383)
* remove default BOM from windows

* update changelog
2021-10-08 15:30:54 -07:00
Willem
cad6b0495c Release flow improvements (#1381)
- Create .tar.gz for Linux that excludes the Windows & Git folders
- Create portable (zipped) version of CCExtractor (closes #1376)
2021-10-08 12:26:21 +02:00
Carlos Fernandez Sanz
c7ebd45d9f Version bump, 0.92 -> 0.93 2021-08-16 11:31:28 -07:00
Carlos Fernandez Sanz
77abe01885 Fix warning about using a keyword (new) as identifier 2021-08-16 11:30:59 -07:00
Punit Lodha
98cec31516 Rust updates:- Update documentation (#1374)
* Fix warning

* Update documentation

* Fix typo

* fmt
2021-08-14 08:44:23 -07:00
Jayesh Nirve
46b145a396 Update README.md (#1373) 2021-08-10 14:13:09 +02:00
570 changed files with 49904 additions and 264575 deletions

37
.dockerignore Normal file
View File

@@ -0,0 +1,37 @@
# Build artifacts
linux/ccextractor
linux/rust/
linux/*.o
linux/*.a
mac/ccextractor
mac/rust/
build/
build_*/
# Git
.git/
.github/
# IDE
.vscode/
.idea/
*.swp
*.swo
# Docker
docker/
# Documentation (not needed for build)
docs/
*.md
!README.md
# Test files
*.ts
*.mp4
*.mkv
*.srt
*.vtt
# Plans
plans/

157
.github/workflows/build_appimage.yml vendored Normal file
View File

@@ -0,0 +1,157 @@
name: Build Linux AppImage
on:
# Build on releases
release:
types: [published]
# Allow manual trigger
workflow_dispatch:
inputs:
build_type:
description: 'Build type (all, minimal, ocr, hardsubx)'
required: false
default: 'all'
# Build on pushes to workflow file for testing
push:
paths:
- '.github/workflows/build_appimage.yml'
- 'linux/build_appimage.sh'
jobs:
build-appimage:
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
build_type: [minimal, ocr, hardsubx]
steps:
- name: Check if should build this variant
id: should_build
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
INPUT_TYPE="${{ github.event.inputs.build_type }}"
if [ "$INPUT_TYPE" = "all" ] || [ "$INPUT_TYPE" = "${{ matrix.build_type }}" ]; then
echo "should_build=true" >> $GITHUB_OUTPUT
else
echo "should_build=false" >> $GITHUB_OUTPUT
fi
else
echo "should_build=true" >> $GITHUB_OUTPUT
fi
- name: Checkout repository
if: steps.should_build.outputs.should_build == 'true'
uses: actions/checkout@v6
- name: Install base dependencies
if: steps.should_build.outputs.should_build == 'true'
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
build-essential \
cmake \
pkg-config \
wget \
file \
libfuse2 \
zlib1g-dev \
libpng-dev \
libjpeg-dev \
libfreetype-dev \
libxml2-dev \
libcurl4-gnutls-dev \
libssl-dev \
clang \
libclang-dev
- name: Install OCR dependencies
if: steps.should_build.outputs.should_build == 'true' && (matrix.build_type == 'ocr' || matrix.build_type == 'hardsubx')
run: |
sudo apt-get install -y --no-install-recommends \
tesseract-ocr \
libtesseract-dev \
libleptonica-dev \
tesseract-ocr-eng
- name: Install FFmpeg dependencies (HardSubX)
if: steps.should_build.outputs.should_build == 'true' && matrix.build_type == 'hardsubx'
run: |
sudo apt-get install -y --no-install-recommends \
libavcodec-dev \
libavformat-dev \
libavutil-dev \
libswscale-dev \
libswresample-dev \
libavfilter-dev \
libavdevice-dev
- name: Install Rust toolchain
if: steps.should_build.outputs.should_build == 'true'
uses: dtolnay/rust-toolchain@stable
- name: Cache GPAC build
if: steps.should_build.outputs.should_build == 'true'
id: cache-gpac
uses: actions/cache@v5
with:
path: /usr/local/lib/libgpac*
key: gpac-v2.4.0-ubuntu22
- name: Build and install GPAC
if: steps.should_build.outputs.should_build == 'true' && steps.cache-gpac.outputs.cache-hit != 'true'
run: |
git clone -b v2.4.0 --depth 1 https://github.com/gpac/gpac
cd gpac
./configure
make -j$(nproc) lib
sudo make install-lib
sudo ldconfig
- name: Update library cache
if: steps.should_build.outputs.should_build == 'true'
run: sudo ldconfig
- name: Build AppImage
if: steps.should_build.outputs.should_build == 'true'
run: |
cd linux
chmod +x build_appimage.sh
BUILD_TYPE=${{ matrix.build_type }} ./build_appimage.sh
- name: Get AppImage name
if: steps.should_build.outputs.should_build == 'true'
id: appimage_name
run: |
case "${{ matrix.build_type }}" in
minimal)
echo "name=ccextractor-minimal-x86_64.AppImage" >> $GITHUB_OUTPUT
;;
ocr)
echo "name=ccextractor-x86_64.AppImage" >> $GITHUB_OUTPUT
;;
hardsubx)
echo "name=ccextractor-hardsubx-x86_64.AppImage" >> $GITHUB_OUTPUT
;;
esac
- name: Test AppImage
if: steps.should_build.outputs.should_build == 'true'
run: |
chmod +x linux/${{ steps.appimage_name.outputs.name }}
linux/${{ steps.appimage_name.outputs.name }} --version
- name: Upload AppImage artifact
if: steps.should_build.outputs.should_build == 'true'
uses: actions/upload-artifact@v6
with:
name: ${{ steps.appimage_name.outputs.name }}
path: linux/${{ steps.appimage_name.outputs.name }}
- name: Upload to Release
if: steps.should_build.outputs.should_build == 'true' && github.event_name == 'release'
uses: softprops/action-gh-release@v2
with:
files: linux/${{ steps.appimage_name.outputs.name }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

92
.github/workflows/build_docker.yml vendored Normal file
View File

@@ -0,0 +1,92 @@
name: Build CCExtractor Docker Images
on:
workflow_dispatch:
push:
paths:
- '.github/workflows/build_docker.yml'
- 'docker/**'
- '**.c'
- '**.h'
- 'src/rust/**'
pull_request:
types: [opened, synchronize, reopened]
paths:
- '.github/workflows/build_docker.yml'
- 'docker/**'
- '**.c'
- '**.h'
- 'src/rust/**'
jobs:
build_minimal:
name: Docker build (minimal)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build minimal image
uses: docker/build-push-action@v6
with:
context: .
file: docker/Dockerfile
build-args: |
BUILD_TYPE=minimal
USE_LOCAL_SOURCE=1
tags: ccextractor:minimal
load: true
cache-from: type=gha,scope=docker-minimal
cache-to: type=gha,mode=max,scope=docker-minimal
- name: Test minimal image
run: |
docker run --rm ccextractor:minimal --version
echo "Minimal build successful"
build_ocr:
name: Docker build (ocr)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build OCR image
uses: docker/build-push-action@v6
with:
context: .
file: docker/Dockerfile
build-args: |
BUILD_TYPE=ocr
USE_LOCAL_SOURCE=1
tags: ccextractor:ocr
load: true
cache-from: type=gha,scope=docker-ocr
cache-to: type=gha,mode=max,scope=docker-ocr
- name: Test OCR image
run: |
docker run --rm ccextractor:ocr --version
echo "OCR build successful"
build_hardsubx:
name: Docker build (hardsubx)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build HardSubX image
uses: docker/build-push-action@v6
with:
context: .
file: docker/Dockerfile
build-args: |
BUILD_TYPE=hardsubx
USE_LOCAL_SOURCE=1
tags: ccextractor:hardsubx
load: true
cache-from: type=gha,scope=docker-hardsubx
cache-to: type=gha,mode=max,scope=docker-hardsubx
- name: Test HardSubX image
run: |
docker run --rm ccextractor:hardsubx --version
echo "HardSubX build successful"

View File

@@ -1,6 +1,7 @@
name: Build CCExtractor on Linux
on:
workflow_dispatch:
push:
paths:
- '.github/workflows/build_linux.yml'
@@ -10,8 +11,6 @@ on:
- 'linux/**'
- 'package_creators/**'
- 'src/rust/**'
tags-ignore: # ignore push via new tag
- '*.*'
pull_request:
types: [opened, synchronize, reopened]
paths:
@@ -26,41 +25,47 @@ jobs:
build_shell:
runs-on: ubuntu-latest
steps:
- name: Install tesseract
run: sudo apt-get install libtesseract-dev
- uses: actions/checkout@v2.3.4
- name: Install dependencies
run: sudo apt update && sudo apt-get install libgpac-dev libtesseract-dev libavcodec-dev libavdevice-dev libx11-dev libxcb1-dev libxcb-shm0-dev
- uses: actions/checkout@v6
- name: build
run: ./build
run: ./build -hardsubx
working-directory: ./linux
- name: Display version information
run: ./linux/ccextractor --version
run: ./ccextractor --version
working-directory: ./linux
- name: Prepare artifacts
run: mkdir ./linux/artifacts
- name: Copy release artifact
run: cp ./linux/ccextractor ./linux/artifacts/
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v6
with:
name: CCExtractor Linux build
path: ./linux/artifacts
build_autoconf:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.3.4
- name: Install dependencies
run: sudo apt update && sudo apt-get install libgpac-dev
- uses: actions/checkout@v6
- name: run autogen
run: ./autogen.sh
working-directory: ./linux
- name: configure
run: ./configure
run: ./configure --enable-debug
working-directory: ./linux
- name: make
run: make
working-directory: ./linux
- name: Display version information
run: ./linux/ccextractor --version
run: ./ccextractor --version
working-directory: ./linux
cmake:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.3.4
- name: Install dependencies
run: sudo apt update && sudo apt-get install libgpac-dev
- uses: actions/checkout@v6
- name: cmake
run: mkdir build && cd build && cmake ../src
- name: build
@@ -71,32 +76,27 @@ jobs:
cmake_ocr_hardsubx:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.3.4
- name: dependencies
run: sudo apt update && sudo apt install libtesseract-dev libavformat-dev libswscale-dev
- uses: actions/checkout@v6
- name: Install dependencies
run: sudo apt update && sudo apt install libgpac-dev libtesseract-dev libavformat-dev libavdevice-dev libswscale-dev yasm
- name: cmake
run: mkdir build && cd build && cmake -DWITH_OCR=ON -DWITH_HARDSUBX=ON ../src
run: |
mkdir build && cd build
cmake -DWITH_OCR=ON -DWITH_HARDSUBX=ON ../src
- name: build
run: make -j$(nproc)
run: |
make -j$(nproc)
working-directory: build
- name: Display version information
run: ./build/ccextractor --version
bazel:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.3.4
- name: bazel build
working-directory: ./
run: bazel build //src:ccextractor --verbose_failures
- name: Display version information
working-directory: ./bazel-bin
run: ./src/ccextractor --version
build_rust:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.3.4
- name: Install dependencies
run: sudo apt update && sudo apt-get install libgpac-dev
- uses: actions/checkout@v6
- name: cache
uses: actions/cache@v2
uses: actions/cache@v5
with:
path: |
src/rust/.cargo/registry

173
.github/workflows/build_mac.yml vendored Normal file
View File

@@ -0,0 +1,173 @@
name: Build CCExtractor on Mac
on:
workflow_dispatch:
push:
paths:
- '.github/workflows/build_mac.yml'
- '**.c'
- '**.h'
- '**Makefile**'
- 'mac/**'
- 'package_creators/**'
- 'src/rust/**'
pull_request:
types: [opened, synchronize, reopened]
paths:
- '.github/workflows/build_mac.yml'
- '**.c'
- '**.h'
- '**Makefile**'
- 'mac/**'
- 'package_creators/**'
- 'src/rust/**'
jobs:
build_shell:
runs-on: macos-latest
steps:
- name: Install dependencies
run: brew install pkg-config autoconf automake libtool tesseract leptonica gpac
- uses: actions/checkout@v6
- name: build
run: ./build.command
working-directory: ./mac
- name: Display version information
run: ./ccextractor --version
working-directory: ./mac
- name: Prepare artifacts
run: mkdir ./mac/artifacts
- name: Copy release artifact
run: cp ./mac/ccextractor ./mac/artifacts/
- uses: actions/upload-artifact@v6
with:
name: CCExtractor mac build
path: ./mac/artifacts
build_shell_system_libs:
# Test building with system libraries via pkg-config (for Homebrew formula compatibility)
runs-on: macos-latest
steps:
- name: Install dependencies
run: brew install pkg-config autoconf automake libtool tesseract leptonica gpac freetype libpng protobuf-c utf8proc zlib
- uses: actions/checkout@v6
- name: build with system libs
run: ./build.command -system-libs
working-directory: ./mac
- name: Display version information
run: ./ccextractor --version
working-directory: ./mac
build_autoconf:
runs-on: macos-latest
steps:
- uses: actions/checkout@v6
- name: Install dependencies
run: brew install pkg-config autoconf automake libtool gpac
- name: run autogen
run: ./autogen.sh
working-directory: ./mac
- name: configure
run: ./configure --enable-debug
working-directory: ./mac
- name: make
run: make
working-directory: ./mac
- name: Display version information
run: ./ccextractor --version
working-directory: ./mac
cmake:
runs-on: macos-latest
steps:
- uses: actions/checkout@v6
- name: dependencies
run: brew install gpac
- uses: actions/checkout@v6
- name: cmake
run: mkdir build && cd build && cmake ../src
- name: build
run: make -j$(nproc)
working-directory: build
- name: Display version information
run: ./build/ccextractor --version
cmake_ocr_hardsubx:
runs-on: macos-latest
steps:
- uses: actions/checkout@v6
- name: Install dependencies
run: brew install pkg-config autoconf automake libtool tesseract leptonica gpac ffmpeg
- name: cmake
run: |
mkdir build && cd build
cmake -DWITH_OCR=ON -DWITH_HARDSUBX=ON ../src
- name: build
run: |
make -j$(nproc)
working-directory: build
- name: Display version information
run: ./build/ccextractor --version
build_shell_hardsubx:
# Test build.command with -hardsubx flag (burned-in subtitle extraction)
runs-on: macos-latest
steps:
- name: Install dependencies
run: brew install pkg-config autoconf automake libtool tesseract leptonica gpac ffmpeg
- uses: actions/checkout@v6
- name: build with hardsubx
run: ./build.command -hardsubx
working-directory: ./mac
- name: Display version information
run: ./ccextractor --version
working-directory: ./mac
- name: Verify hardsubx support
run: |
# Check that -hardsubx is recognized (will fail if not compiled in)
./ccextractor -hardsubx --help 2>&1 | head -20 || true
working-directory: ./mac
build_autoconf_hardsubx:
# Test autoconf build with HARDSUBX enabled (fixes issue #1173)
runs-on: macos-latest
steps:
- uses: actions/checkout@v6
- name: Install dependencies
run: brew install pkg-config autoconf automake libtool tesseract leptonica gpac ffmpeg
- name: run autogen
run: ./autogen.sh
working-directory: ./mac
- name: configure with hardsubx
run: |
# Set Homebrew paths for configure to find libraries
export HOMEBREW_PREFIX="$(brew --prefix)"
export LDFLAGS="-L${HOMEBREW_PREFIX}/lib"
export CPPFLAGS="-I${HOMEBREW_PREFIX}/include"
export PKG_CONFIG_PATH="${HOMEBREW_PREFIX}/lib/pkgconfig"
./configure --enable-hardsubx --enable-ocr
working-directory: ./mac
- name: make
run: make
working-directory: ./mac
- name: Display version information
run: ./ccextractor --version
working-directory: ./mac
- name: Verify hardsubx support
run: |
# Check that -hardsubx is recognized
./ccextractor -hardsubx --help 2>&1 | head -20 || true
working-directory: ./mac
build_rust:
runs-on: macos-latest
steps:
- uses: actions/checkout@v6
- name: cache
uses: actions/cache@v5
with:
path: |
src/rust/.cargo/registry
src/rust/.cargo/git
src/rust/target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-cargo-
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- name: build
run: cargo build
working-directory: ./src/rust

View File

@@ -1,98 +1,131 @@
name: Build CCExtractor on Windows
env:
RUSTFLAGS: -Ctarget-feature=+crt-static
VCPKG_DEFAULT_TRIPLET: x64-windows-static
VCPKG_DEFAULT_BINARY_CACHE: C:\vcpkg\.cache
VCPKG_COMMIT: ab2977be50c702126336e5088f4836060733c899
on:
workflow_dispatch:
push:
paths:
- '.github/workflows/build_windows.yml'
- '**.c'
- '**.h'
- 'windows/**'
tags-ignore: # ignore push via new tag
- '*.*'
- ".github/workflows/build_windows.yml"
- "**.c"
- "**.h"
- "windows/**"
- "src/rust/**"
pull_request:
types: [opened, synchronize, reopened]
paths:
- '.github/workflows/build_windows.yml'
- '**.c'
- '**.h'
- 'windows/**'
- ".github/workflows/build_windows.yml"
- "**.c"
- "**.h"
- "windows/**"
- "src/rust/**"
jobs:
build_non_ocr_release:
runs-on: windows-latest
build_release:
runs-on: windows-2022
steps:
- name: Check out repository
uses: actions/checkout@v2.3.4
- name: Setup MSBuild.exe
uses: microsoft/setup-msbuild@v1.0.2
- name: build Release
run: msbuild ccextractor.sln /p:Configuration=Release
working-directory: ./windows
- name: Display version information
run: ./ccextractorwin.exe --version
working-directory: ./windows/Release
- uses: actions/upload-artifact@v2
with:
name: CCExtractor Windows Non-OCR Release build
path: |
./windows/Release/ccextractorwin.exe
./windows/Release/*.dll
build_non_ocr_debug:
runs-on: windows-latest
- name: Check out repository
uses: actions/checkout@v6
- name: Setup MSBuild.exe
uses: microsoft/setup-msbuild@v2.0.0
with:
msbuild-architecture: x64
- name: Install gpac
run: choco install gpac --version 2.4.0
- name: Setup vcpkg
run: mkdir C:\vcpkg\.cache
- name: Cache vcpkg
id: cache
uses: actions/cache@v5
with:
path: |
C:\vcpkg\.cache
key: vcpkg-${{ runner.os }}-${{ env.VCPKG_COMMIT }}
- name: Build vcpkg
run: |
git clone https://github.com/microsoft/vcpkg
./vcpkg/bootstrap-vcpkg.bat
- name: Install dependencies
run: ${{ github.workspace }}/vcpkg/vcpkg.exe install --x-install-root ${{ github.workspace }}/vcpkg/installed/
working-directory: windows
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- name: Install Win 10 SDK
uses: ilammy/msvc-dev-cmd@v1
- name: build Release-Full
env:
LIBCLANG_PATH: "C:\\Program Files\\LLVM\\lib"
LLVM_CONFIG_PATH: "C:\\Program Files\\LLVM\\bin\\llvm-config"
CARGO_TARGET_DIR: "..\\..\\windows"
BINDGEN_EXTRA_CLANG_ARGS: -fmsc-version=0
VCPKG_ROOT: ${{ github.workspace }}/vcpkg
run: msbuild ccextractor.sln /p:Configuration=Release-Full /p:Platform=x64
working-directory: ./windows
- name: Display version information
run: ./ccextractorwinfull.exe --version
working-directory: ./windows/x64/Release-Full
- uses: actions/upload-artifact@v6
with:
name: CCExtractor Windows Release build
path: |
./windows/x64/Release-Full/ccextractorwinfull.exe
./windows/x64/Release-Full/*.dll
build_debug:
runs-on: windows-2022
steps:
- name: Check out repository
uses: actions/checkout@v2.3.4
- name: Setup MSBuild.exe
uses: microsoft/setup-msbuild@v1.0.2
- name: build Debug
run: msbuild ccextractor.sln /p:Configuration=Debug
working-directory: ./windows
- name: Display version information
run: ./ccextractorwin.exe --version
working-directory: ./windows/Debug
- uses: actions/upload-artifact@v2
with:
name: CCExtractor Windows Non-OCR Debug build
path: |
./windows/Debug/ccextractorwin.exe
./windows/Debug/ccextractorwin.pdb
./windows/Debug/*.dll
build_ocr_hardsubx_release:
runs-on: windows-latest
steps:
- name: Check out repository
uses: actions/checkout@v2.3.4
- name: Setup MSBuild.exe
uses: microsoft/setup-msbuild@v1.0.2
- name: build Release
run: msbuild ccextractor.sln /p:Configuration=Release-Full
working-directory: ./windows
- name: Display version information
run: ./ccextractorwinfull.exe --version
working-directory: ./windows/Release-Full
- uses: actions/upload-artifact@v2
with:
name: CCExtractor Windows OCR and HardSubX Release build
path: |
./windows/Release-Full/ccextractorwinfull.exe
./windows/Release-Full/*.dll
build_ocr_hardsubx_debug:
runs-on: windows-latest
steps:
- name: Check out repository
uses: actions/checkout@v2.3.4
- name: Setup MSBuild.exe
uses: microsoft/setup-msbuild@v1.0.2
- name: build Debug
run: msbuild ccextractor.sln /p:Configuration=Debug-Full
working-directory: ./windows
- name: Display version information
run: ./ccextractorwinfull.exe --version
working-directory: ./windows/Debug-Full
- uses: actions/upload-artifact@v2
with:
name: CCExtractor Windows OCR and HardSubX Debug build
path: |
./windows/Debug-Full/ccextractorwinfull.exe
./windows/Debug-Full/ccextractorwinfull.pdb
./windows/Debug-Full/*.dll
- name: Check out repository
uses: actions/checkout@v6
- name: Setup MSBuild.exe
uses: microsoft/setup-msbuild@v2.0.0
with:
msbuild-architecture: x64
- name: Install gpac
run: choco install gpac --version 2.4.0
- name: Setup vcpkg
run: mkdir C:\vcpkg\.cache
- name: Cache vcpkg
id: cache
uses: actions/cache@v5
with:
path: |
C:\vcpkg\.cache
key: vcpkg-${{ runner.os }}-${{ env.VCPKG_COMMIT }}
- name: Build vcpkg
run: |
git clone https://github.com/microsoft/vcpkg
./vcpkg/bootstrap-vcpkg.bat
- name: Install dependencies
run: ${{ github.workspace }}/vcpkg/vcpkg.exe install --x-install-root ${{ github.workspace }}/vcpkg/installed/
working-directory: windows
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- name: Install Win 10 SDK
uses: ilammy/msvc-dev-cmd@v1
- name: build Debug-Full
env:
LIBCLANG_PATH: "C:\\Program Files\\LLVM\\lib"
LLVM_CONFIG_PATH: "C:\\Program Files\\LLVM\\bin\\llvm-config"
CARGO_TARGET_DIR: "..\\..\\windows"
BINDGEN_EXTRA_CLANG_ARGS: -fmsc-version=0
VCPKG_ROOT: ${{ github.workspace }}/vcpkg
run: msbuild ccextractor.sln /p:Configuration=Debug-Full /p:Platform=x64
working-directory: ./windows
- name: Display version information
continue-on-error: true
run: ./ccextractorwinfull.exe --version
working-directory: ./windows/x64/Debug-Full
- uses: actions/upload-artifact@v6
with:
name: CCExtractor Windows Debug build
path: |
./windows/x64/Debug-Full/ccextractorwinfull.exe
./windows/x64/Debug-Full/ccextractorwinfull.pdb
./windows/x64/Debug-Full/*.dll

View File

@@ -19,33 +19,39 @@ jobs:
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.3.4
- uses: actions/checkout@v6
- name: Format code
run: |
find src/ -type f -not -path "src/thirdparty/*" -not -path "src/lib_ccx/zvbi/*" -name '*.c' -not -path "src/GUI/icon_data.c" | xargs clang-format -i
git diff-index --quiet HEAD -- || (git diff && exit 1)
format_rust:
runs-on: ubuntu-latest
strategy:
matrix:
workdir: ['./src/rust', './src/rust/lib_ccxr']
defaults:
run:
working-directory: ./src/rust
working-directory: ${{ matrix.workdir }}
steps:
- uses: actions/checkout@v2.3.4
- uses: actions/checkout@v6
- name: cache
uses: actions/cache@v2
uses: actions/cache@v5
with:
path: |
src/rust/.cargo/registry
src/rust/.cargo/git
src/rust/target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
${{ matrix.workdir }}/.cargo/registry
${{ matrix.workdir }}/.cargo/git
${{ matrix.workdir }}/target
key: ${{ runner.os }}-cargo-${{ hashFiles('${{ matrix.workdir }}/Cargo.lock') }}
restore-keys: ${{ runner.os }}-cargo-
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
components: rustfmt, clippy
- name: dependencies
run: sudo apt update && sudo apt install libtesseract-dev libavformat-dev libavdevice-dev libswscale-dev yasm
- name: rustfmt
run: cargo fmt --all -- --check
- name: clippy
run: cargo clippy -- -D warnings
run: |
cargo clippy -- -D warnings

View File

@@ -5,28 +5,73 @@ on:
types:
- created
permissions:
contents: write
env:
RUSTFLAGS: -Ctarget-feature=+crt-static
VCPKG_DEFAULT_TRIPLET: x64-windows-static
VCPKG_DEFAULT_BINARY_CACHE: C:\vcpkg\.cache
VCPKG_COMMIT: ab2977be50c702126336e5088f4836060733c899
jobs:
build_windows:
runs-on: windows-latest
runs-on: windows-2022
steps:
- name: Check out repository
uses: actions/checkout@v2.3.4
uses: actions/checkout@v6
- name: Get the version
id: get_version
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\/v/}
run: |
# Extract version from tag, strip 'v' prefix and everything after first dash
VERSION=${GITHUB_REF/refs\/tags\/v/}
VERSION=${VERSION%%-*}
echo ::set-output name=VERSION::$VERSION
shell: bash
- name: Setup MSBuild.exe
uses: microsoft/setup-msbuild@v1.0.2
- name: build Release
run: msbuild ccextractor.sln /p:Configuration=Release-Full
uses: microsoft/setup-msbuild@v2.0.0
with:
msbuild-architecture: x64
- name: Install gpac
run: choco install gpac --version 2.4.0
- name: Setup vcpkg
run: mkdir C:\vcpkg\.cache
- name: Cache vcpkg
id: cache
uses: actions/cache@v5
with:
path: |
C:\vcpkg\.cache
key: vcpkg-${{ runner.os }}-${{ env.VCPKG_COMMIT }}
- name: Build vcpkg
run: |
git clone https://github.com/microsoft/vcpkg
./vcpkg/bootstrap-vcpkg.bat
- name: Install dependencies
run: ${{ github.workspace }}/vcpkg/vcpkg.exe install --x-install-root ${{ github.workspace }}/vcpkg/installed/
working-directory: windows
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- name: Install Win 10 SDK
uses: ilammy/msvc-dev-cmd@v1
- name: build Release-Full
env:
LIBCLANG_PATH: "C:\\Program Files\\LLVM\\lib"
LLVM_CONFIG_PATH: "C:\\Program Files\\LLVM\\bin\\llvm-config"
CARGO_TARGET_DIR: "..\\..\\windows"
BINDGEN_EXTRA_CLANG_ARGS: -fmsc-version=0
VCPKG_ROOT: ${{ github.workspace }}/vcpkg
run: msbuild ccextractor.sln /p:Configuration=Release-Full /p:Platform=x64
working-directory: ./windows
- name: Copy files to directory for installer
run: mkdir installer; cp ./Release-Full/ccextractorwinfull.exe ./installer; cp ./Release-Full/*.dll ./installer
run: mkdir installer; cp ./x64/Release-Full/ccextractorwinfull.exe ./installer; cp ./x64/Release-Full/*.dll ./installer
working-directory: ./windows
- name: install WiX
run: dotnet tool install --global wix --version 4.0.0-preview.0 && wix extension -g add WixToolset.UI.wixext
run: dotnet tool uninstall --global wix; dotnet tool install --global wix --version 6.0.2 && wix extension add -g WixToolset.UI.wixext/6.0.2
- name: Make sure WiX works
run: wix --version && wix extension -g list
run: wix --version && wix extension list -g
- name: Download Flutter GUI
run: ((Invoke-WebRequest -UseBasicParsing https://api.github.com/repos/CCExtractor/ccextractorfluttergui/releases/latest).Content | ConvertFrom-Json).assets | ForEach-Object {if ($_.name -eq "windows.zip") { Invoke-WebRequest -UseBasicParsing -Uri $_.browser_download_url -OutFile windows.zip}}
working-directory: ./windows
@@ -34,16 +79,32 @@ jobs:
run: ls
working-directory: ./windows
- name: Unzip Flutter GUI
run: Expand-Archive -Path ./windows.zip -DestinationPath ./installer
run: Expand-Archive -Path ./windows.zip -DestinationPath ./installer -Force
working-directory: ./windows
- name: Display installer folder contents
run: Get-ChildItem -Recurse ./installer
working-directory: ./windows
- name: build installer
run: wix build -ext "$HOME\.wix\extensions\WixToolset.UI.wixext\4.0.0-preview.0\tools\WixToolset.UI.wixext.dll" -d "AppVersion=${{ steps.get_version.outputs.VERSION }}.0.0" -o CCExtractor.msi installer.wxs
- name: Create portable zip
run: Compress-Archive -Path ./installer/* -DestinationPath ./CCExtractor_win_portable.zip
working-directory: ./windows
- name: Build installer
run: wix build -ext WixToolset.UI.wixext -d "AppVersion=${{ steps.get_version.outputs.VERSION }}.0.0" -o CCExtractor.msi installer.wxs CustomUI.wxs
working-directory: ./windows
- name: Upload as asset
uses: AButler/upload-release-assets@v2.0
uses: AButler/upload-release-assets@v3.0
with:
files: './windows/CCExtractor.msi'
repo-token: ${{ secrets.GITHUB_TOKEN }}
files: './windows/CCExtractor.msi;./windows/CCExtractor_win_portable.zip'
repo-token: ${{ secrets.GITHUB_TOKEN }}
create_linux_package:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
path: ./ccextractor
- name: Create .tar.gz without git and windows folders
run: tar -pczf ./ccextractor_minimal.tar.gz --exclude "ccextractor/windows" --exclude "ccextractor/.git" ccextractor
- name: Upload as asset
uses: AButler/upload-release-assets@v3.0
with:
files: './ccextractor_minimal.tar.gz'
repo-token: ${{ secrets.GITHUB_TOKEN }}

41
.github/workflows/test_rust.yml vendored Normal file
View File

@@ -0,0 +1,41 @@
name: Unit Test Rust
on:
push:
paths:
- ".github/workflows/test.yml"
- "src/rust/**"
tags-ignore:
- "*.*"
pull_request:
types: [opened, synchronize, reopened]
paths:
- ".github/workflows/test.yml"
- "src/rust/**"
jobs:
test_rust:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./src/rust
steps:
- uses: actions/checkout@v6
- name: cache
uses: actions/cache@v5
with:
path: |
src/rust/.cargo/registry
src/rust/.cargo/git
src/rust/target
src/rust/lib_ccxr/target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-cargo-
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- name: Test main module
run: cargo test
working-directory: ./src/rust
- name: Test lib_ccxr module
run: cargo test
working-directory: ./src/rust/lib_ccxr

29
.gitignore vendored
View File

@@ -17,8 +17,10 @@ CVS
mac/ccextractor
linux/ccextractor
linux/depend
windows/x86_64-pc-windows-msvc/**
windows/Debug/**
windows/Debug-OCR/**
windows/release-with-debug/**
windows/Release/**
windows/Release-Full/**
windows/Release-OCR/**
@@ -84,6 +86,7 @@ linux/aclocal.m4
linux/*.in
linux/configure
linux/build-conf/
mac/rust/
mac/config.h
mac/config.log
mac/config.status
@@ -97,16 +100,12 @@ package_creators/*tar.gz
package_creators/build/*.deb
src/.deps/
src/.dirstamp
src/gpacmp4/.deps/
src/gpacmp4/.dirstamp
src/lib_ccx/.deps/
src/lib_ccx/.dirstamp
src/lib_hash/.deps/
src/lib_hash/.dirstamp
src/libpng/.deps/
src/libpng/.dirstamp
src/protobuf-c/.deps/
src/protobuf-c/.dirstamp
src/utf8proc/.deps/
src/utf8proc/.dirstamp
src/zlib/.deps/
@@ -140,3 +139,25 @@ mac/CMakeCache.txt
# Bazel
bazel*
#Intellij IDEs
.idea/
# Rust build and MakeFiles (and CMake files)
src/rust/CMakeFiles/
src/rust/CMakeCache.txt
src/rust/Makefile
src/rust/cmake_install.cmake
src/rust/target/
src/rust/lib_ccxr/target/
windows/ccx_rust.lib
windows/*/debug/*
windows/*/CACHEDIR.TAG
windows/.rustc_info.json
linux/configure~
# Plans and temporary files
plans/
tess.log
**/tess.log
ut=srt*

View File

@@ -4,7 +4,7 @@ MAINTAINER = Marc Espie <espie@openbsd.org>
CATEGORIES = multimedia
COMMENT = closed caption subtitles extractor
HOMEPAGE = https://ccextractor.org
V = 0.92
V = 0.96
DISTFILES = ccextractor.${V:S/.//}-src.zip
MASTER_SITES = ${MASTER_SITE_SOURCEFORGE:=ccextractor/}
DISTNAME = ccextractor-$V

View File

@@ -38,7 +38,7 @@ This will extract the subtitles.
More usage information can be found on our website:
- [Using the command line tool](https://ccextractor.org/public/general/command_line_usage/)
- [Using the Windows GUI](https://ccextractor.org/public/general/win_gui_usage/)
- [Using the Flutter GUI](https://ccextractor.org/public/general/flutter_gui/)
You can also find the list of parameters and their brief description by running `ccextractor` without any arguments.

239
docker/Dockerfile Normal file
View File

@@ -0,0 +1,239 @@
# CCExtractor Docker Build
#
# Build variants via BUILD_TYPE argument:
# - minimal: Basic CCExtractor without OCR
# - ocr: CCExtractor with OCR support (default)
# - hardsubx: CCExtractor with burned-in subtitle extraction (requires FFmpeg)
#
# Source options via USE_LOCAL_SOURCE argument:
# - 0 (default): Clone from GitHub (standalone Dockerfile usage)
# - 1: Use local source (when building from cloned repo)
#
# Build examples:
#
# # Standalone (just the Dockerfile, clones from GitHub):
# docker build -t ccextractor docker/
# docker build --build-arg BUILD_TYPE=hardsubx -t ccextractor docker/
#
# # From cloned repository (faster, uses local source):
# docker build --build-arg USE_LOCAL_SOURCE=1 -f docker/Dockerfile -t ccextractor .
# docker build --build-arg USE_LOCAL_SOURCE=1 --build-arg BUILD_TYPE=minimal -f docker/Dockerfile -t ccextractor .
ARG DEBIAN_VERSION=bookworm-slim
FROM debian:${DEBIAN_VERSION} AS base
FROM base AS builder
# Build arguments
ARG BUILD_TYPE=ocr
ARG USE_LOCAL_SOURCE=0
# BUILD_TYPE: minimal, ocr, hardsubx
# USE_LOCAL_SOURCE: 0 = git clone, 1 = copy local source
# Avoid interactive prompts during package installation
ENV DEBIAN_FRONTEND=noninteractive
# Install base build dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
git \
curl \
ca-certificates \
gcc \
g++ \
cmake \
make \
pkg-config \
bash \
zlib1g-dev \
libpng-dev \
libjpeg-dev \
libssl-dev \
libfreetype-dev \
libxml2-dev \
libcurl4-gnutls-dev \
clang \
libclang-dev \
&& rm -rf /var/lib/apt/lists/*
# Install Rust toolchain
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
ENV PATH="/root/.cargo/bin:${PATH}"
# Install OCR dependencies (for ocr and hardsubx builds)
RUN if [ "$BUILD_TYPE" = "ocr" ] || [ "$BUILD_TYPE" = "hardsubx" ]; then \
apt-get update && apt-get install -y --no-install-recommends \
tesseract-ocr \
libtesseract-dev \
libleptonica-dev \
&& rm -rf /var/lib/apt/lists/*; \
fi
# Install FFmpeg dependencies (for hardsubx build)
RUN if [ "$BUILD_TYPE" = "hardsubx" ]; then \
apt-get update && apt-get install -y --no-install-recommends \
libavcodec-dev \
libavformat-dev \
libavutil-dev \
libswscale-dev \
libswresample-dev \
libavfilter-dev \
libavdevice-dev \
&& rm -rf /var/lib/apt/lists/*; \
fi
# Build and install GPAC library
WORKDIR /root
RUN git clone -b v2.4.0 --depth 1 https://github.com/gpac/gpac
WORKDIR /root/gpac
RUN ./configure && make -j$(nproc) lib && make install-lib && ldconfig
WORKDIR /root
RUN rm -rf /root/gpac
# Get CCExtractor source (either clone or copy based on USE_LOCAL_SOURCE)
WORKDIR /root
# First, copy local source if provided (will be empty dir if building standalone)
COPY . /root/ccextractor-local/
# Then get source: use local copy if USE_LOCAL_SOURCE=1 and source exists,
# otherwise clone from GitHub
RUN if [ "$USE_LOCAL_SOURCE" = "1" ] && [ -f /root/ccextractor-local/src/ccextractor.c ]; then \
echo "Using local source"; \
mv /root/ccextractor-local /root/ccextractor; \
else \
echo "Cloning from GitHub"; \
rm -rf /root/ccextractor-local; \
git clone --depth 1 https://github.com/CCExtractor/ccextractor.git /root/ccextractor; \
fi
WORKDIR /root/ccextractor/linux
# Generate build info
RUN ./pre-build.sh
# Build Rust library with appropriate features
RUN if [ "$BUILD_TYPE" = "hardsubx" ]; then \
cd ../src/rust && \
CARGO_TARGET_DIR=../../linux/rust cargo build --release --features hardsubx_ocr; \
else \
cd ../src/rust && \
CARGO_TARGET_DIR=../../linux/rust cargo build --release; \
fi
RUN cp rust/release/libccx_rust.a ./libccx_rust.a
# Compile CCExtractor
RUN if [ "$BUILD_TYPE" = "minimal" ]; then \
BLD_FLAGS="-std=gnu99 -Wno-write-strings -Wno-pointer-sign -D_FILE_OFFSET_BITS=64 -DVERSION_FILE_PRESENT -DFT2_BUILD_LIBRARY -DGPAC_DISABLE_VTT -DGPAC_DISABLE_OD_DUMP -DGPAC_DISABLE_REMOTERY -DNO_GZIP -DGPAC_64_BITS"; \
BLD_INCLUDE="-I../src -I../src/lib_ccx/ -I /usr/include/gpac/ -I../src/thirdparty/libpng -I../src/thirdparty/zlib -I../src/lib_ccx/zvbi -I../src/thirdparty/lib_hash -I../src/thirdparty -I../src/thirdparty/freetype/include"; \
BLD_LINKER="-lm -Wl,--allow-multiple-definition -lpthread -ldl -lgpac ./libccx_rust.a"; \
elif [ "$BUILD_TYPE" = "hardsubx" ]; then \
BLD_FLAGS="-std=gnu99 -Wno-write-strings -Wno-pointer-sign -D_FILE_OFFSET_BITS=64 -DVERSION_FILE_PRESENT -DENABLE_OCR -DENABLE_HARDSUBX -DFT2_BUILD_LIBRARY -DGPAC_DISABLE_VTT -DGPAC_DISABLE_OD_DUMP -DGPAC_DISABLE_REMOTERY -DNO_GZIP -DGPAC_64_BITS"; \
BLD_INCLUDE="-I../src -I /usr/include/leptonica/ -I /usr/include/tesseract/ -I../src/lib_ccx/ -I /usr/include/gpac/ -I../src/thirdparty/libpng -I../src/thirdparty/zlib -I../src/lib_ccx/zvbi -I../src/thirdparty/lib_hash -I../src/thirdparty -I../src/thirdparty/freetype/include"; \
BLD_LINKER="-lm -Wl,--allow-multiple-definition -ltesseract -lleptonica -lpthread -ldl -lgpac -lswscale -lavutil -lavformat -lavcodec -lavfilter -lswresample ./libccx_rust.a"; \
else \
BLD_FLAGS="-std=gnu99 -Wno-write-strings -Wno-pointer-sign -D_FILE_OFFSET_BITS=64 -DVERSION_FILE_PRESENT -DENABLE_OCR -DFT2_BUILD_LIBRARY -DGPAC_DISABLE_VTT -DGPAC_DISABLE_OD_DUMP -DGPAC_DISABLE_REMOTERY -DNO_GZIP -DGPAC_64_BITS"; \
BLD_INCLUDE="-I../src -I /usr/include/leptonica/ -I /usr/include/tesseract/ -I../src/lib_ccx/ -I /usr/include/gpac/ -I../src/thirdparty/libpng -I../src/thirdparty/zlib -I../src/lib_ccx/zvbi -I../src/thirdparty/lib_hash -I../src/thirdparty -I../src/thirdparty/freetype/include"; \
BLD_LINKER="-lm -Wl,--allow-multiple-definition -ltesseract -lleptonica -lpthread -ldl -lgpac ./libccx_rust.a"; \
fi && \
SRC_LIBPNG="$(find ../src/thirdparty/libpng/ -name '*.c')" && \
SRC_ZLIB="$(find ../src/thirdparty/zlib/ -name '*.c')" && \
SRC_CCX="$(find ../src/lib_ccx/ -name '*.c')" && \
SRC_GPAC="$(find /usr/include/gpac/ -name '*.c' 2>/dev/null || true)" && \
SRC_HASH="$(find ../src/thirdparty/lib_hash/ -name '*.c')" && \
SRC_UTF8PROC="../src/thirdparty/utf8proc/utf8proc.c" && \
SRC_FREETYPE="../src/thirdparty/freetype/autofit/autofit.c \
../src/thirdparty/freetype/base/ftbase.c \
../src/thirdparty/freetype/base/ftbbox.c \
../src/thirdparty/freetype/base/ftbdf.c \
../src/thirdparty/freetype/base/ftbitmap.c \
../src/thirdparty/freetype/base/ftcid.c \
../src/thirdparty/freetype/base/ftfntfmt.c \
../src/thirdparty/freetype/base/ftfstype.c \
../src/thirdparty/freetype/base/ftgasp.c \
../src/thirdparty/freetype/base/ftglyph.c \
../src/thirdparty/freetype/base/ftgxval.c \
../src/thirdparty/freetype/base/ftinit.c \
../src/thirdparty/freetype/base/ftlcdfil.c \
../src/thirdparty/freetype/base/ftmm.c \
../src/thirdparty/freetype/base/ftotval.c \
../src/thirdparty/freetype/base/ftpatent.c \
../src/thirdparty/freetype/base/ftpfr.c \
../src/thirdparty/freetype/base/ftstroke.c \
../src/thirdparty/freetype/base/ftsynth.c \
../src/thirdparty/freetype/base/ftsystem.c \
../src/thirdparty/freetype/base/fttype1.c \
../src/thirdparty/freetype/base/ftwinfnt.c \
../src/thirdparty/freetype/bdf/bdf.c \
../src/thirdparty/freetype/bzip2/ftbzip2.c \
../src/thirdparty/freetype/cache/ftcache.c \
../src/thirdparty/freetype/cff/cff.c \
../src/thirdparty/freetype/cid/type1cid.c \
../src/thirdparty/freetype/gzip/ftgzip.c \
../src/thirdparty/freetype/lzw/ftlzw.c \
../src/thirdparty/freetype/pcf/pcf.c \
../src/thirdparty/freetype/pfr/pfr.c \
../src/thirdparty/freetype/psaux/psaux.c \
../src/thirdparty/freetype/pshinter/pshinter.c \
../src/thirdparty/freetype/psnames/psnames.c \
../src/thirdparty/freetype/raster/raster.c \
../src/thirdparty/freetype/sfnt/sfnt.c \
../src/thirdparty/freetype/smooth/smooth.c \
../src/thirdparty/freetype/truetype/truetype.c \
../src/thirdparty/freetype/type1/type1.c \
../src/thirdparty/freetype/type42/type42.c \
../src/thirdparty/freetype/winfonts/winfnt.c" && \
BLD_SOURCES="../src/ccextractor.c $SRC_CCX $SRC_GPAC $SRC_ZLIB $SRC_LIBPNG $SRC_HASH $SRC_UTF8PROC $SRC_FREETYPE" && \
gcc $BLD_FLAGS $BLD_INCLUDE -o ccextractor $BLD_SOURCES $BLD_LINKER
# Copy binary to known location
RUN cp /root/ccextractor/linux/ccextractor /ccextractor
# Final minimal image
FROM base AS final
ARG BUILD_TYPE=ocr
# Avoid interactive prompts
ENV DEBIAN_FRONTEND=noninteractive
# Install runtime dependencies based on build type
RUN apt-get update && apt-get install -y --no-install-recommends \
libpng16-16 \
libjpeg62-turbo \
zlib1g \
libssl3 \
libcurl4 \
&& rm -rf /var/lib/apt/lists/*
# OCR runtime dependencies
RUN if [ "$BUILD_TYPE" = "ocr" ] || [ "$BUILD_TYPE" = "hardsubx" ]; then \
apt-get update && apt-get install -y --no-install-recommends \
tesseract-ocr \
liblept5 \
&& rm -rf /var/lib/apt/lists/*; \
fi
# HardSubX runtime dependencies
RUN if [ "$BUILD_TYPE" = "hardsubx" ]; then \
apt-get update && apt-get install -y --no-install-recommends \
libavcodec59 \
libavformat59 \
libavutil57 \
libswscale6 \
libswresample4 \
libavfilter8 \
libavdevice59 \
&& rm -rf /var/lib/apt/lists/*; \
fi
# Copy GPAC library from builder
COPY --from=builder /usr/local/lib/libgpac.so* /usr/local/lib/
# Update library cache
RUN ldconfig
# Copy CCExtractor binary
COPY --from=builder /ccextractor /ccextractor
ENTRYPOINT ["/ccextractor"]

91
docker/README.md Normal file
View File

@@ -0,0 +1,91 @@
# CCExtractor Docker Image
This Dockerfile builds CCExtractor with support for multiple build variants.
## Build Variants
| Variant | Description | Features |
|---------|-------------|----------|
| `minimal` | Basic CCExtractor | No OCR support |
| `ocr` | With OCR support (default) | Tesseract OCR for bitmap subtitles |
| `hardsubx` | With burned-in subtitle extraction | OCR + FFmpeg for hardcoded subtitles |
## Building
### Standalone Build (from Dockerfile only)
You can build CCExtractor using just the Dockerfile - it will clone the source from GitHub:
```bash
# Default build (OCR enabled)
docker build -t ccextractor docker/
# Minimal build (no OCR)
docker build --build-arg BUILD_TYPE=minimal -t ccextractor docker/
# HardSubX build (OCR + FFmpeg for burned-in subtitles)
docker build --build-arg BUILD_TYPE=hardsubx -t ccextractor docker/
```
### Build from Cloned Repository (faster)
If you have already cloned the repository, you can use local source for faster builds:
```bash
git clone https://github.com/CCExtractor/ccextractor.git
cd ccextractor
# Default build (OCR enabled)
docker build --build-arg USE_LOCAL_SOURCE=1 -f docker/Dockerfile -t ccextractor .
# Minimal build
docker build --build-arg USE_LOCAL_SOURCE=1 --build-arg BUILD_TYPE=minimal -f docker/Dockerfile -t ccextractor .
# HardSubX build
docker build --build-arg USE_LOCAL_SOURCE=1 --build-arg BUILD_TYPE=hardsubx -f docker/Dockerfile -t ccextractor .
```
## Build Arguments
| Argument | Default | Description |
|----------|---------|-------------|
| `BUILD_TYPE` | `ocr` | Build variant: `minimal`, `ocr`, or `hardsubx` |
| `USE_LOCAL_SOURCE` | `0` | Set to `1` to use local source instead of cloning |
| `DEBIAN_VERSION` | `bookworm-slim` | Debian version to use as base |
## Usage
### Basic Usage
```bash
# Show version
docker run --rm ccextractor --version
# Show help
docker run --rm ccextractor --help
```
### Processing Local Files
Mount your local directory to process files:
```bash
# Process a video file with output file
docker run --rm -v $(pwd):$(pwd) -w $(pwd) ccextractor input.mp4 -o output.srt
# Process using stdout
docker run --rm -v $(pwd):$(pwd) -w $(pwd) ccextractor input.mp4 --stdout > output.srt
```
### Interactive Mode
```bash
docker run --rm -it --entrypoint=/bin/bash ccextractor
```
## Image Size
The multi-stage build produces runtime images:
- `minimal`: ~130MB
- `ocr`: ~215MB (includes Tesseract)
- `hardsubx`: ~610MB (includes Tesseract + FFmpeg)

View File

@@ -29,7 +29,7 @@ To do:
though. No samples, no support.
- A few commands are not yet supported, specifically those related
to delay.
- Detect and extract captions from MP4 (MOV) files, handled by gpacmp4
- Detect and extract captions from MP4 (MOV) files, handled by gpac
Done (18.08.2015):

View File

@@ -0,0 +1,157 @@
# Building CCExtractor on macOS using System Libraries (-system-libs)
## Overview
This document explains how to build CCExtractor on macOS using system-installed libraries instead of bundled third-party libraries.
This build mode is required for Homebrew compatibility and is enabled via the `-system-libs` flag introduced in PR #1862.
## Why is -system-libs needed?
### Background
CCExtractor was removed from Homebrew (homebrew-core) because:
- Homebrew does not allow bundling third-party libraries
- The default CCExtractor build compiles libraries from `src/thirdparty/`
- This violates Homebrew packaging policies
### What -system-libs fixes
The `-system-libs` flag allows CCExtractor to:
- Use system-installed libraries via Homebrew
- Resolve headers and linker flags using `pkg-config`
- Skip compiling bundled copies of common libraries
This makes CCExtractor acceptable for Homebrew packaging.
## Build Modes Explained
### 1⃣ Default Build (Bundled Libraries)
**Command:**
```bash
./mac/build.command
```
**Behavior:**
- Compiles bundled libraries:
- `freetype`
- `libpng`
- `zlib`
- `utf8proc`
- Self-contained binary
- Larger size
- Suitable for standalone builds
### 2⃣ System Libraries Build (Homebrew-compatible)
**Command:**
```bash
./mac/build.command -system-libs
```
**Behavior:**
- Uses system libraries via `pkg-config`
- Does not compile bundled libraries
- Smaller binary
- Faster build
- Required for Homebrew
## Required Homebrew Dependencies
Install required dependencies:
```bash
brew install pkg-config autoconf automake libtool \
gpac freetype libpng protobuf-c utf8proc zlib
```
**Optional** (OCR / HARDSUBX support):
```bash
brew install tesseract leptonica ffmpeg
```
## How to Build
```bash
cd mac
./build.command -system-libs
```
**Verify:**
```bash
./ccextractor --version
```
## What Changes Internally with -system-libs
### Libraries NOT compiled (system-provided)
- **FreeType**
- **libpng**
- **zlib**
- **utf8proc**
### Libraries STILL bundled
- **lib_hash** (Custom SHA-256 implementation, no system equivalent)
## CI Coverage
A new CI job was added:
- `build_shell_system_libs`
**What it does:**
- Installs Homebrew dependencies
- Runs `./build.command -system-libs`
- Verifies the binary runs correctly
This ensures Homebrew-compatible builds stay working.
## Verification (Local)
You can confirm system libraries are used:
```bash
otool -L mac/ccextractor
```
**Expected output includes paths like:**
```
/opt/homebrew/opt/gpac/lib/libgpac.dylib
```
## Homebrew Formula Usage (Future)
Example formula snippet:
```ruby
def install
system "./mac/build.command", "-system-libs"
bin.install "mac/ccextractor"
end
```
## Summary
- `-system-libs` is opt-in
- Default build remains unchanged
- Enables CCExtractor to return to Homebrew
- Fully tested in CI and locally
## Related
- **PR #1862** — Add `-system-libs` flag
- **Issue #1580** — Homebrew compatibility
- **Issue #1534** — System library support

View File

@@ -1,3 +1,54 @@
0.96 (2025-12-23)
-----------------
- New: Multi-page teletext extraction support (#665)
- Extract multiple teletext pages simultaneously with separate output files
- Use --tpage multiple times (e.g., --tpage 100 --tpage 200)
- Output files are named with page suffix (e.g., output_p100.srt, output_p200.srt)
- New: Added --list-tracks (-L) option to list all tracks in media files without processing
New: Chinese, Korean, Japanese support - proper encoding and OCR.
New: Correct McPoodle DVD raw format support
Fix: Timing is now frame perfect (using FFMpeg timing dump as reference) in all formats.
Fix: Solved garbling in all the pending issues we had on GitHub.
Fix: All causes of "premature end of file" messages due to bugs and not actual file cuts.
Fix: All memory leaks, double frees and usual C nastyness that valgrind could find.
- Fix Include ATSC VCT virtual channel numbers and call signs in XMLTV output
- Fix: Restore ATSC XMLTV generation with ETT parsing for extended descriptions, multi-segment handling, extended table ID's (EIT/VCT), corrected <programme> XMLTV formatting, buffer bounds fixes
- Fix: Add HEVC/H.265 stream type recognition to prevent crashes on ATSC 3.0 streams.
Fix: Tolerance to damaged streams - recover where possible instead of terminating.
Issues closed: Over 40! Too many to list here, but each of them was either a bug squashed or a feature implemented.
0.95 (2025-09-15 - never formally packaged)
-----------------
- New: Create a Docker image to simplify the CCExtractor usage without any environmental hustle (#1611)
- New: Add SCC support for CEA-708 decoder (#1595)
Refactor: Lots of code ported to Rust.
- Fix: Improved handling of IETF language tags in Matroska files (#1665)
- Breaking: Major argument flags revamp for CCExtractor (#1564 & #1619)
- Fix: segmentation fault in using hardsubx
- Fix: WebVTT X-TIMESTAMP-MAP placement (#1463)
- Fix: ffmpeg 5.0, tesseract 5.0 compatibility and remove deprecated methods
- Fix: tesseract 5.x traineddata location in ocr
- Improvement: Ignore MXF Caption Essence Container version byte to enhance SRT subtitle extraction compatibility
- New: Add tesseract page segmentation modes control with `--psm` flag
- Fix: Support for MINGW-w64 cross compiling
0.94 (2021-12-14)
-----------------
- BOM is no longer enabled by default on windows platforms
- CEA-708: Rust decoder is now default instead of C decoder
- CEA-708 subs are now extracted by default
- New: Add check for Minimum supported rust version (MSRV) (#1387)
- Fix: Fix CEA-708 Carriage Return command implementation
- Fix: Fix bug with startat/endat parameter (#1396)
- Fix: Mac Build processes (#1390)
- Fix: Fix bug with negative delay parameter (#1365)
0.93 (2021-08-16)
-----------------
- Minor Rust updates (format, typos, docs)
- Updated GUI
0.92 (2021-08-10)
-----------------
- Rust updates: Added srt writer
@@ -74,7 +125,7 @@
- New: Add support for DVB inside .mkv
- Fix: Added -latrusmap Map Latin symbols to Cyrillic ones in special cases
of Russian Teletext files (issue #1086)
- Fix: Several OCR crashes
- Fix: Several OCR crashes
0.87 (2018-10-23)
-----------------
@@ -154,10 +205,10 @@
- New: Added tarball generation script.
- New: Added --analyzevideo. If present the video stream will be processed even if the
subtitles are in a different stream. This is useful when we want video information
(resolution, frame type, etc). -vides now implies this option too.
(resolution, frame type, etc). -vides now implies this option too.
[Note: Tentative - some possibly breaking changed were made for this, so if you
use it validate results]
- New: Added a GUI in the main CCExtractor binary (separate from the external GUIs
- New: Added a GUI in the main CCExtractor binary (separate from the external GUIs
such as CCExtractorGUI).
- New: A Python binding extension so it's possible to use CCExtractor's tools from
Python.
@@ -168,29 +219,29 @@
- New: FreeType-based text renderer (-out=spupng with teletext/EIA608).
- New: Upgrade library UTF8proc
- New: Upgrade library win_iconv
- New: Upgrade library zlib
- New: Upgrade library LibPNG
- New: Upgrade library zlib
- New: Upgrade library LibPNG
- New: Support for Source-Specific Multicast
- New: Added Travis CI support
- New: Added Travis CI support
- New: Made error messages clearer, less ambiguous
- Fix: Prevent the OCR being initialized more than once (happened on multiprogram and
PAT changes)
- Fix: Makefiles, build scripts, etc... everything updated and corrected for all
platforms.
-Fix: Proper line ending for .srt files from bitmaps.
- Fix: OCR corrections using grayscale before extracting texts.
-Fix: Proper line ending for .srt files from bitmaps.
- Fix: OCR corrections using grayscale before extracting texts.
- Fix: End timestamps in transcripts from DVB.
- Fix: Forcing -noru to cause deduplication in ISDB
- Fix: TS: Skip NULL packets
- Fix: TS: Skip NULL packets
- Fix: When NAL decoding fails, don't dump the whole decoded thing, limit to 160 bytes.
- Fix: Modify Autoconf scripts to generate tarball for mac from `/package_creators/tarball.sh`
- Fix: Modify Autoconf scripts to generate tarball for mac from `/package_creators/tarball.sh`
and include GUI files in tarball
- Fix: Started work on libGPAC upgrade.
- Fix: DVB subtitle not extracted if there's no display segment
- Fix: Heap corruption in add_ocrtext2str
- Fix: bug that caused -out=spupng sometimes crashes
- Fix: Checks for text before newlines on DVB subtitles
- Fix: OCR issue caused by separated dvb subtitle regions
- Fix: Checks for text before newlines on DVB subtitles
- Fix: OCR issue caused by separated dvb subtitle regions
- Fix: DVB crash on specific condition (!rect->ocr_text)
- Fix: DVB bug (Multiple-line subtitle; Missing last line)
- Fix: --sentencecap for teletext samples
@@ -237,7 +288,7 @@
0.84 (2016-12-16)
-----------------
- New: In Windows, both with and without-OCR binaries are bundled, since the OCR one causes problems due to
- New: In Windows, both with and without-OCR binaries are bundled, since the OCR one causes problems due to
dependencies in some system. So unless you need the OCR just use the non-OCR version.
- New: Added -sbs (sentence by sentence) for DVB output. Each frame in the output file contains a complete
sentence (experimental).
@@ -260,7 +311,7 @@
- Fix: Added detail in many error messages.
- Fix: Memory leaks in videos with XDS.
- Fix: Makefile compatibility issues with Raspberry pi.
- Fix: missing separation between WebVTT header and body.
- Fix: missing separation between WebVTT header and body.
- Fix: Stupid bug in M2TS that preventing it from working.
- Fix: OCR libraries dependencies for the release version in Windows.
- Fix: non-buffered reading from pipes.
@@ -307,7 +358,7 @@
- Fix: Timing in -ucla
- Fix: Timing in ISDB (some instances)
- Fix: "mfra" mp4 box weight changed to 1 (this helps with correct file format detection)
- Fix: Fix for TARGET File is null.
- Fix: Fix for TARGET File is null.
- Fix: Fixed SegFaults while parsing parameters (if mandatory parameter is not present in -outinterval, -codec or -nocodec)
- Fix: Crash when input small is too small
- Fix: Update some URLs in code (references to docs)
@@ -365,7 +416,7 @@
- CCExtractor can be used as library if compiled using cmake
- By default the Windows version adds BOM to generated UTF files (this is
because it's needed to open the files correctly) while all other
builds don't add it (because it messes with text processing tools).
builds don't add it (because it messes with text processing tools).
You can use -bom and -nobom to change the behaviour.
0.74 (2014-09-24)
@@ -404,7 +455,7 @@
------------------------
This is the first release that is part of Google's Summer of Code.
Anshul, Ruslan and Willem joined CCExtractor to work on a number of things
over the summer, and their work is already reaching the mainstream
over the summer, and their work is already reaching the mainstream
version of CCExtractor.
- Added a huge dictionary submitted by Matt Stockard.
@@ -437,7 +488,7 @@ version of CCExtractor.
0000101 is the default setting for transcripts
1110101 is the default for timed transcripts
1111001 is the default setting for -ucla
Make sure you use this parameter after others that might affect these
Make sure you use this parameter after others that might affect these
settings (-out, -ucla, -xds, -txt, -ttxt, ...)
- Fixed Negative timing Bug
@@ -455,7 +506,7 @@ version of CCExtractor.
- Started refactoring and clean-up.
- Fix: MPEG clock rollover (happens each 26 hours) caused a time
discontinuity.
- Windows GUI: Started work on HDHomeRun support. For now it just looks
- Windows GUI: Started work on HDHomeRun support. For now it just looks
for HDHomeRun devices. Lots of other things will arrive in the next
versions.
- Windows GUI: Some code refactoring, since the HDHomeRun support makes
@@ -472,7 +523,7 @@ version of CCExtractor.
a good test sample file...
- Color and fonts in PAC commands were ignored, fixed (Helen Buus).
- Added a new output format, spupng. It consists on one .png file
for each subtitle frame and one .xml with all the timing
for each subtitle frame and one .xml with all the timing
(Heleen Buus).
- Some fixes (Chris Small).
@@ -494,12 +545,12 @@ version of CCExtractor.
- Added -latin1 to select Latin 1 as encoding. Default is now
UTF-8 (-utf8 still exists but it's not needed).
- Added -ru1, which emulates a (non-existing in real life) 1 line
roll-up mode.
roll-up mode.
0.66 (2013-07-01)
-----------------
- Fixed bug in auto detection code that triggered a message
- Fixed bug in auto detection code that triggered a message
about file being auto of sync.
- Added -investigate_packets
The PMT is used to select the most promising elementary stream
@@ -508,39 +559,39 @@ version of CCExtractor.
manually, in case the CC location is not obvious from the PMT
contents. To assist looking for the right stream, the parameter
"-investigate_packets" will have CCExtractor look inside each
stream, looking for CC markers, and report the streams that
stream, looking for CC markers, and report the streams that
are likely to contain CC data even if it can't be determined from
their PMT entry.
- Added -datastreamtype to manually selecting a stream based on
its type instead of its PID. Useful if your recording program
always hides the caption under the stream type.
always hides the caption under the stream type.
- Added -streamtype so if an elementary stream is selected manually
for processing, the streamtype can be selected too. This can be
needed if you process, for example a stream that is declared as
for processing, the streamtype can be selected too. This can be
needed if you process, for example a stream that is declared as
"private MPEG" in the PMT, so CCExtractor can't tell what it is.
Usually you'll want -streamtype 2 (MPEG video) or -streamtype 6
(MPEG private data).
- PMT content listing improved, it now shows the stream type for
more types.
- Fixes in roll-up, cursor was being moved to column 1 if a
- Fixes in roll-up, cursor was being moved to column 1 if a
RU2, RU3 or RU4 was received even if already in roll-up mode.
- Added -autoprogram. If a multiprogram TS is processed and
- Added -autoprogram. If a multiprogram TS is processed and
-autoprogram is used, CCExtractor will analyze all PMTs and use
the first program that has a suitable data stream.
- Timed transcript (ttxt) now also exports the caption mode
(roll-up, paint-on, etc.) next to each line, as it's useful to
- Timed transcript (ttxt) now also exports the caption mode
(roll-up, paint-on, etc.) next to each line, as it's useful to
detect things like commercials.
- Content Advisory information from XDS is now decoded if it's
transmitted in "US TV parental guidelines" or "MPA".
Other encoding such as Canada's are not supported yet due
transmitted in "US TV parental guidelines" or "MPA".
Other encoding such as Canada's are not supported yet due
to lack of samples.
- Copy Management information from XDS is now decoded.
- Added -xds. If present and export format is timed transcript
(only), XDS information will be saved to file (same file as the
transcript, with XDS being clearly marked). Note that for now
all XDS data is exported even if it doesn't change, so the
all XDS data is exported even if it doesn't change, so the
transcript file will be significantly larger.
- Added some PaintOn support, at least enough to prevent it
- Added some PaintOn support, at least enough to prevent it
from breaking things when the other modes are used.
- Removed afd_data() warning. AFD doesn't carry any caption related
data. AFD still detected in code in case we want to do something
@@ -558,21 +609,21 @@ version of CCExtractor.
calculated distance, the maximum allowed distance, and whether
the strings are ultimately considered equivalent or not, i.e.
the calculated distance is less or equal than the max allowed.
-levdistmincnt value: Minimum distance we always allow
regardless of the length of the strings. Default 2. This means
that if the calculated distance is 0, 1 or 2, we consider the
-levdistmincnt value: Minimum distance we always allow
regardless of the length of the strings. Default 2. This means
that if the calculated distance is 0, 1 or 2, we consider the
strings to be equivalent.
-levdistmaxpct value: Maximum distance we allow, as a
percentage of the shortest string length. Default 10%. For
example, consider a comparison of one string of 30 characters
and one of 60 characters. We want to determine whether the
first 30 characters of the longer string are more or less the
same as the shortest string, i.e. whether the longest string
is the shortest one plus new characters and maybe some
corrections. Since the shortest string is 30 characters and
the default percentage is 10%, we would allow a distance of
-levdistmaxpct value: Maximum distance we allow, as a
percentage of the shortest string length. Default 10%. For
example, consider a comparison of one string of 30 characters
and one of 60 characters. We want to determine whether the
first 30 characters of the longer string are more or less the
same as the shortest string, i.e. whether the longest string
is the shortest one plus new characters and maybe some
corrections. Since the shortest string is 30 characters and
the default percentage is 10%, we would allow a distance of
up to 3 between the first 30 characters.
- Added -lf : Use UNIX line terminator (LF) instead of Windows (CRLF).
- Added -lf : Use UNIX line terminator (LF) instead of Windows (CRLF).
- Added -noautotimeref: Prevent UTC reference from being auto set from
the stream data.
@@ -582,7 +633,7 @@ version of CCExtractor.
- Added end timestamps in timed transcripts
- Added support for SMPTE (patch by John Kemp)
- Initial support for MPEG2 video tracks inside MP4 files (thanks a
lot to GPAC's Jean who assisted in analyzing the sample and
lot to GPAC's Jean who assisted in analyzing the sample and
doing the required changes in GPAC).
- Improved MP4 auto detection
- Support for PCR if PTS is not available (needed for some teletext
@@ -608,7 +659,7 @@ version of CCExtractor.
data (bypassing detections).
- Added -ru2 and -ru3 to limit the number of visible lines in roll-up
captions (bypassing whatever the broadcast says).
- Added support for a .hex (hexadecimal) dump of data.
- Added support for a .hex (hexadecimal) dump of data.
- Added support for wtv in Windows. This is done by using a new program
(wtvccdump.exe) and a new DirectShow filter (CCExtractorDump.dll) that
process the .wtv using DirecShow's filters and export the line 21 data
@@ -619,9 +670,9 @@ version of CCExtractor.
0.63 (2012-08-17)
-----------------
- Telext support added, by integrating Petr Kutalek's telxcc. Integration is
still quite basic (there's equivalent code from both CCExtractor and
telxcc) and some clean up is needed, but it works. Petr has announced that
he's abandoning telxcc so further development will happen directly in
still quite basic (there's equivalent code from both CCExtractor and
telxcc) and some clean up is needed, but it works. Petr has announced that
he's abandoning telxcc so further development will happen directly in
CCExtractor.
- Some bug fixes, as usual.
@@ -631,14 +682,14 @@ version of CCExtractor.
Mac users that sent this.
- Hauppauge mode now uses PES timing, needed for files that don't have
caption data during all the video (such as in commercial breaks).
- Added -mp4 and -in:mp4 to force the input to be processed as MP4.
- Added -mp4 and -in:mp4 to force the input to be processed as MP4.
- CC608 data embedded in a separate stream (as opposed as in the video
stream itself) in MP4 files is now supported (not heavily tested).
stream itself) in MP4 files is now supported (not heavily tested).
This should be rather useful since closed captioned files from iTunes
use this format.
- More CEA-708 work. The debugger is now able to dump the "TV" contents for
the first time. Also, a .srt can be generated, however timing is not quite
good yet (still need to figure out why).
the first time. Also, a .srt can be generated, however timing is not quite
good yet (still need to figure out why).
- Added -svc (or --service) to select the CEA-708 services to be processed.
For example, -svc 1,2 will process the primary and secondary language
services. Valid values are 1-63, where 1 is the primary language, 2 is
@@ -653,9 +704,9 @@ version of CCExtractor.
- Fix: GCC 3.4.4 can now build CCExtractor.
- Fix: Damaged TS packets (those that come with 'error in transport' bit
on) are now skipped.
- Fix: Part of the changes for MP4 support (CC packets buffering in
particular) broke some stuff for other files, causing at least very
annoying character duplication. We hope we've fixed it without breaking
- Fix: Part of the changes for MP4 support (CC packets buffering in
particular) broke some stuff for other files, causing at least very
annoying character duplication. We hope we've fixed it without breaking
anything but please report).
- Some non-interesting cleanup.
@@ -666,13 +717,13 @@ version of CCExtractor.
code, the stream must be a file (no streaming), etc.
- Fix: The Windows version was writing text files with double \r.
- Fix: Closed captions blocks with no data could cause a crash.
- Fix: -noru (to generate files without duplicate lines in
- Fix: -noru (to generate files without duplicate lines in
roll-up) was broken, with complete lines being missing.
- Fix: bin format not working as input.
- Fix: bin format not working as input.
0.59 (2011-10-07)
-----------------
- More AVC/H.264 work. pic_order_cnt_type != 0 will be processed now.
- More AVC/H.264 work. pic_order_cnt_type != 0 will be processed now.
- Fix: Roll-up captions with interruptions for Text (with ResumeTextDisplay
in the middle of the caption data) were missing complete lines.
- Added a timed text transcript output format, probably only useful for
@@ -695,7 +746,7 @@ version of CCExtractor.
- Added -stdout => If used, the captions will be sent to stdout (console)
instead of file. Combined with -, CCExtractor can work as a filter in
a larger process, receiving the stream from stdin and sending the
captions to stdout.
captions to stdout.
- Some code clean up, minor refactoring.
- Teletext detection (not yet processing).
@@ -704,20 +755,20 @@ version of CCExtractor.
- Implemented new PTS based mode to order the caption information
of AVC/H.264 data streams. The old pic_order_cnt_lsb based method
is still available via the -poc or --usepicorder command switches.
- Removed a couple of those annoying "Impossible!" error messages
- Removed a couple of those annoying "Impossible!" error messages
that appears when processing some (possibly broken, unsure) files.
- Added -nots --notypesettings to prevent italics and underline
- Added -nots --notypesettings to prevent italics and underline
codes from being displayed.
- Note to those not liking the paragraph symbol being used for the
- Note to those not liking the paragraph symbol being used for the
music note: Submit a VALID replacement in latin-1.
- Added preliminary support for multiple program TS files. The
- Added preliminary support for multiple program TS files. The
parameter --program-number (or -pn) will let you choose which
program number to process. If no number is passed and the TS
program number to process. If no number is passed and the TS
file contains more than one, CCExtractor will display a list of
found programs and terminate.
- Added support (basic, because I only received one sample) for some
Hauppauge cards that save CC data in their own format. Use the
parameter -haup to enable it (CCExtractor will display a notice
parameter -haup to enable it (CCExtractor will display a notice
if it thinks that it's processing a Hauppauge capture anyway).
- Fixed bug in roll-up.
- More AVC work, now TS files from echostar that provided garbled
@@ -727,7 +778,7 @@ version of CCExtractor.
0.57 (2010-12-16)
-----------------
- Bug fixes in the Windows version. Some debug code was unintentionally
left in the released version.
left in the released version.
0.56 (2010-12-09)
-----------------
@@ -744,10 +795,10 @@ version of CCExtractor.
- Start implementation of EIA-708 decoding (not active yet).
- Add -gt / --goptime switch to use GOP timing instead of PTS timing.
- Start implementation of AVC/H.264 decoding (not active yet).
- Fixed: The basic problem is that when 24fps movie film gets converted to 30fps NTSC
they repeat every 4th frame. Some pics have 3 fields of CC data with field 3 CC data
belongs to the same channel as field 1. The following pics have the fields reversed
because of the odd number of fields. I used top_field_first to tell when the channels
- Fixed: The basic problem is that when 24fps movie film gets converted to 30fps NTSC
they repeat every 4th frame. Some pics have 3 fields of CC data with field 3 CC data
belongs to the same channel as field 1. The following pics have the fields reversed
because of the odd number of fields. I used top_field_first to tell when the channels
are reversed. See Table 6-1 of the SCTE 20 [Paul Fernquist]
0.54 (2009-04-16)
@@ -757,9 +808,9 @@ version of CCExtractor.
- Improve synchronization of captions for source files with
jumps in their time information or gaps in the caption
information.
- [R. Abarca] Changed Mac script, it now compiles/link
everything from the /src directory.
- It's now possible to have CCExtractor add credits
- [R. Abarca] Changed Mac script, it now compiles/link
everything from the /src directory.
- It's now possible to have CCExtractor add credits
automatically.
- Added a feature to add start and end messages (for credits).
See help screen for details.
@@ -780,13 +831,13 @@ version of CCExtractor.
for Raw Captions With Time). This new format
allows one file to contain all the available
closed caption data instead of just one stream.
- Added --no_progress_bar to disable status
- Added --no_progress_bar to disable status
information (mostly used when debugging, as the
progress information is annoying in the middle
of debug logs).
- The Windows GUI was reported to freeze in some
- The Windows GUI was reported to freeze in some
conditions. Fixed.
- The Windows GUI is now targeted for .NET 2.0
- The Windows GUI is now targeted for .NET 2.0
instead of 3.5. This allows Windows 2000 to run
it (there's not .NET 3.5 for Windows 2000), as
requested by a couple of key users.
@@ -794,17 +845,17 @@ version of CCExtractor.
0.51 (unreleased)
-----------------
- Removed -autopad and -goppad, no longer needed.
- In preparation to a new binary format we have
renamed the current .bin to .raw. Raw files
- In preparation to a new binary format we have
renamed the current .bin to .raw. Raw files
have only CC data (with no header, timing, etc.).
- The input file format (when forced) is now
specified with
specified with
-in=format
such as -in=ts, -in=raw, -in=ps ...
The old switches (-ts, -ps, etc.) still work.
The only exception is -bin which has been removed
(reserved for the new binary format). Use
-in=raw to process a raw file.
-in=raw to process a raw file.
- Removed -d, which when produced a raw file used
a DVD format. This has been merged into a new
output type "dvdraw". So now instead of using
@@ -813,7 +864,7 @@ version of CCExtractor.
- Removed --noff
- Added gui_mode_reports for frontend communications,
see related file.
- Windows GUI rewritten. Source code now included,
- Windows GUI rewritten. Source code now included,
too.
- [Volker] Dish Network clean-up
@@ -826,12 +877,12 @@ version of CCExtractor.
0.49 (2008-12-10)
-----------------
- [Volker] Major MPEG parser rework. Code much
cleaner now.
cleaner now.
- Some stations transmit broken roll-up captions,
and for some reason don't send CRs but RUs...
Added work-around code to make captions readable.
- Started work on EIA-708 (DTV). Right now you can
add -debug-708 to get a dump of the 708 data.
add -debug-708 to get a dump of the 708 data.
An actually useful decoder will come soon.
- Some of the changes MIGHT HAVE BROKEN MythTV's
code. I don't use MythTV myself so I rely on
@@ -847,9 +898,9 @@ version of CCExtractor.
can now process files that are being recorded
at the same time.
- [Volker] Added a new DVR-MS loop - this is
- [Volker] Added a new DVR-MS loop - this is
completely new, DVR-MS specific code, so we no
longer use the generic MPEG code for DVR-MS.
longer use the generic MPEG code for DVR-MS.
DVR-MS should (or will be eventually at least)
be as reliable as TS.
Note: For now, it's only ATSC recordings, not
@@ -868,11 +919,11 @@ version of CCExtractor.
new options.
- Added -lg --largegops
From the help screen:
Each Group-of-Picture comes with timing
information. When this info is too separate
(for example because there are a lot of
frames in a GOP) ccextractor may prefer not
to use GOP timing. Use this option is you
Each Group-of-Picture comes with timing
information. When this info is too separate
(for example because there are a lot of
frames in a GOP) ccextractor may prefer not
to use GOP timing. Use this option is you
need ccextractor to use GOP timing in large
GOPs.
@@ -891,8 +942,8 @@ version of CCExtractor.
0.43 (2008-06-20)
-----------------
- Fixed a bug in the read loop (no less)
that caused some files to fail when
reading without buffering (which is
that caused some files to fail when
reading without buffering (which is
the default in the Linux build).
- Several improvements in the GUI, such as
saving current options as default.
@@ -909,8 +960,8 @@ version of CCExtractor.
-----------------
- Default output is now .srt instead of .bin,
use -raw if you need the data dump instead of
.srt.
- Added -trim, which removes blank spaces at
.srt.
- Added -trim, which removes blank spaces at
the left and rights of each line in .srt.
Note that those spaces are there to help
deaf people know if the person talking is
@@ -920,8 +971,8 @@ version of CCExtractor.
0.40 (2008-05-20)
-----------------
- Fixed a bug in the sanity check function
that caused the Myth branch to abort.
- Fixed a bug in the sanity check function
that caused the Myth branch to abort.
- Fixed the OSX build script, it needed a
new #define to work.
@@ -931,30 +982,30 @@ version of CCExtractor.
have no time information. Also, if in roll-up
mode there will be no repeated lines.
- Lots of changes in the MPEG parser, most of
them submitted by Volker Quetschke.
them submitted by Volker Quetschke.
- Fixed a bug in the CC decoder that could cause
the first line not to be cleared in roll-up
mode.
mode.
- CCExtractor can now follow number sequences in
file names, by suffixing the name with +.
For example,
DVD0001.VOB+
DVD0001.VOB+
means DVD0001.VOB, DVD0002.VOB, etc. This works
for all files, so part001.ts+ does what you
could expect.
- Added -90090 which changes the clock frequency
from the MPEG standard 90000 to 90090. It
from the MPEG standard 90000 to 90090. It
*could* (remains to be seen) help if there are
timing issues.
timing issues.
- Better support for Tivo files.
- By default ccextractor now considers the whole
input file list a one large file, instead of
several, independent, video files. This has
been changed because most programs (for example
DVDDecrypt) just cut the files by size.
If you need the old behaviour (because you
DVDDecrypt) just cut the files by size.
If you need the old behaviour (because you
actually edited the video files and want to
join the subs), use -ve.
@@ -972,7 +1023,7 @@ version of CCExtractor.
that have been added because old behaviour was
annoying to most people: _1 and _2 at the end
of the output file names is now added ONLY if
-12 is used (i.e. when there are two output
-12 is used (i.e. when there are two output
files to produce). So
ccextractor -srt sopranos.mpg
@@ -1033,7 +1084,7 @@ version of CCExtractor.
Alan
Tony
So you get
So you get
You better respect
this robe, Alan.
@@ -1042,7 +1093,7 @@ version of CCExtractor.
have a different spelling file per TV
show, or a large file with a lot of
words, etc.
- ccextractor has been reported to
- ccextractor has been reported to
compile and run on Mac with a minor
change in the build script, so I've
created a mac directory with the
@@ -1056,17 +1107,17 @@ version of CCExtractor.
-----------------
- Added -scr or --screenfuls, to select the
number of screenfuls ccextractor should
write before exiting. A screenful is
write before exiting. A screenful is
a change of screen contents caused by
a CC command (not new characters). In
practice, this means that for .srt each
group of lines is a screenful, except when
using -dru (which produces a lot of
using -dru (which produces a lot of
groups of lines because each new character
produces a new group).
- Completed tables for all encodings.
- Fixed bug in .srt related to milliseconds
in time lines.
in time lines.
- Font colors are back for .srt (apparently
some programs do support them after all).
Use -nofc or --nofontcolor if you don't
@@ -1075,7 +1126,7 @@ version of CCExtractor.
0.32 (unreleased)
-----------------
- Added -delay ms, which adds (or subtracts)
a number of milliseconds to all times in
a number of milliseconds to all times in
.srt/.sami files. For example,
-delay 400
@@ -1106,8 +1157,8 @@ version of CCExtractor.
- Fix in extended char decoding, I wasn't
replacing the previous char.
- When a sequence code was found before
having a PTS, reported time was
undefined.
having a PTS, reported time was
undefined.
0.29 (unreleased)
-----------------
@@ -1132,7 +1183,7 @@ version of CCExtractor.
0.26 (unreleased)
-----------------
- Added -gp (or -goppad) to make ccextractor use
GOP timing. Try it for non TS files where
GOP timing. Try it for non TS files where
subs start OK but desync as the video advances.
0.25 (unreleased)
@@ -1141,7 +1192,7 @@ version of CCExtractor.
-nomyth to prevent the MytvTV code path to be
called. I've seen apparently correct files that
make MythTV's MPEG decoder to choke. So, if it
doesn't work correctly automatically: Try
doesn't work correctly automatically: Try
-nomyth and -myth. Hopefully one of the two
options will work.
@@ -1154,7 +1205,7 @@ version of CCExtractor.
- Reworked input buffer code, faster now.
- Completed MythTV's MPEG decoder for Program Streams,
which results in better processing of some specific
files.
files.
- Automatic file format detection for all kind of
files and closed caption storage method. No need to
tell ccextractor anything about your file (but you
@@ -1163,10 +1214,10 @@ version of CCExtractor.
0.22 (2007-05-15)
-----------------
- Added text mode handling into decoder, which gets rids
- Added text mode handling into decoder, which gets rids
of junk when text mode data is present.
- Added support for certain (possibly non standard
compliant) DVDs that add more captions block in a
compliant) DVDs that add more captions block in a
user data block than they should (such as Red October).
- Fix in roll-up init code that caused the previous popup
captions not to be written to disk.
@@ -1177,13 +1228,13 @@ version of CCExtractor.
-----------------
- Unicode should be decent now.
- Added support for Hauppauge PVR 250 cards, and (possibly)
many others (bttv) with the same closed caption recording
many others (bttv) with the same closed caption recording
format.
This is the result of hacking MythTV's MPEG parser into
CCExtractor. Integration is not very good (to put it
midly) but it seems to work. Depending on the feedback I
may continue working on this or just leave it 'as it'
(good enough).
(good enough).
If you want to process a file generated by one of these
analog cards, use -myth. This is essential as it will
make the program take a totally different code path.
@@ -1193,10 +1244,10 @@ version of CCExtractor.
0.19 (2007-05-03)
-----------------
- Work on Dish Network streams, timing was completely broken.
- Work on Dish Network streams, timing was completely broken.
It's fixed now at least for the samples I have, if it's not
completely fixed let me know. Credit for this goes to
Jack Ha who sent me a couple of samples and a first
Jack Ha who sent me a couple of samples and a first
implementation of a semi working-fix.
- Added support for several input files (see help screen for
details).

View File

@@ -6,10 +6,23 @@ Downloads for precompiled binaries and source code can be found [on our website]
Clone the latest repository from Github
```
```bash
git clone https://github.com/CCExtractor/ccextractor.git
```
### Hardsubx (Burned-in Subtitles) and FFmpeg Versions
CCExtractor's hardsubx feature extracts burned-in subtitles from videos using OCR. It requires FFmpeg libraries. The build system automatically selects appropriate FFmpeg versions for each platform:
- **Linux**: FFmpeg 6.x (default)
- **Windows**: FFmpeg 6.x (default)
- **macOS**: FFmpeg 8.x (default)
You can override the default by setting the `FFMPEG_VERSION` environment variable to `ffmpeg6`, `ffmpeg7`, or `ffmpeg8` before building. This flexibility ensures compatibility with different FFmpeg installations across platforms.
## Docker
You can now use docker image to build latest source of CCExtractor without any environmental hustle. Follow these [instructions](https://github.com/CCExtractor/ccextractor/tree/master/docker/README.md) for building docker image & usage of it.
## Linux
1. Make sure all the dependencies are met.
@@ -17,26 +30,40 @@ git clone https://github.com/CCExtractor/ccextractor.git
Debian:
```bash
sudo apt-get install -y libglew-dev libglfw3-dev cmake gcc libcurl4-gnutls-dev tesseract-ocr tesseract-ocr-dev libleptonica-dev
sudo apt-get install -y libgpac-dev libglew-dev libglfw3-dev cmake gcc libcurl4-gnutls-dev tesseract-ocr libtesseract-dev libleptonica-dev clang libclang-dev
```
RHEL:
RHEL/Fedora:
```bash
yum install -y glew-devel glfw-devel cmake gcc libcurl-devel tesseract-devel leptonica-devel
yum install -y glew-devel glfw-devel cmake gcc libcurl-devel tesseract-devel leptonica-devel clang gpac-devel
```
**Note:** On Ubuntu Version 18.04 (Bionic) and (probably) later, install `libtesseract-dev` rather than `tesseract-ocr-dev`, which does not exist anymore.
Arch:
```bash
sudo paru -S glew glfw curl tesseract leptonica cmake gcc clang gpac
```
or
```bash
sudo pacman -S glew glfw curl tesseract leptonica cmake gcc clang gpac
```
Rust 1.54 or above is also required. [Install Rust](https://www.rust-lang.org/tools/install). Check specific compilation methods below, on how to compile without rust.
**Note:** On Ubuntu Version 23.10 (Mantic) and later, `libgpac-dev` isn't available, you should build gpac from source by following the easy build instructions [here](https://github.com/gpac/gpac/wiki/GPAC-Build-Guide-for-Linux)
**Note:** On Ubuntu Version 18.04 (Bionic) and later, `libtesseract-dev` is installed rather than `tesseract-ocr-dev`, which does not exist anymore.
**Note:** On Ubuntu Version 14.04 (Trusty) and earlier, you should build leptonica and tesseract from source
2. Compiling
### Using the build script
By default build script does not include debugging information hence, you cannot debug the executable produced (i.e. `./ccextractor`) on a debugger. To include debugging information, use the `builddebug` script.
```bash
#Navigate to linux directory and call the build script
# navigate to linux directory and call the build script
cd ccextractor/linux
@@ -44,7 +71,25 @@ cd ccextractor/linux
./build
# compile with debug info
./builddebug
./build -debug # same as ./builddebug
# compile with hardsubx (burned-in subtitle extraction)
# Hardsubx requires FFmpeg libraries. Different FFmpeg versions are used by default:
# - Linux: FFmpeg 6.x (automatic)
# - Windows: FFmpeg 6.x (automatic)
# - macOS: FFmpeg 8.x (automatic)
./build -hardsubx # uses platform-specific FFmpeg version
# To override the default FFmpeg version, set FFMPEG_VERSION:
FFMPEG_VERSION=ffmpeg8 ./build -hardsubx # force FFmpeg 8 on any platform
FFMPEG_VERSION=ffmpeg6 ./build -hardsubx # force FFmpeg 6 on any platform
FFMPEG_VERSION=ffmpeg7 ./build -hardsubx # force FFmpeg 7 on any platform
# [Optional] For custom FFmpeg installations, set these environment variables:
FFMPEG_INCLUDE_DIR=/usr/include
FFMPEG_PKG_CONFIG_PATH=/usr/lib/pkgconfig
# test your build
./ccextractor
@@ -53,7 +98,7 @@ cd ccextractor/linux
### Standard linux compilation through Autoconf scripts
```bash
sudo apt-get install autoconf #Dependency to generate configuration script
sudo apt-get install autoconf # dependency to generate configuration script
cd ccextractor/linux
./autogen.sh
./configure
@@ -69,15 +114,13 @@ sudo make install
### Using CMake
```bash
#Create and navigate to directory where you want to store built files
# create and navigate to directory where you want to store built files
cd ccextractor/
mkdir build
cd build
#Generate makefile using cmake and then compile
cmake ../src/
# generate makefile using cmake and then compile
cmake ../src/ # options here
make
# test your build
@@ -87,37 +130,42 @@ make
sudo make install
```
`cmake` also accepts the argument `-DWITH_OCR=ON` to enable OCR and `-DWITH_RUST=ON` to enable rust.
`cmake` also accepts the options:
`-DWITH_OCR=ON` to enable OCR
`-DWITH_HARDSUBX=ON` to enable burned-in subtitles (requires FFmpeg)
For hardsubx with specific FFmpeg versions:
Set `FFMPEG_VERSION=ffmpeg6` for FFmpeg 6.x (default on Linux and Windows)
Set `FFMPEG_VERSION=ffmpeg7` for FFmpeg 7.x
Set `FFMPEG_VERSION=ffmpeg8` for FFmpeg 8.x
(Defaults: Linux=FFmpeg 6, Windows=FFmpeg 6, macOS=FFmpeg 8)
### Compiling with GUI:
([OPTIONAL] For custom FFmpeg installations, set these environment variables)
To build CCExtractor with a gui you will additionally need to install [GLEW](http://glew.sourceforge.net/build.html) and [GLFW](http://www.glfw.org/docs/latest/compile.html)
FFMPEG_INCLUDE_DIR=/usr/include
FFMPEG_PKG_CONFIG_PATH=/usr/lib/pkgconfig
In order to compile it you'll need to configure it using autoconf by passing the `-with-gui` option.
### Compiling with GUI
```bash
./autogen.sh
./configure --with-gui
make
# make build systemwide
sudo make install
```
Once set up you can run the GUI interface from the terminal `./ccextractorGUI`
The GUI for CCExtractor has been moved to a separate repository ([https://github.com/CCExtractor/ccextractorfluttergui](https://github.com/CCExtractor/ccextractorfluttergui)).
## macOS
1. Make sure all the dependencies are met. They can be installed via Homebrew as
1. Make sure all the dependencies are met. Decide if you want OCR; if so, you'll need to install tesseract and leptonica.
Dependencies can be installed via Homebrew as:
```bash
brew install pkg-config
brew install autoconf automake libtool
brew install cmake gpac
# optional if you want OCR:
brew install tesseract
brew install leptonica
# optional if you want hardsubx (burned-in subtitle extraction):
brew install ffmpeg
```
Use pkg-config to verify tesseract and leptonica dependencies, e.g.
If configuring OCR, use pkg-config to verify tesseract and leptonica dependencies, e.g.
```bash
pkg-config --exists --print-errors tesseract
@@ -130,17 +178,12 @@ pkg-config --exists --print-errors lept
```bash
cd ccextractor/mac
./build.command OCR
./build.command # basic build
./build.command -ocr # build with OCR support
./build.command -hardsubx # build with hardsubx (uses FFmpeg 8 by default on macOS)
# test your build
./ccextractor
```
If you don't want the OCR capabilities, then you don't need to configure the tesseract and leptonica packages, and build it with just
```bash
cd ccextractor/mac
./build.command
# Override FFmpeg version if needed:
FFMPEG_VERSION=ffmpeg7 ./build.command -hardsubx
# test your build
./ccextractor
@@ -149,27 +192,29 @@ cd ccextractor/mac
#### Using CMake
```bash
#Create and navigate to directory where you want to store built files
# create and navigate to directory where you want to store built files
cd ccextractor/
mkdir build
cd build
#Generate makefile using cmake and then compile
cmake ../src/
# generate makefile using cmake and then compile
cmake ../src/ # options here
make
# test your build
./ccextractor
```
`cmake` also accepts the options:
`-DWITH_OCR=ON` to enable OCR
`-DWITH_HARDSUBX=ON` to enable burned-in subtitles
#### Standard compilation through Autoconf scripts:
```bash
cd ccextractor/mac
./autogen.sh
./configure
./configure
make
# test your build
@@ -178,27 +223,49 @@ make
#### Compiling with GUI:
To use CCExtractor with a gui you will additionally need to install GLEW and GLFW. You can do that by installing it via homebrew using:
```bash
brew install glfw
brew install glew
```
In order to compile it you'll need to configure it using autoconf by passing the `-with-gui` option.
```bash
./autogen.sh
./configure --with-gui
make
```
Once set up you can run the GUI interface from the terminal `./ccextractorGUI`
The GUI for CCExtractor has been moved to a separate repository ([https://github.com/CCExtractor/ccextractorfluttergui](https://github.com/CCExtractor/ccextractorfluttergui)).
## Windows
Dependencies are clang and rust. To enable OCR, rust x86_64-pc-windows-msvc or i686-pc-windows-msvc target should be installed
GPAC is also required, you can install it through chocolatey:
```
choco install gpac
```
Other dependencies are required through vcpkg, so you can follow below steps:
1. Download vcpkg (prefer version `2023.02.24` as it is supported)
2. Integrate vcpkg into your system, run the below command in the downloaded vcpkg folder:
```
vcpkg integrate install
```
3. Set Environment Variable for Vcpkg triplet, you can choose between x86 or x64 based on your system.
```
setx VCPKG_DEFAULT_TRIPLET "x64-windows-static"
setx RUSTFLAGS "-Ctarget-feature=+crt-static"
```
4. Install dependencies from vcpkg
In this step we are using `x64-windows-static` triplet, but you will have to use the triplet you set in Step 3
if building Debug-Full, Release-Full (HardSubx)
```
vcpkg install ffmpeg leptonica tesseract --triplet x64-windows-static
```
Note: Windows builds use FFmpeg 6 by default. To override:
```
set FFMPEG_VERSION=ffmpeg8
msbuild ccextractor.sln /p:Configuration=Debug-Full /p:Platform=x64
```
otherwise if you have Debug, Release
```
vcpkg install libpng --triplet x64-windows-static
```
Note: Following screenshots and steps are based on Visual Studio 2017, but they should be more or less same for other versions.
1.Open `windows/` directory to locate `ccextractor.vcxproj`, `ccextractorGUI.vcxproj` (blue arrows) and `ccextractor.sln` (red arrow).
1.Open `windows/` directory to locate `ccextractor.vcxproj` and `ccextractor.sln` (red arrow).
![Project Files](img/projectFiles.png)
@@ -234,6 +301,22 @@ cmake ../src/ -G "Visual Studio 14 2015"
cmake --build . --config Release --ccextractor
```
### Using MSBuild
Run the following command in `windows/` directory
```bash
msbuild ccextractor.sln /p:Configuration=Release /p:Platform=x64
```
Different configuration options are,
| Configuration | Platform | Rust target required |
| ------------- |:-------------:| -----:|
| Release | x64 | default |
| Debug | x64 | default |
| Release-Full(OCR) | Win32 | i686-pc-windows-msvc |
| Debug-Full(OCR) | Win32 | i686-pc-windows-msvc |
## Building Installation Packages
### Arch Linux

View File

@@ -16,10 +16,24 @@ Note:If you installed ffmpeg on non-standard location, please change/update your
environment variable `$PATH` and `$LD_LIBRARY_PATH`
### Download and Install FFmpeg on your Windows pc:
Download prebuilt library from following link:
http://ffmpeg.zeranoe.com/builds/
1. Download vcpkg (prefer version `2023.02.24` as it is supported)
2. Integrate vcpkg into your system, run the below command in the downloaded vcpkg folder:
```
vcpkg integrate install
```
3. Set Environment Variable for Vcpkg triplet, you can choose between x86 or x64 based on your system.
```
setx VCPKG_DEFAULT_TRIPLET "x64-windows-static"
setx RUSTFLAGS "-Ctarget-feature=+crt-static"
```
4. Install ffmpeg from vcpkg
You need to download Shared Versions to run the program and Dev Versions to compile.
In this step we are using `x64-windows-static` triplet, but you will have to use the triplet you set in Step 3
```
vcpkg install ffmpeg --triplet x64-windows-static
```
## How to compile ccextractor
@@ -27,24 +41,8 @@ You need to download Shared Versions to run the program and Dev Versions to comp
`make ENABLE_FFMPEG=yes`
### On Windows:
#### Put the path of libs/include of ffmpeg library in library paths.
1. In visual studio 2013 right click <Project> and select property.
2. Select Configuration properties in left panel(column) of property.
3. Select VC++ Directory.
4. In the right pane, in the right-hand column of the VC++ Directory property, open the drop-down menu and choose Edit.
5. Add path of Directory where you have kept uncompressed library of FFmpeg.
#### Set preprocessor flag `ENABLE_FFMPEG=1`
1. In visual studio 2013 right click <Project> and select property.
1. In visual studio 2022 right click <Project> and select property.
2. In the left panel, select Configuration Properties, C/C++, Preprocessor.
3. In the right panel, in the right-hand column of the Preprocessor Definitions property, open the drop-down menu and choose Edit.
4. In the Preprocessor Definitions dialog box, add `ENABLE_FFMPEG=1`. Choose OK to save your changes.
#### Add library in linker
1. Open property of project
2. Select Configuration properties
3. Select Linker in left panel(column)
4. Select Input
5. Select Additional dependencies in right panel
6. Add all FFmpeg's lib in new line

View File

@@ -54,6 +54,32 @@ To build the program with hardsubx support,
NOTE: The build has been tested with FFMpeg version 3.1.0, and Tesseract 3.04.
macOS
-----
Install the required dependencies using Homebrew:
brew install tesseract leptonica ffmpeg
To build the program with hardsubx support, use one of these methods:
== Using build.command (Recommended):
cd ccextractor/mac
./build.command -hardsubx
== Using autoconf:
cd ccextractor/mac
./autogen.sh
./configure --enable-hardsubx --enable-ocr
make
== Using cmake:
cd ccextractor
mkdir build && cd build
cmake -DWITH_OCR=ON -DWITH_HARDSUBX=ON ../src/
make
NOTE: The -hardsubx parameter uses a single dash (not --hardsubx).
Windows
-------

View File

@@ -93,7 +93,7 @@ Download prebuild library of leptonica and tesseract from following link
https://drive.google.com/file/d/0B2ou7ZfB-2nZOTRtc3hJMHBtUFk/view?usp=sharing
put the path of libs/include of leptonica and tesseract in library paths.
1. In visual studio 2013 right click <Project> and select property.
1. In visual studio 2022 right click <Project> and select property.
2. Select Configuration properties in left panel(column) of property.
3. Select VC++ Directory.
4. In the right pane, in the right-hand column of the VC++ Directory property, open the drop-down menu and choose Edit.
@@ -101,7 +101,7 @@ put the path of libs/include of leptonica and tesseract in library paths.
Set preprocessor flag ENABLE_OCR=1
1. In visual studio 2013 right click <Project> and select property.
1. In visual studio 2022 right click <Project> and select property.
2. In the left panel, select Configuration Properties, C/C++, Preprocessor.
3. In the right panel, in the right-hand column of the Preprocessor Definitions property, open the drop-down menu and choose Edit.
4. In the Preprocessor Definitions dialog box, add ENABLE_OCR=1. Choose OK to save your changes.

View File

@@ -0,0 +1,71 @@
# C to Rust Migration Guide
## Porting C Functions to Rust
This guide outlines the process of migrating C functions to Rust while maintaining compatibility with existing C code.
### Step 1: Identify the C Function
First, identify the C function you want to port. For example, let's consider a function named `net_send_cc()` in a file called `networking.c`:
```c
void net_send_cc() {
// Some C code
}
```
### Step 2: Create a Pure Rust Equivalent
Write an equivalent function in pure Rust within the `lib_ccxr` module:
```rust
fn net_send_cc() {
// Rust equivalent code to `net_send_cc` function in `networking.c`
}
```
### Step 3: Create a C-Compatible Rust Function
In the `libccxr_exports` module, create a new function that will be callable from C:
```rust
#[no_mangle]
pub extern "C" fn ccxr_net_send_cc() {
net_send_cc() // Call the pure Rust function
}
```
### Step 4: Declare the Rust Function in C
In the original C file (`networking.c`), declare the Rust function as an external function:
```rust
extern void ccxr_net_send_cc();
```
### Step 5: Modify the Original C Function
Update the original C function to use the Rust implementation when available:
```c
void net_send_cc() {
#ifndef DISABLE_RUST
return ccxr_net_send_cc(); // Use the Rust implementation
#else
// Original C code
#endif
}
```
## Rust module system
- `lib_ccxr` crate -> **The Idiomatic Rust layer**
- Path: `src/rust/lib_ccxr`
- This layer will contain the migrated idiomatic Rust. It will have complete documentation and tests.
- `libccxr_exports` module -> **The C-like Rust layer**
- Path: `src/rust/src/libccxr_exports`
- This layer will have function names the same as defined in C but with the prefix `ccxr_`. These are the functions defined in the `lib_ccx` crate under appropriate modules. And these functions will be provided to the C library.
- Ex: `extern "C" fn ccxr_<function_name>(<args>) {}`

View File

@@ -1,821 +0,0 @@
# Documentation
## CCExtractor Graphical User Interface
### Code Structure:
```
src/GUI
├── activity.c -Activity window definitions
├── activity.h -Activity window declarations
├── ccextractorGUI.c -Contains main() and GUI code for 'Main' Tab + 'Menu'
├── ccextractorGUI.h -Function and structure declarations
├── ccx_cli_thread.c -All the functions (definitions) passed in threads
├── ccx_cli_thread.h -Function, variables & structs declaration used in thread
├── command_builder.c -Builds command to pass to CLI CCExtractor
├── command_builder.h -Function, variables & structs declaration used
├── file_browser.c -Function definition for File Browser
├── file_browser.h -Function, struct & variable declaration
├── nuklear_lib -Diretory contains Library Files
│ ├── nuklear_glfw_gl2.h -GLFW backend source header to interact with Nuklear
│ └── nuklear.h -Nuklear library source code
├── popups.c -Function definitions for all Popups used
├── popups.h -Function & network struct declaration for all Popups
├── preview.c -Preview window definitions
├── preview.h -Preview window definitions
├── save_load_data.c -Function definition to save last run state
├── save_load_data.h -Function declaration to save last run state
├── stb_image.h -Code to load images
├── tabs.c -Function definitions for all tabs except 'Main' tab
├── tabs.h -Function, variable and structure declarations
├── terminal.c -Code for terminal Window
└── win_dirent.h -Dirent API for Windows
```
### File by File functions:
activity.c
[nk_begin](#nk-begin)(ctx, "Activity", nk_rect(x, y, width, height), NK_WINDOW_TITLE|NK_WINDOW_BACKGROUND);
[nk_end](#nk-end)(ctx);
[nk_layout_row_dynamic](#nk-layout-row-dynamic)(ctx, 40, 1);
[nk_label_wrap](#nk-label-wrap)(ctx, [main_settings](#struct-main-tab)->activity_string[i]);
[nk_window_is_closed](#nk-window-is-closed)(ctx, "Activity");
activity.h
int [activity](#func-activity)(struct [nk_context](#nk-context) &ast;ctx, int x, int y, int width, int height, struct [main_tab](#struct-main-tab) &ast;main_settings);
ccextractorGUI.c
[nk_menubar_begin](#nk-menubar-begin)(ctx);
[nk_layout_row_begin](#nk-layout-row-begin)(ctx, NK_STATIC, 30, 3);
[nk_layout_row_push](#nk-layout-row-push)(ctx, 80);
[nk_menu_begin_label](#nk-menu-begin-label)(ctx, "Preferences", NK_TEXT_LEFT, [nk_vec2](#nk-vec2)(120, 200));
[nk_menu_end](#nk-menu-end)(ctx);
[nk_menubar_end](#nk-menubar-end)(ctx);
[nk_layout_space_begin](#nk-layout-space-begin)(ctx, NK_STATIC, 15, 1);
[nk_layout_space_end](#nk-layout-space-end)(ctx);
[nk_style_push_vec2](#nk-style-push-vec2)(ctx, &ctx->style.window.spacing, [nk_vec2(](#nk-vec2)0, 0));
[nk_style_push_float](#nk-style-push-float)(ctx, &ctx->style.button.rounding, 0);
[nk_button_label](#nk-label-button)(ctx, names[i]);
[nk_style_pop_float](#nk-style-pop-float)(ctx);
[nk_group_begin](#nk-group-begin)(ctx, "Advanced Tabs", NK_WINDOW_NO_SCROLLBAR);
[nk_group_end](#nk-group-end)(ctx);
[nk_layout_row](#nk-layout-row)(ctx, NK_DYNAMIC, 20, 3, ratio_adv_mode);
[nk_spacing](#nk-spacing)(ctx, 1);
[nk_checkbox_label](#nk-checkbox-label)(ctx, "Advanced Mode", &advanced_mode_check);
[nk_option_label](#nk-option-label)(ctx, "Extract from files below:", [main_settings](#struct-main-tab).port_or_files == FILES));
[nk_selectable_label](#nk-selectable-label)(ctx, [truncate_path_string](#func-truncate-path-string)([main_settings](#struct-main-tab).filenames[i]), NK_TEXT_LEFT, &[main_settings](#struct-main-tab).is_file_selected[i]);
[nk_combo](#nk-combo)(ctx, [main_settings](#struct-main-tab).port_type, 2, [main_settings](#struct-main-tab).port_select, 20, [nk_vec2](#nk-vec2)_(85,100));
[nk_label](#nk-label)(ctx, "Drag and Drop files for extraction.", NK_TEXT_CENTERED
[nk_progress](#nk-progress)(ctx, &[main_settings](#struct-main-tab).progress_cursor, 101, nk_true);
ccextractorGUI.h
void [setup_main_settings](#func-setup-main-settings)(struct main_tab &ast;main_settings);
char&ast; [truncate_path_string](#func-truncate-path-string)(char &ast;filePath);
void [remove_path_entry](#func-remove-path-entry)(struct [main_tab](#struct-main-tab) &ast;main_settings, int indexToRemove);
ccx_cli_thread.c || ccx_cli_thread.h
void&ast; [read_activity_data](#func-read-activity-data)(void &ast;read_args);
void&ast; [read_data_from_thread](#func-read-data-from-thread)(void&ast; read_args);
void&ast; [extract_thread](#func-extract-thread)(void&ast; extract_args);
void&ast; [feed_files_for_extraction](#func-feed-files-for-extraction)(void&ast; file_args);
void [setup_and_create_thread](#fun-setup-and-create-thread)(struct [main_tab](#struct-main-tab) &ast;main_settings, struct [built_string](#struct-built-string) &ast;command);
void&asst; [find_hd_homerun_devices](#func-hd-homerun-devices)(void &ast;args);
void&ast; [setup_hd_homerun_device](#func-setup-hd-homerun-device)(void &ast;args);
command_builder.c || command_builder.h
void [command_builder](#func-command-builder)(struct [built_string](#struct-built-string) &ast;command,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [main_tab](#struct-main-tab) &ast;main_settings,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [network_popup](#struct-network-popup) &ast;network_settings,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [input_tab](#struct-input-tab) &ast;input,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [advanced_input_tab](#struct-advanced-input-tab) &ast;advanced_input,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [output_tab](#struct-output-tab) &ast;output,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [decoders_tab](#struct-output-tab) &ast;decoders,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [credits_tab](#struct-output-tab) &ast;credits,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [debug_tab](#struct-debug-tab) &ast;debug,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [burned_subs_tab](#struct-debug-tab) &ast;burned_subs);
file_browser.c || file_browser.h
void [die](#func-die)(const char &ast;fmt, ...);
char&ast; [file_load](#func-file-load)(const char&ast; path, size_t&ast; siz);
char&ast; [str_duplicate](#func-str-duplicate)(const char &ast;src);
void [dir_free_list](#func-dir-free-list)(char &ast;&ast;list, size_t size);
char&ast;&ast; [dir_list](#func-dir-list)(const char &ast;dir, int return_subdirs, size_t &ast;count);
struct file_group [FILE_GROUP](#func-file-group)(enum file_groups group, const char &ast;name, struct nk_image &ast;icon);
struct file [FILE_DEF](#func-file-def)(enum file_types type, const char &ast;suffix, enum file_groups group);
struct nk_image&ast; [media_icon_for_file](#func-media-icon-for-file)(struct media &ast;media, const char &ast;file);
void [media_init](#func-media-init)(struct media &ast;media);
void [file_browser_reload_directory_content](#func-file-browser-reload-directory-content)(struct file_browser &ast;browser, const char &ast;path);
void [get_drives](#func-get-drives)(struct file_browser &ast;browser);
void [file_browser_init](#func-file-browser-init)(struct file_browser &ast;browser, struct media &ast;media);
void [file_browser_free](#func-file-browser-free)(struct file_browser &ast;browser);
int [file_browser_run](#func-file-browser-run)(struct file_browser &ast;browser, struct [nk_context](#nk-context) &ast;ctx, struct [main_tab](#struct-main-tab) &ast;main_settings, struct [output_tab](#struct-output-tab) &ast;output, struct [debug_tab](#struct-debug-tab) &ast;debug, struct [hd_homerun_tab](#struct-hd-homerun-tab) &ast;hd_homerun);
popups.c || popups.h
void [draw_network_popup](#func-draw-network-popup)(struct [nk_context](#nk-context) &ast;ctx, int &ast;show_preferences_network, struct [network_popup](#struct-network-popup) &ast;network_settings);
void [draw_getting_started_popup](#func-draw-getting-started-popup)(struct [nk_context](#nk-context) &ast;ctx, int &ast;show_getting_started);
void [draw_about_ccx_popup](#func-draw-about-ccx-popup)(struct [nk_context](#nk-context) &ast;ctx, int &ast;show_about_ccx, struct nk_user_font &ast;droid_big, struct nk_user_font &ast;droid_head);
void [draw_progress_details_popup](#func-draw-progress-details-popup)(struct [nk_context](#nk-context) &ast;ctx, int &ast;show_progress_details, struct [main_tab](#struct-main-tab) &ast;main_settings);
void [draw_color_popup](#func-draw-color-popup)(struct [nk_context](#nk-context) &ast;ctx, struct [output_tab](#struct-output-tab) &ast;output);
void [draw_thread_popup](#fun-draw-thread-popup)(struct [nk_context](#nk-context) &ast;ctx, int &ast;show_thread_popup);
void [setup_network_settings](#func-setup-network-settings)(struct [network_popup](#struct-network-popup) &ast;network_settings);
preview.c || preview.h
int [preview](#func-preview)(struct [nk_context](#nk-context) &ast;ctx, int x, int y, int width, int height, struct [main_tab](#struct-main-tab) &ast;main_settings);
save_load_data.c || save_load_data.h
void [load_data](#func-load-data)(FILE *file,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [main_tab](#struct-main-tab) &ast;main_settings,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [input_tab](#struct-input-tab) &ast;input,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [advanced_input_tab](#struct-advanced-input-tab) &ast;advanced_input,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [output_tab](#struct-output-tab) &ast;output,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [decoders_tab](#struct-decoders-tab) &ast;decoders,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [credits_tab](#struct-credits-tab) &ast;credits,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [debug_tab](#struct-debug-tab) &ast;debug,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [hd_homerun_tab](#struct-hd-homerun-tab) &ast;hd_homerun,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [burned_subs_tab](#struct-burned-subs-tab) &ast;burned_subs);
void [save_data](#func-save-data)(FILE *file,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [main_tab](#struct-main-tab) &ast;main_settings,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [input_tab](#struct-input-tab) &ast;input,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [advanced_input_tab](#struct-advanced-input-tab) &ast;advanced_input,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [output_tab](#struct-output-tab) &ast;output,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [decoders_tab](#struct-decoders-tab) &ast;decoders,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [credits_tab](#struct-credits-tab) &ast;credits,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [debug_tab](#struct-debug-tab) &ast;debug,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [hd_homerun_tab](#struct-hd-homerun-tab) &ast;hd_homerun,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct [burned_subs_tab](#struct-burned-subs-tab) &ast;burned_subs);
void [write_credits](#func-write-credits)(FILE* file, struct [credits_tab](#struct-credits-tab) &ast;credits);
void [read_credits](#func-read-credits)(FILE* file, struct [credits_tab](#struct-credits-tab) &ast;credits);
terminal.c
int [terminal](#func-terminal)(struct [nk_context](#nk-context) &ast;ctx, int x, int y, int width, int height, char &ast;command);
### About CCExtractor specific functions
#### int <a id="func-activity">activity</a>(struct nk_context &ast;ctx, int x, int y, int width, int height, struct [main_tab](#struct-main-tab) &ast;main_settings);
##### Info:
--Contains the procedure to be carried out when Activity Window is toggled.
##### Parameters:
* &ast;ctx - pointer to `nk_context` structure.
* x - X co-ordinate to draw Activity Window
* y - Y co-ordinate to draw Activty Window.
* width - width of window to draw.
* height - height of window to draw.
* &ast;main_settings - pointer to [`main_tab`](#struct-main-tab) structure.
##### Return Type: int
* Returns non-zero value if window is not closed.
* Returns zero if window is closed.
#### void <a id="func-setup-main-settings">setup_main_settings</a>(struct [main_tab](#struct-main-tab) &ast;main_settings);
##### Info:
Setups the required defaults of variables in [`main_tab`](#struct-main-tab) structure.
##### Parameters:
* &ast;main_settings - pointer to [`main_tab`](#struct-main-tab) structure.
##### Return Type: void
#### char* <a id="func-truncate-path-string">truncate_path_string</a>(char &ast;filePath);
##### Info:
Truncated the Path String of file to visible area using `...`
##### Parameters:
* &ast;filePath - Pointer to string to be truncated.
##### Return Type: *char
* Returns pointer to truncated string.
#### void <a id="func-remove-path-entry">remove_path_entry</a>(struct [main_tab](#struct-main-tab) &ast;main_settings, int indexToRemove);
##### Info:
Removes the selected path in the extraction queue (Selected entry's index is passed).
##### Parameters:
* &ast;main_settings - pointer to [`main_tab`](#struct-main-tab) structure.
* indexToRemove - index of the string to be removed from dynamic array of many strings.
##### Return Type: void
#### void&ast; <a id="func-read-activity-data">read_activity_data</a>(void &ast;read_args);
##### Info:
Reads activity data related to CCExtractor on `stdout`. And outputs to activity window (Updates variables that code of activity window uses).
##### Parameters:
* &ast;read_args - Pointer to void, because thread functions don't allow any datatype as argument or return type. Therefore they are passed as void then typecasted later in the function.
##### Return type: void&ast;
#### void&ast; <a id="func-read-data-from-thread>read_data_from_thread</a>(void&ast; read_args);
##### Info:
Reads data from`--gui_mode_reports` redirected from `stderr` to a file. Reads the subtitles extracted in realtime and updates the variables for the same, updates the state of progress bar. Also, lanches [read_activity_data](#func-read-activity-data) in a new thread.
##### Parameters:
* &ast;read_args - Pointer to void, because thread functions don't allow any datatype as argument or return type. Therefore they are passed as void then typecasted later in the function.
##### Return type: void&ast;
#### void&ast; <a id="func-extract-thread">extract_thread</a>(void&ast; extract_args);
##### Info:
Passes command with all options from GUI to CLI CCExtractor.
##### Parameters:
* &ast;extract_args - Pointer to void, because thread functions don't allow any datatype as argument or return type. Therefore they are passed as void then typecasted later in the function.
##### Return type: void&ast;
#### void&ast; <a id="func-feed-files-for-extraction">feed_files_for_extraction</a>(void&ast; file_args);
##### Info:
Feeds file by file to a new thread and waits until its extraction is done. This is done until all the files in extraction queue are extracted.
##### Parameters:
* &ast;file_args - Pointer to void, because thread functions don't allow any datatype as argument or return type. Therefore they are passed as void then typecasted later in the function.
##### Return type: void&ast;
#### void <a id="func-setup-and-create-thread">setup_and_create_thread</a>(struct [main_tab](#struct-main-tab) &ast;main_settings, struct [built_string](#struct-built-string) &ast;command);
##### Info:
Initialises some values for the structure used in thread arguments and creates [feed_files_for_extraction](#feed-files-for-extraction).
##### Parameters:
* &ast;main_settings - Pointer to `main_tab` struct.
* &ast;command - Pointer to `built_string` struct.
##### Return type: void&ast;
#### void&ast; <a id="func-hind-hd-homerun-devices">find_hd_homerun_devices</a>(void &ast;args);
Finds devices connected to HD HomeRun Network.
#### Parameters:
* &ast;args - Pointer to void, because thread functions don't allow any datatype as argument or return type. Therefore they are passed as void then typecasted later in the function.
#### Return type: void&ast;
#### void&ast; <a id="func-setup-hd-homerun-device">setup_hd_homerun_device</a>(void &ast;args);
##### Info:
Sets up various parameters required to extract subtitle from incoming stream from a HD HomeRun Device.
##### Parameters:
* &ast;args - Pointer to void, because thread functions don't allow any datatype as argument or return type. Therefore they are passed as void then typecasted later in the function.
##### Return type: void&ast;
#### void [command_builder](#func-command-builder)(struct [built_string](#struct-built-string) &ast;command, struct [main_tab](#struct-main-tab) &ast;main_settings, struct [network_popup](#struct-network-popup) &ast;network_settings, struct [input_tab](#struct-input-tab) &ast;input, struct [advanced_input_tab](#struct-advanced-input-tab) &ast;advanced_input, struct [output_tab](#struct-output-tab) &ast;output, struct [decoders_tab](#struct-output-tab) &ast;decoders, struct [credits_tab](#struct-output-tab) &ast;credits, struct [debug_tab](#struct-debug-tab) &ast;debug, struct [burned_subs_tab](#struct-debug-tab) &ast;burned_subs);
##### Info:
Fetches the options from the whole GUI and adds the respective CLI commands to the `term_string` in `built_string` struct.
##### Parameters:
* &ast;command - Pointer to `built_string` command.
* &ast;main_settings - Pointer to `main_tab` struct.
* &ast;network_settings - Pointer to `network_popup` struct.
* &ast;input - Pointer to `input_tab` struct.
* &ast;advance_input - Pointer to `advanced_input` struct.
* &ast;output - Pointer to `output_tab` struct.
* &ast;decoders - Pointer to `decoders_tab` struct.
* &ast;credits - Pointer to `credits_tab` struct.
* &ast;debug - Pointer to `debug_tab` struct.
* &ast;burned_subs - Pointer to `burned_subs_tab` struct.
##### Return type: void
#### void <a id="func-die">die</a>(const char &ast;fmt, ...);
##### Info:
Custom function to generate error if something in File Browser goes wrong.
##### Parameters:
* &ast;fmt - Format of char string along with place holder for variables.
* ... - Variables in order of their specified place holder.
##### Return type: void
#### char&ast; <a id="func-file-load">file_load</a>(const char&ast; path, size_t&ast; siz);
##### Info:
Custom function to load file and read data from loaded file.
##### Parameters:
* &ast;path - Pointer to string literal (Path of the file).
* &ast;siz - Size of string literal provided (To allocate memory accordingly).
##### Return type: void
#### char&ast; <a id="func-str-duplicate">str_duplicate</a>(const char &ast;src);
##### Info:
Dynamically copies specified string to memory.
##### Parameters:
* &ast;src - The String to be copied.
##### Return type: char&ast;
* Pointer to the string in the memory.
#### void <a id="func-dir-free-list">dir_free_list</a>(char &ast;&ast;list, size_t size);
##### Info:
Frees the memory allocated to Files' and Directories' name and path.
##### Parameters:
* &ast;&ast;char - Pointer to list (array of strings) to be freed
##### Return type: void
#### char&ast;&ast; <a id="func-dir-list">dir_list</a>(const char &ast;dir, int return_subdirs, size_t &ast;count);
##### Info:
Opens the selected directory and adds its path to list and returns the same list.
#####Parameters:
* &ast;dir - Pointer to string (name of directory to be opened).
* return_subdirs - `nk_true` if subdirectories are to be returned then.
* &ast;count - Number of directories in opened directories.
#### Retrun type: char&ast;&ast;
* Pointer to List (Array of strings, name of directories and files) is returned.
#### struct file_group <a id="func-file-group">FILE_GROUP</a>(enum file_groups group, const char &ast;name, struct nk_image &ast;icon);
##### Info:
Initialises variables for `file_group` struct.
##### Parameters:
* group - specifies to which group does the file belong to. Selected from `file_groups` enum, like `FILE_GROUP_MUSIC`.
* &ast;name - Pointer to a string literal (to set `name` member in `file_group`.
* &ast;icon - Pointer to `nk_image` struct (Holds attributes for loaded image file) to set to `icon`member of `file_group`.
##### Returnt type: struct `file_group`
* Returns a `file_group` instance with set variables.
#### struct file <a id="func-file-def">FILE_DEF</a>(enum file_types type, const char &ast;suffix, enum file_groups group);
##### Info:
Initialises variables for `file` struct.
##### Parameters:
* type - specifies which type does the file belong to. Selected from `file_types` enum, like `FILE_TEXT`.
* &ast;suffix - Pointer to string( to set `suffix` member in `file`).
* group - specifies to which group does the file belong to. Selected from `file_groups` enum, like `FILE_GROUP_MUSIC`.
##### Return type: struct `file`
* Returns a `file` instance with set variables.
#### struct nk_image&ast; <a id="func-media-icon-for-file">media_icon_for_file</a>(struct media &ast;media, const char &ast;file);
##### Info:
Analyses the files and checks to which `file` or `file_group` they belong and assign appropriate icon to the file and returns the same.
##### Parameters:
* &ast;media - pointer to `media` struct.
* &ast;file - pointer to string literal (name of file with extension)
##### Return type: struct `nk_image`&ast;
* Returns appropriate `nk_image` corresponding to the file.
#### void <a id="func-media-init">media_init</a>(struct media &ast;media);
##### Info:
Assigns icons to `file` and `file_group` members from.
##### Parameters:
* &ast;media - pointer to `media` struct.
#### Return type: void
#### void <a is="func-file-browser-reload-directory-content">file_browser_reload_directory_content</a>(struct file_browser &ast;browser, const char &ast;path);
##### Info:
Updates various variables related to Files/Directories path and names when screen of File Browser reloads. (Due to clicking on a directory or any other button leading to different directory).
##### Parameters:
* &ast;browser - Pointer to `file_browser` struct.
* &ast;path - Path of the new directory whose contents are to be reloaded and showed on file browser.
##### Return type: void
#### void <a id="func-get-drives">get_drives</a>(struct file_browser &ast;browser);
##### Info:
NOTE: Windows Specific Function.
Detects the number of drives and their respective Drive Letters to show the same in File Browser.
#####Parameters:
* &ast;browser - pointer to `file_browser` struct.
##### Return type: void
#### void <a id="func-file-browser-init">file_browser_init</a>(struct file_browser &ast;browser, struct media &ast;media);
##### Info:
Initialised various variables/attributes required whenever the File Browser is run.
##### Parameters:
* &ast;browser - Pointer to `file_browser` struct.
* &ast;media - pointer to `media` struct.
##### Return type: void
#### void <a id="func-file-browser-free">file_browser_free</a>(struct file_browser &ast;browser);
##### Info:
Frees the memory allocated to various variables in [file_browser_init](#func-file-browser-init).
##### Parameters:
* &ast;browser - pointer to `file_browser` struct.
##### Return type: void
#### int <a id="func-file-browser-run">file_browser_run</a>(struct file_browser &ast;browser, struct [nk_context](#nk-context) &ast;ctx, struct [main_tab](#struct-main-tab) &ast;main_settings, struct [output_tab](#struct-output-tab) &ast;output, struct [debug_tab](#struct-debug-tab) &ast;debug, struct [hd_homerun_tab](#struct-hd-homerun-tab) &ast;hd_homerun);
##### Info:
Provides runtime of File Browser on GUI.
##### Parameters:
* &ast;browser - pointer to `file_browser` struct.
* &ast;ctx - pointer to `nk_context` struct.
* &ast;main_settings - pointer to `main_tab` struct.
* &ast;output - poiter to `output_tab` struct.
* &ast;debug - pointer to `debug_tab` struct.
* &ast;hd_homerun - pointer to `hd_homerun_tab` struct.
##### Return type: int
* Returns `1` if any File name/path is copied to current variable.
* Returns `0` otherwise.
#### void <a -d="func-draw-network-popup">draw_network_popup</a>(struct [nk_context](#nk-context) &ast;ctx, int &ast;show_preferences_network, struct [network_popup](#struct-network-popup) &ast;network_settings);
##### Info:
Draws popup with Network Settings on GUI.
##### Parameters:
* &ast;ctx - pointer to `nk_context` struct.
* &ast;show_preferences_network - pointer to variable status if which triggers the popup.
* &ast;network_settings - pointer to `network_popup` struct.
##### Return type: void
#### void <a id="func-draw-getting-started-popup">draw_getting_started_popup</a>(struct [nk_context](#nk-context) &ast;ctx, int &ast;show_getting_started);
##### Info:
Draws popup on screen which shows Getting Started Info.
##### Parameters:
* &ast;ctx - pointer to `nk_context` struct.
* &ast;show_getting_started - pointer to variable status if which triggers the popup.
##### Return type: void
#### void <a id="func-draw-about-ccx-popup">draw_about_ccx_popup</a>(struct [nk_context](#nk-context) &ast;ctx, int &ast;show_about_ccx, struct nk_user_font &ast;droid_big, struct nk_user_font &ast;droid_head);
##### Info:
Draws popup on screen containing information about CCExtractor.
##### Parameters:
* &ast;ctx - pointer to `nk_context` struct.
* &ast;show_about_ccx - pointer to variable status if which triggers the popup.
* &ast;droid_big - pointer to `nk_user_font` struct.
* &ast;droid_head - pointer to `nk_user_font` struct.
##### Return type: void
#### void <a id="func-draw-progress-details-popup">draw_progress_details_popup</a>(struct [nk_context](#nk-context) &ast;ctx, int &ast;show_progress_details, struct [main_tab](#struct-main-tab) &ast;main_settings);
##### Info:
Draws popup on screen which shows progress details.
##### Parameters:
* &ast;ctx - pointer to `nk_context` struct.
* &ast;show_pogress_details - pointer to variable status if which triggers the popup.
* &ast;main_settings - pointer to `main_tab` struct.
##### Return type: void
#### void <a id="func-draw-color-popup">draw_color_popup</a>(struct [nk_context](#nk-context) &ast;ctx, struct [output_tab](#struct-output-tab) &ast;output);
##### Info:
Draws popup on screen which shows color-picker.
##### Parameters:
* &ast;ctx - pointer to `nk_context` struct.
* &ast;output - pointer to `output_tab` struct.
##### Return type: void
#### void <a id="func-draw-thread-popup">draw_thread_popup</a>(struct [nk_context](#nk-context) &ast;ctx, int &ast;show_thread_popup);
##### Info:
This popup is shown if anyhow the GUI is unable to read file.
##### Parameters:
* &ast;ctx - pointer to `nk_context` struct.
* &ast;show_thread_popup - pointer to variable status if which triggers the popup.
##### Return type: void
#### void <a id="func-setup-network-settings">setup_network_settings</a>(struct [network_popup](#struct-network-popup) &ast;network_settings);
##### Info:
Sets up defaults for Network Settings.
##### Parameters:
* &ast;network_settings - pointer to `network_popup` struct.
##### Return type: void
#### int <a id="func-preview">preview</a>(struct [nk_context](#nk-context) &ast;ctx, int x, int y, int width, int height, struct [main_tab](#struct-main-tab) &ast;main_settings);
##### Info:
Draws `Preview` Nuklear window and shows preview strings (lines of subtitles extracted in realtime).
##### Parameters:
* &ast;ctx - pointer to `nk_context` struct.
* x - X co-ordinate from where to draw window.
* y - Y co-ordinate from where to draw window.
* width - width of window.
* height - height of window.
* &ast;main_settings - pointer to `main_tab ` struct.
##### Return type:
* Returns non-zero value if window is not closed.
* Returns zero if window is closed.
#### void <a id="func-load-data">load_data</a>(FILE *file, struct [main_tab](#struct-main-tab) &ast;main_settings, struct [input_tab](#struct-input-tab) &ast;input, struct [advanced_input_tab](#struct-advanced-input-tab) &ast;advanced_input, struct [output_tab](#struct-output-tab) &ast;output, struct [decoders_tab](#struct-decoders-tab) &ast;decoders, struct [credits_tab](#struct-credits-tab) &ast;credits, struct [debug_tab](#struct-debug-tab) &ast;debug, struct [hd_homerun_tab](#struct-hd-homerun-tab) &ast;hd_homerun, struct [burned_subs_tab](#struct-burned-subs-tab) &ast;burned_subs);
##### Info:
Loads values of all the variables stored in a file at last exit of GUI.
##### Parameters:
* &ast;file - pointer to `FILE`.
* &ast;main_settings - pointer to `main_tab` struct.
* &ast;intput - pointer to `input_tab` struct.
* &ast;advanced_input - pointer to `advanced_input_tab` struct.
* &ast;output - pointer to `output_tab` struct.
* &ast;decoders - pointer to `decoders_tab` struct.
* &ast;credits - poitner to `credits_tab` struct.
* &ast;debug - pointer to `debug_tab` struct.
* &ast;hd_homerun - pointer to `hd_homerun_tab` struct.
* &ast;burned_subs - pointer to `burned_subs_tab` struct.
##### Return type: void
#### void <a id="func-save-data">save_data</a>(FILE *file, struct [main_tab](#struct-main-tab) &ast;main_settings, struct [input_tab](#struct-input-tab) &ast;input, struct [advanced_input_tab](#struct-advanced-input-tab) &ast;advanced_input, struct [output_tab](#struct-output-tab) &ast;output, struct [decoders_tab](#struct-decoders-tab) &ast;decoders, struct [credits_tab](#struct-credits-tab) &ast;credits, struct [debug_tab](#struct-debug-tab) &ast;debug, struct [hd_homerun_tab](#struct-hd-homerun-tab) &ast;hd_homerun, struct [burned_subs_tab](#struct-burned-subs-tab) &ast;burned_subs);
##### info:
Saves values of all the variables as a "Current State" in a file on exit.
##### Parameters:
* &ast;file - pointer to `FILE`.
* &ast;main_settings - pointer to `main_tab` struct.
* &ast;intput - pointer to `input_tab` struct.
* &ast;advanced_input - pointer to `advanced_input_tab` struct.
* &ast;output - pointer to `output_tab` struct.
* &ast;decoders - pointer to `decoders_tab` struct.
* &ast;credits - poitner to `credits_tab` struct.
* &ast;debug - pointer to `debug_tab` struct.
* &ast;hd_homerun - pointer to `hd_homerun_tab` struct.
* &ast;burned_subs - pointer to `burned_subs_tab` struct.
##### Return type: void
#### void <a id="func-write-credits">write_credits</a>(FILE &ast;file, struct [credits_tab](#struct-credits-tab) &ast;credits);
##### Info:
Writes Credits to files after some operations, since extra`\n` character gives problems while reading file.
##### Parameters:
* &ast;file - pointer to `FILE`.
* &ast;credits - pointer to `credits_tab` struct.
##### Return type: void
#### void <a id="func-read-credits">read_credits</a>(FILE* file, struct [credits_tab](#struct-credits-tab) &ast;credits);
##### Info:
Reads credits from file in a specific format (as written by [write_credits](#func-write-credits)) from file.
##### Parameters:
* &ast;file - pointer to `FILE`.
* &ast;credits - pointer to `credits_tab` struct.
##### Return type: void
#### int <a id="func-terminal">terminal</a>(struct [nk_context](#nk-context) &ast;ctx, int x, int y, int width, int height, char &ast;command);
##### Info:
Writes the command string (that would be passed to CLI CCExtractor) in "Terminal" Nuklear Window.
##### Parameters:
* &ast;ctx - pointer to `nk_context` struct.
* x - X co-ordinate from where to draw the window.
* y - Y co-ordinate from where to draw the window.
* width - Width of the window.
* height - height of the window.
* &ast;command - String to write on window (the command to be passed).
##### Return type: int
* Returns non-zero value if window is not closed.
* Returns zero if window is closed.
### About CCExtractor specific Structures/Variables
#### <a id="struct-main-tab">main_tab</a>
##### Info:
Contains all the variables for `Main` tab.
##### Variables worth noting:
* `int is_file_browser_active`
* `nk_true` if File Browser is triggered by any event.
* `nk_false` otherwise.
* `int scaleWindowForFileBrowser`
* Sets to `nk_true` if `is_file_browser_active` is `nk_true` to scale the `glfwWindow` to required size to accommodate File Browser.
* Sets to `nk_false` otherwise.
#### <a id="struct-input-tab">input_tab</a>
##### Info:
Contains all variables to hold data of options selected/changed and view dynamically generated data to GUI in `Input` tab.
#### <a id="struct-advanced-input">advanced_input_tab</a>
Info:
Contains all variables to hold data of options selected/changed and view dynamically generated data to GUI in `Advanced Input` tab.
#### <a id="struct-output-tab">output_tab</a>
#####Info:
Contains all variables to hold data of options selected/changed and view dynamically generated data to GUI in `Advanced Input` tab.
#### <a id="struct-decoders-tab">decoders_tab</a>
##### Info:
Contains all variables to hold data of options selected/changed and view dynamically generated data to GUI in `Decoders` tab.
#### <a id="struct-credits-tab">credits_tab</a>
##### Info:
Contains all variables to hold data of options selected/changed and view dynamically generated data to GUI in `Credits` tab.
#### <a id="struct-debug-tab">debug_tab</a>
##### Info:
Contains all variables to hold data of options selected/changed and view dynamically generated data to GUI in `Debug` tab.
#### <a id="struct-hd-homerun-tab">hd_homerun_tab</a>
##### Info:
Contains all variables to hold data of options selected/changed and view dynamically generated data to GUI in `HDHomeRun` tab.
#### <a id="struct-burned-subs-tab">burned_subs</a>
##### Info:
Contains all variables to hold data of options selected/changed and view dynamically generated data to GUI in `HDHomeRun` tab.
#### <a id="struct-network-popup">networ_popup</a>
##### Info:
Contains all the variables to store all the Network related options or showing them in GUI dynamically.
### About Nuklear Specific functions
#### int <a id="nk-begin">nk_begin</a>(struct nk_context&ast;, const char &ast;title, struct nk_rect bounds, nk_flags flags);
##### Info:
Draws a basic(and blank) window(Nuklear Window inside main GLFW window) to hold other Nuklear widgets.
##### Parameters:
* nk_context&ast; - Pointer to `nk_context` structure.
* &ast;title - Title for the so drawn Nuklear Window.
* bounds - instance of `nk_rect` structure to hold co-ordinates, width and height of the Nuklear Window.
* flags - Which flags to pass( from those contained in `enum flags`) to change behaviour of the Nuklear Window.
##### Return Type: int
* Returns true if window creation is successful.
* Returns false if window creation fails.
#### void <a id="nk-end">nk_end</a>(struct nk_context *ctx)
##### Info:
Marks the end of the Nuklear Window.
##### Parameter:
* &ast;ctx - Pointer to `nk_context` structure.
##### Return type: void
#### void <a id="nk-layout-row-dynamic">nk_layout_row_dynamic</a>(struct nk_context&ast;, float height, int cols);
##### Info:
Used to define a dynamic row layout(to hold widgets), dynamic in the sense that the width is dynamically allocated to widgets.
##### Parameters:
* &ast;nk_context - Pointer to `nk_context` structure.
* height - height to set for widgets of that row.
* cols - Columns to set for layout (generally the number of widgets to place).
##### Return Type: void
#### void <a id="nk-label-wrap">nk_label_wrap</a>(struct nk_context&ast;, const char&ast;);
##### Info:
Writes a label ( A plain String) and wraps it to the next line if the border of Nuklear Window, Group or Popup is reached.
*Note*: If the text wraps to next line, height for a new line must be considered while defining a layout, else the wrapped text won't be visible (but it will be there).
##### Parameters:
* nk_context&ast; - Pointer to `nk_context` structure.
* char&ast; - Pointer to string literal (to view).
#### int <a id="nk-window-is-closed">nk_window_is_closed</a>(struct nk_context &ast;ctx, const char &ast;name);
##### Info:
Checks if the active Nuklear Window is closed (by any trigger).
##### Parameters:
* &ast;ctx - Pointer to `nk_context` structure.
* &ast;name - Pointer to String literal(Name of window to check).
##### Return type: int
* Returns true if window is closed (by any trigger).
* Returns false of window is not closed.
#### void <a id="nk-menubar-begin">nk_menubar_begin</a>(struct nk_context &ast;ctx);
##### Info:
Marks the end of Menu Bar definition(Menubar code).
##### Parameters:
* &ast;ctx - Pointer to `nk_context` structure.
##### Return type: void
#### void <a id="nk-layout-row-begin">nk_layout_row_begin</a>(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols);
##### Info:
Marks the beginning of custom layout. Which means, marking that layout has begun, now the widgets will be pushed row by row as per requirement using [nk_layout_row_push](#nk-layout-row-push).
##### Parameters:
* &ast;ctx - Pointer to `nk_context` structure.
* fmt - Layout format from provided formats (`enum nk_layout_format`), example - `NK_STATIC`, `NK_DYNAMIC`.
* row_height - height of row pushed.
* cols - Number of columns pushed in row.
##### Return type: void
#### void <a id="nk-layout-row-push">nk_layout_row_push</a>(struct nk_context&ast;, float value);
##### Info:
Pushes a row to hold widgets after defining the beginning of custom layout by [nk_layout_row_begin](#nk-layout-row-begin).
##### Parameters:
* nk_context&ast; - Pointer to `nk_context` structure.
* value - ratio or width of the widget to be pushed next.
##### Return Type: void
#### int <a id="nk-menu-begin-label">nk_menu_begin_label</a>(struct nk_context &ast;ctx, const char &ast;text, nk_flags align, struct [nk_vec2](#nk-vec2) size);
##### Info:
The label of the Menu Item to be pushed, for example - "Preferences" is marked by this function.
##### Parameters:
* &ast;ctx - pointer to `nk_context` structure.
* &ast;text - pointer to string literal (Title of the Menu, example - "Settings").
* align - alignment enumeration in `nk_flags`, example `NK_TEXT_LEFT`.
* size - Size of label (as `nk_vec2` struct)
##### Return type: int
* Returns true if label creation successful.
* Returns false if label creation fails.
#### void <a id="nk-menubar-end">nk_menubar_end</a>(struct nk_context&ast;);
##### Info:
Marks the end of the MenuBar definition.
##### Parameters:
* nk_context&ast; - Pointer to `nk_context` structure.
##### Return type: void
#### void <a id="nk-layout-space-begin">nk_layout_space_begin</a>(struct nk_context &ast;ctx, enum nk_layout_format fmt, float height, int widget_count);
##### Info:
Marks the beginning of an empty space (Custom space for proper placement of widgets).
##### Parameters:
* &ast;ctx - pointer to `nk_context` structure.
* fmt - Layout format as in `enu nk_layout_format`, example - `NK_STATIC`, `NK_DYNAMIC`.
* height = height of space to be added.
* widget_count - Number of spaces to add.
##### Return type: void
#### void <a id="nk-layout-space-end">nk_layout_space_end</a>(struct nk_context &ast;ctx);
##### Info:
Marks the end of custom space (empty) definition.
##### Parameters:
* &ast;ctx - pointer to `nk_context` structure.
##### Return type: void
#### int <a id="nk-style-push-vec2">nk_style_push_vec2</a>(struct nk_context&ast; struct nk_vec2&ast;, struct nk_vec2);
##### Info:
Comes under `Style Stack`. Used to temporarily modify length, width, spacing related attributes of Styles of Nuklear Context.
##### Parameters:
* nk_context&ast; - Pointer to `nk_context` structure.
* nk_vec2&ast; - Pointer to attribute to be modified.
* nk_vec2&ast; - New value in the form `nk_vec2(x, y)` as an instance of nk_vec2 structure.
##### Return type: int
* Returns true if successful.
* Returns false if unsuccessful.
#### int <a id="nk-style-push-float">nk_style_push_float</a>(struct nk_context&ast;, float&ast;, float);
##### Info:
Comes under `Style Stack`. Used to temporarily modify attributes requiring precision with floating point such as rounding value for buttons.
##### Parameters:
* nk_context&ast; - Pointer to `nk_context` structure.
* float&ast; - Pointer to variable whose value is to be changed.
* float - new value to set.
#### int <a id="nk-button-label">nk_button_label</a>(struct nk_context&ast;, const char &ast;title);
##### Info:
Draws a Button with provided label.
##### Parameters:
* nk_context&ast; - Pointer to `nk_context` struct.
* &ast;title - Pointer to string literal (Label to put on button).
##### Return type: int
* Returns true of Button is clicked.
* Returns false of Button is in 'unclicked' state.
#### int <a id="nk-style-pop-float">nk_style_pop_float</a>(struct nk_context&ast;);
##### Info:
Pops the float values modified off the `Style Stack`. Which means, returns them to original state as they were before being modified by [nk_style_push_float](#nk-style-push-float).
##### Paramaters:
* nk_context&ast; - Pointer to `nk_context` struct.
##### Return type: int
* Returns true if successful.
* Returns false if unsuccessful.
#### int <a id="nk-group-begin">nk_group_begin</a>(struct nk_context &ast;ctx, const char &ast;title, nk_flags flags);
##### Info:
Makes a group with given flags. Looks just like a window created by [nk_begin](#nk-begin) but can be created inside a window.
##### Parameters:
* &ast;ctx - pointer to `nk_context` struct.
* &ast;title - string literal (Title of the group).
* flags - All the required flags among available flags in `nk_flags`.
##### Return Type: int
* Returns false if creation unsuccessful.
* Returns true if creation successful.
#### void <a id="nk-group-end">nk_group_end</a>(struct nk_context &ast;ctx);
##### Info:
Marks the end of the group created by [nk_group_begin](#nk-group-begin).
##### Parameters:
* &ast;ctx - pointer to `nk_context` struct.
##### Return type: void
#### void <a id="nk-layout-row">nk_layout_row</a>(struct nk_context&ast;, enum nk_layout_format, float height, int cols, const float &ast;ratio);
##### Info:
Used to create custom row layout in which widget placement (including spacing) is done using ratios in floating point. Maximum ratio allowed is one. So, if there are two widgets (say buttons) need to placed in 50% available area each. Then `ratio` will be {0.5f, 0.5f}.
##### Parameters:
* nk_context&ast; - pointer to `nk_context` struct.
* nk_layout_format - format from available formats in `enum nk_layout_format` like `NK_STATIC` , `NK_DYNAMIC`.
* height - height of the layout.
* cols - Number of widgets(including spaces) to be used.
* &ast;ratio - Ratio for widget placement.
##### Return type: void
#### void <a id="nk-spacing">nk_spacing</a>(struct nk_context&ast;, int cols);
##### Info:
Used to create spacing (blank) of specified columns.
##### Parameters:
* nk_context&ast; - pointer to `nk_context` struct.
* cols - Number of columns for which spacing has to be true.
##### Return type: void
#### int <a id="nk-checkbox-label">nk_checkbox_label</a>(struct nk_context &ast;ctx, const char &ast;label, int &ast;active);
##### Info:
Creates a checkbox with specified label.
##### Parameters:
* &ast;ctx - Pointer to `nk_context` struct.
* &ast; - Pointer to string literal(Label of checkbox).
* &ast; - Pointer to variable to store the active value. `nk_false` if unchecked, `nk_true` if checked.
##### Return type: int
* Returns false if unable to draw widget or old value of `*active` = new value of `*active`.
* Returns true of old value of `*active` != new value of `*active`.
#### int <a id="nk-option-label">nk_option_label</a>(struct nk_context &ast;ctx, const char &ast;label, int active);
##### Info:
Draws radio button (among radio group) with specified label.
##### Parameters:
* &ast;ctx - pointer to `nk_context` struct.
* &ast;label - Pointer to string literal (label of radio button).
* active - Any check to specify if the radio button is active.
##### Return type: int
* Returns true if radio button is active.
* Returns false if radio button is inactive.
#### int <a id="nk-selectable-label">nk_selectable_label</a>(struct nk_context&ast;, const char&ast;, nk_flags align, int &ast;value);
##### Info:
Draws a selectable label. (Just like a regular [nk_label](#nk-label) but with a difference that it can be selected)
##### Parameters:
* nk_context&ast; - pointer to `nk_context` struct.
* char&ast; - Pointer to string literal (Label to display on GUI).
* align - required alignment flags from `nk_flags` like `NK_TEXT_LEFT`.
* &ast;value - Pointer to integer variable to store the value if the label is triggered or not.
* Sets to `nk_true` if label selected.
* Sets to `nk_false` if label is in unselected state.
##### Return type: int
* Returns false if unable to draw widget or old value of `*value` = new value of `*value`.
* Returns true of old value of `*value` != new value of `*value`.
#### int <a id="nk-combo">nk_combo</a>(struct nk_context&ast;, const char &ast;&ast;items, int count, int selected, int item_height, struct nk_vec2 size);
##### Info:
Draws combobox with given items as array of strings.
##### Parameters:
* nk_context&ast; - Pointer to `nk_context` structure.
* &ast;&ast;items - Array of strings of items to populate the list of combobox.
* count - Number of items in the combobox.
* selected - variable to store the index of selected item.
* item_height - Height to allocate to each item in combobox.
* size - size of combobox after expansion(when dropdown arrow is clicked). Given as [nk_vec2](#nk-vec2)(x, y).
##### Return type: int
* Returns the index of selected item.
#### void <a id="nk-label">nk_label</a>(struct nk_context &ast;ctx, const char &ast;str, nk_flags alignment);
##### Info:
Draws a plain text on Nuklear Window, Popup or group.
##### Parameters:
* &ast;ctx - pointer to `nk_context` structure.
* &ast;str - Pointer to string literal (Text to draw).
* alignment - required flags for text alignment from `nk_flags`, like `NK_TEXT_LEFT`.
##### Return type: void
#### int <a id="nk-progress">nk_progress</a>(struct nk_context &ast;ctx, nk_size &ast;cur, nk_size max, int is_modifyable);
##### Info:
Draws a progress bar.
##### Parameters:
* &ast;ctx - Poitner to `nk_context` struct.
* &ast;cur - Realtime value to update in progress bar.
* max - Maximum value `*cur` can achieve (usually 100, for 100% progress).
* is_modifyable -
* `nk_true` if progress bar can be modified with other events like mouse click and drag.
* `nk_false` if progress bar needs to be modified only by value of `*cur`
##### Return type: int
* Returns false if unable to draw widget or old value of `*cur` = new value of `*cur`.
* Returns true of old value of `*cur` != new value of `*cur`.
### About Nuklear Specific Structures/Variables
#### <a id="nk-context">nk_context</a>
##### Info:
Contains various Variables/attributes related to current Window.
#### <a id="nk-vec2">nk_vec2</a>
##### Info:
A simple structure containing 2 variables `x` and `y`. Used for various purposes where 2 variables are required for example.. using offset for position or size of any widget/window.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 KiB

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 101 KiB

View File

@@ -13,7 +13,7 @@ Step 2) create a separate directory where you want to build the target.
Step 3) make the build system using cmake. Params in [] are optional and have
been explained later in the document.
~> cmake [-DWITH_FFMPEG=ON] [-DWITH_OCR=ON] [-DWITH_SHARING=ON]
~> cmake [-DWITH_FFMPEG=ON] [-DWITH_OCR=ON]
[-DWITH_HARDSUBX=ON] ../src/
Step 4) Compile the code.
@@ -29,14 +29,8 @@ cmake -DWITH_FFMPEG=ON ../src/
If you want to build CCExtractor with OCR you need to pass
cmake -DWITH_OCR=ON ../src/
If you want to build CCExtractor with Sharing and Translating service:
cmake -DWITH_SHARING=ON ../src/
If you want to build CCExtractor with HARDSUBX support
cmake -DWITH_HARDSUBX=ON ../src/
If you want to build CCExtractor with rust enabled you need to pass
cmake -DWITH_RUST=ON ../src/
Hint for looking all the things you want to set from outside
cmake -LAH ../src/

2
linux/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
libccx_rust.a
rust

View File

@@ -1,92 +1,37 @@
AUTOMAKE_OPTIONS = foreign
ACLOCAL_AMFLAGS = -I m4/
bin_PROGRAMS = ccextractor
ccextractor_SOURCES = \
../src/ccextractor.c \
../src/ccextractor.h \
../src/thirdparty/gpacmp4/avc_ext.c \
../src/thirdparty/gpacmp4/avilib.c \
../src/thirdparty/gpacmp4/av_parsers.c \
../src/thirdparty/gpacmp4/base_encoding.c \
../src/thirdparty/gpacmp4/bitstream.c \
../src/thirdparty/gpacmp4/box_code_3gpp.c \
../src/thirdparty/gpacmp4/box_code_adobe.c \
../src/thirdparty/gpacmp4/box_code_apple.c \
../src/thirdparty/gpacmp4/box_code_base.c \
../src/thirdparty/gpacmp4/box_code_drm.c \
../src/thirdparty/gpacmp4/box_dump.c \
../src/thirdparty/gpacmp4/box_code_meta.c \
../src/thirdparty/gpacmp4/box_funcs.c \
../src/thirdparty/gpacmp4/color.c \
../src/thirdparty/gpacmp4/configfile.c \
../src/thirdparty/gpacmp4/data_map.c \
../src/thirdparty/gpacmp4/desc_private.c \
../src/thirdparty/gpacmp4/descriptors.c \
../src/thirdparty/gpacmp4/drm_sample.c \
../src/thirdparty/gpacmp4/error.c \
../src/thirdparty/gpacmp4/gpac_ogg.c \
../src/thirdparty/gpacmp4/hint_track.c \
../src/thirdparty/gpacmp4/hinting.c \
../src/thirdparty/gpacmp4/ipmpx_code.c \
../src/thirdparty/gpacmp4/ipmpx_parse.c \
../src/thirdparty/gpacmp4/isom_intern.c \
../src/thirdparty/gpacmp4/isom_read.c \
../src/thirdparty/gpacmp4/isom_store.c \
../src/thirdparty/gpacmp4/isom_write.c \
../src/thirdparty/gpacmp4/list.c \
../src/thirdparty/gpacmp4/math.c \
../src/thirdparty/gpacmp4/media.c \
../src/thirdparty/gpacmp4/media_odf.c \
../src/thirdparty/gpacmp4/meta.c \
../src/thirdparty/gpacmp4/movie_fragments.c \
../src/thirdparty/gpacmp4/odf_code.c \
../src/thirdparty/gpacmp4/odf_codec.c \
../src/thirdparty/gpacmp4/odf_command.c \
../src/thirdparty/gpacmp4/os_config_init.c \
../src/thirdparty/gpacmp4/os_divers.c \
../src/thirdparty/gpacmp4/os_file.c \
../src/thirdparty/gpacmp4/qos.c \
../src/thirdparty/gpacmp4/sample_descs.c \
../src/thirdparty/gpacmp4/slc.c \
../src/thirdparty/gpacmp4/stbl_read.c \
../src/thirdparty/gpacmp4/stbl_write.c \
../src/thirdparty/gpacmp4/track.c \
../src/thirdparty/gpacmp4/tx3g.c \
../src/thirdparty/gpacmp4/url.c \
../src/thirdparty/gpacmp4/utf.c \
../src/thirdparty/gpacmp4/os_thread.c \
../src/thirdparty/gpacmp4/module.c \
../src/thirdparty/gpacmp4/os_module.c \
../src/thirdparty/gpacmp4/xml_parser.c \
../src/thirdparty/gpacmp4/constants.c \
../src/thirdparty/gpacmp4/gpac/avparse.h \
../src/thirdparty/gpacmp4/gpac/base_coding.h \
../src/thirdparty/gpacmp4/gpac/bitstream.h \
../src/thirdparty/gpacmp4/gpac/color.h \
../src/thirdparty/gpacmp4/gpac/config_file.h \
../src/thirdparty/gpacmp4/gpac/configuration.h \
../src/thirdparty/gpacmp4/gpac/constants.h \
../src/thirdparty/gpacmp4/gpac/events_constants.h \
../src/thirdparty/gpacmp4/gpac/ietf.h \
../src/thirdparty/gpacmp4/gpac/isomedia.h \
../src/thirdparty/gpacmp4/gpac/list.h \
../src/thirdparty/gpacmp4/gpac/maths.h \
../src/thirdparty/gpacmp4/gpac/media_tools.h \
../src/thirdparty/gpacmp4/gpac/mpeg4_odf.h \
../src/thirdparty/gpacmp4/gpac/network.h \
../src/thirdparty/gpacmp4/gpac/revision.h \
../src/thirdparty/gpacmp4/gpac/setup.h \
../src/thirdparty/gpacmp4/gpac/tools.h \
../src/thirdparty/gpacmp4/gpac/utf.h \
../src/thirdparty/gpacmp4/gpac/version.h \
../src/thirdparty/gpacmp4/gpac/iso639.h \
../src/thirdparty/gpacmp4/gpac/internal/avilib.h \
../src/thirdparty/gpacmp4/gpac/internal/isomedia_dev.h \
../src/thirdparty/gpacmp4/gpac/internal/media_dev.h \
../src/thirdparty/gpacmp4/gpac/internal/odf_dev.h \
../src/thirdparty/gpacmp4/gpac/internal/odf_parse_common.h \
../src/thirdparty/gpacmp4/gpac/internal/ogg.h \
/usr/include/gpac/avparse.h \
/usr/include/gpac/base_coding.h \
/usr/include/gpac/bitstream.h \
/usr/include/gpac/color.h \
/usr/include/gpac/config_file.h \
/usr/include/gpac/configuration.h \
/usr/include/gpac/constants.h \
/usr/include/gpac/events_constants.h \
/usr/include/gpac/ietf.h \
/usr/include/gpac/isomedia.h \
/usr/include/gpac/list.h \
/usr/include/gpac/maths.h \
/usr/include/gpac/media_tools.h \
/usr/include/gpac/mpeg4_odf.h \
/usr/include/gpac/network.h \
/usr/include/gpac/revision.h \
/usr/include/gpac/setup.h \
/usr/include/gpac/tools.h \
/usr/include/gpac/utf.h \
/usr/include/gpac/version.h \
/usr/include/gpac/iso639.h \
/usr/include/gpac/internal/avilib.h \
/usr/include/gpac/internal/isomedia_dev.h \
/usr/include/gpac/internal/media_dev.h \
/usr/include/gpac/internal/odf_dev.h \
/usr/include/gpac/internal/odf_parse_common.h \
/usr/include/gpac/internal/ogg.h \
../src/thirdparty/libpng/pngstruct.h \
../src/thirdparty/libpng/pngpriv.h \
../src/thirdparty/libpng/pnginfo.h \
@@ -115,9 +60,10 @@ ccextractor_SOURCES = \
../src/lib_ccx/activity.h \
../src/lib_ccx/asf_constants.h \
../src/lib_ccx/avc_functions.h \
../src/lib_ccx/bitstream.h \
../src/lib_ccx/cc_bitstream.h \
../src/lib_ccx/ccx_common_option.c \
../src/lib_ccx/ccx_common_common.c \
../src/lib_ccx/compile_info_real.h \
../src/lib_ccx/utility.c \
../src/lib_ccx/activity.c \
../src/lib_ccx/asf_functions.c \
@@ -177,10 +123,6 @@ ccextractor_SOURCES = \
../src/lib_ccx/ccx_gxf.c \
../src/lib_ccx/ccx_gxf.h \
../src/lib_ccx/ccx_mp4.h \
../src/lib_ccx/ccx_share.c \
../src/lib_ccx/ccx_share.h \
../src/lib_ccx/ccx_sub_entry_message.pb-c.c \
../src/lib_ccx/ccx_sub_entry_message.pb-c.h \
../src/lib_ccx/compile_info.h \
../src/lib_ccx/compile_info_real.h \
../src/lib_ccx/configuration.c \
@@ -260,9 +202,7 @@ ccextractor_SOURCES = \
../src/thirdparty/utf8proc/utf8proc.h \
../src/thirdparty/lib_hash/sha2.c \
../src/thirdparty/lib_hash/sha2.h \
../src/thirdparty/protobuf-c/protobuf-c.c \
../src/thirdparty/protobuf-c/protobuf-c.h \
../src/thirdparty/zvbi/bcd.h \
../src/lib_ccx/zvbi/bcd.h \
../src/lib_ccx/zvbi/bit_slicer.c \
../src/lib_ccx/zvbi/bit_slicer.h \
../src/lib_ccx/zvbi/decoder.c \
@@ -274,7 +214,7 @@ ccextractor_SOURCES = \
../src/lib_ccx/zvbi/sampling_par.h \
../src/lib_ccx/zvbi/sliced.h \
../src/lib_ccx/zvbi/zvbi_decoder.h \
../src/freetype/* \
../src/freetype/* \
../src/thirdparty/freetype/autofit/autofit.c \
../src/thirdparty/freetype/base/ftbase.c \
../src/thirdparty/freetype/base/ftbbox.c \
@@ -303,7 +243,7 @@ ccextractor_SOURCES = \
../src/thirdparty/freetype/cff/cff.c \
../src/thirdparty/freetype/cid/type1cid.c \
../src/thirdparty/freetype/gzip/ftgzip.c \
../src/thirdparty/freetype/include/ft2build.h \
../src/thirdparty/freetype/include/ft2build.h \
../src/thirdparty/freetype/lzw/ftlzw.c \
../src/thirdparty/freetype/pcf/pcf.c \
../src/thirdparty/freetype/pfr/pfr.c \
@@ -318,37 +258,55 @@ ccextractor_SOURCES = \
../src/thirdparty/freetype/type42/type42.c \
../src/thirdparty/freetype/winfonts/winfnt.c
ccextractor_CFLAGS = -std=gnu99 -Wno-write-strings -Wno-pointer-sign -D_FILE_OFFSET_BITS=64 -DVERSION_FILE_PRESENT -DFT2_BUILD_LIBRARY -DGPAC_DISABLE_VTT -DGPAC_DISABLE_OD_DUMP -DGPAC_DISABLE_REMOTERY -DNO_GZIP -DGPAC_HAVE_CONFIG_H
if SYS_IS_APPLE_SILICON
ccextractor_SOURCES += ../src/thirdparty/libpng/arm/arm_init.c \
../src/thirdparty/libpng/arm/filter_neon_intrinsics.c \
../src/thirdparty/libpng/arm/palette_neon_intrinsics.c
endif
ccextractor_CPPFLAGS =-I../src/lib_ccx/ -I../src/thirdparty/gpacmp4/ -I../src/thirdparty/libpng/ -I../src/thirdparty/zlib/ -I../src/thirdparty/zvbi/ -I../src/thirdparty/lib_hash/ -I../src/thirdparty/protobuf-c/ -I../src/thirdparty -I../src/ -I../src/thirdparty/freetype/include/
ccextractor_CFLAGS = -std=gnu99 -Wno-write-strings -Wno-pointer-sign -D_FILE_OFFSET_BITS=64 -DVERSION_FILE_PRESENT -DFT2_BUILD_LIBRARY -DGPAC_DISABLE_VTT -DGPAC_DISABLE_OD_DUMP -DGPAC_DISABLE_REMOTERY -DNO_GZIP
ccextractor_CPPFLAGS =-I../src/lib_ccx/ -I/usr/include/ -I../src/thirdparty/libpng/ -I../src/thirdparty/zlib/ -I../src/lib_ccx/zvbi/ -I../src/thirdparty/lib_hash/ -I../src/thirdparty -I../src/ -I../src/thirdparty/freetype/include/
ccextractor_LDADD=-lm -lpthread -ldl
ccextractor_LDADD=-lm -lpthread -ldl -lgpac
if SYS_IS_LINUX
ccextractor_CFLAGS += -O3 -s -DGPAC_CONFIG_LINUX
ccextractor_CFLAGS += -O3 -s
endif
if SYS_IS_MAC
ccextractor_CFLAGS += -DPAC_CONFIG_DARWIN -Dfopen64=fopen -Dopen64=open -Dlseek64=lseek
ccextractor_LDADD += -liconv -lz
ccextractor_LDADD += -liconv -lz
endif
if SYS_IS_64_BIT
ccextractor_CFLAGS += -DGPAC_64_BITS
endif
HARDSUBX_FEATURE_RUST=
if HARDSUBX_IS_ENABLED
ccextractor_CFLAGS += -DENABLE_HARDSUBX
ccextractor_CPPFLAGS+= ${libavcodec_CFLAGS}
ccextractor_CPPFLAGS+= ${libavformat_CFLAGS}
ccextractor_CPPFLAGS+= ${libavfilter_CFLAGS}
ccextractor_CPPFLAGS+= ${libavutil_CFALGS}
ccextractor_CPPFLAGS+= ${libswscale_CFLAGS}
# HARDSUBX requires tesseract/leptonica for OCR (same as OCR feature)
ccextractor_CPPFLAGS+= ${tesseract_CFLAGS}
ccextractor_CPPFLAGS+= ${lept_CFLAGS}
AV_LIB = ${libavcodec_LIBS}
AV_LIB += ${libavformat_LIBS}
AV_LIB += ${libavfilter_LIBS}
AV_LIB += ${libavutil_LIBS}
AV_LIB += ${libswscale_LIBS}
ccextractor_LDADD += $(AV_LIB)
# HARDSUBX requires tesseract/leptonica libs for OCR
ccextractor_LDADD += ${tesseract_LIBS}
ccextractor_LDADD += ${lept_LIBS}
HARDSUBX_FEATURE_RUST += --features "hardsubx_ocr"
endif
if OCR_IS_ENABLED
@@ -375,64 +333,17 @@ ccextractor_LDADD += $(TESS_LIB)
ccextractor_LDADD += $(LEPT_LIB)
endif
EXTRA_DIST = ../src/thirdparty/gpacmp4/gpac/sync_layer.h ../src/lib_ccx/ccfont2.xbm ../src/thirdparty/utf8proc/utf8proc_data.c fonts/ icon/
ccextractor_LDADD += ./rust/@RUST_TARGET_SUBDIR@/libccx_rust.a
#For GUI
if BUILD_WITH_GUI
bin_PROGRAMS += ccextractorGUI
ccextractorGUI_SOURCES = \
../src/GUI/ccextractorGUI.c \
../src/GUI/ccextractorGUI.h \
../src/GUI/activity.c \
../src/GUI/activity.h \
../src/GUI/terminal.c \
../src/GUI/preview.c \
../src/GUI/preview.h \
../src/GUI/ccx_cli_thread.c \
../src/GUI/ccx_cli_thread.h \
../src/GUI/command_builder.c \
../src/GUI/command_builder.h \
../src/GUI/save_load_data.c \
../src/GUI/save_load_data.h \
../src/GUI/file_browser.c \
../src/GUI/file_browser.h \
../src/GUI/popups.c \
../src/GUI/popups.h \
../src/GUI/tabs.c \
../src/GUI/tabs.h \
../src/GUI/stb_image.h \
../src/GUI/nuklear_lib/nuklear.h \
../src/GUI/nuklear_lib/nuklear_glfw_gl2.h
ccextractorGUI_CFLAGS = -std=gnu99
ccextractorGUI_LDADD = ${glfw3_LIBS}
if SYS_IS_LINUX
ccextractorGUI_CFLAGS += -s -O3 -DUNIX
ccextractorGUI_CFLAGS += ${glew_CFLAGS}
ccextractorGUI_LDADD += ${glew_LIBS}
ccextractorGUI_LDADD += -lX11 -lXinerama -lXcursor -lXi -lXrandr -lXxf86vm -lm -ldl -lpthread
if DEBUG_RELEASE
CARGO_RELEASE_ARGS=
else
CARGO_RELEASE_ARGS=--release
endif
if SYS_IS_MAC
ccextractorGUI_CFLAGS += -O3 -DUNIX
ccextractorGUI_CFLAGS += ${glew_CFLAGS}
ccextractorGUI_LDADD += ${glew_LIBS}
ccextractorGUI_LDFLAGS = -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo
ccextractorGUI_LDADD += -lglfw -lm -L/usr/local/lib -lpthread
endif
./rust/@RUST_TARGET_SUBDIR@/libccx_rust.a:
cd ../src/rust && \
CARGO_TARGET_DIR=../../linux/rust $(CARGO) build $(HARDSUBX_FEATURE_RUST) $(CARGO_RELEASE_ARGS);
if HARDSUBX_IS_ENABLED
if OCR_IS_ENABLED
ccextractorGUI_CFLAGS += -DENABLE_OCR
endif
endif
EXTRA_DIST += ../icon/ ../fonts/
endif
EXTRA_DIST = /usr/include/gpac/sync_layer.h ../src/lib_ccx/ccfont2.xbm ../src/thirdparty/utf8proc/utf8proc_data.c fonts/ icon/

View File

@@ -1,17 +1,47 @@
#!/usr/bin/env bash
BLD_FLAGS="$BLD_FLAGS -std=gnu99 -Wno-write-strings -Wno-pointer-sign -DGPAC_CONFIG_LINUX -D_FILE_OFFSET_BITS=64 -DVERSION_FILE_PRESENT -DENABLE_OCR -DFT2_BUILD_LIBRARY -DGPAC_DISABLE_VTT -DGPAC_DISABLE_OD_DUMP -DGPAC_DISABLE_REMOTERY -DNO_GZIP -DGPAC_HAVE_CONFIG_H"
RUST_LIB="rust/release/libccx_rust.a"
RUST_PROFILE="--release"
while [[ $# -gt 0 ]]; do
case $1 in
-debug)
DEBUG=true
BLD_FLAGS="$BLD_FLAGS -g -fsanitize=address"
RUST_PROFILE=""
RUST_LIB="rust/debug/libccx_rust.a"
shift
;;
-hardsubx)
HARDSUBX=true
# Allow overriding FFmpeg version via environment variable
if [ -n "$FFMPEG_VERSION" ]; then
RUST_FEATURES="--features hardsubx_ocr,$FFMPEG_VERSION"
else
RUST_FEATURES="--features hardsubx_ocr"
fi
BLD_FLAGS="$BLD_FLAGS -DENABLE_HARDSUBX"
BLD_LINKER="$BLD_LINKER -lswscale -lavutil -pthread -lavformat -lavcodec -lavfilter -lxcb-shm -lxcb -lX11 -llzma -lswresample"
shift
;;
-*)
echo "Unknown option $1"
exit 1
;;
esac
done
BLD_FLAGS="$BLD_FLAGS -std=gnu99 -Wno-write-strings -Wno-pointer-sign -D_FILE_OFFSET_BITS=64 -DVERSION_FILE_PRESENT -DENABLE_OCR -DFT2_BUILD_LIBRARY -DGPAC_DISABLE_VTT -DGPAC_DISABLE_OD_DUMP -DGPAC_DISABLE_REMOTERY -DNO_GZIP"
bit_os=$(getconf LONG_BIT)
if [ "$bit_os"=="64" ]
if [ "$bit_os" == "64" ]
then
BLD_FLAGS="$BLD_FLAGS -DGPAC_64_BITS"
fi
BLD_INCLUDE="-I../src -I /usr/include/leptonica/ -I /usr/include/tesseract/ -I../src/lib_ccx/ -I../src/thirdparty/gpacmp4/ -I../src/thirdparty/libpng -I../src/thirdparty/zlib -I../src/lib_ccx/zvbi -I../src/thirdparty/lib_hash -I../src/thirdparty/protobuf-c -I../src/thirdparty -I../src/thirdparty/freetype/include"
BLD_INCLUDE="-I../src -I /usr/include/leptonica/ -I /usr/include/tesseract/ -I../src/lib_ccx/ -I /usr/include/gpac/ -I../src/thirdparty/libpng -I../src/thirdparty/zlib -I../src/lib_ccx/zvbi -I../src/thirdparty/lib_hash -I../src/thirdparty -I../src/thirdparty/freetype/include"
SRC_LIBPNG="$(find ../src/thirdparty/libpng/ -name '*.c')"
SRC_ZLIB="$(find ../src/thirdparty/zlib/ -name '*.c')"
SRC_CCX="$(find ../src/lib_ccx/ -name '*.c')"
SRC_GPAC="$(find ../src/thirdparty/gpacmp4/ -name '*.c')"
SRC_GPAC="$(find /usr/include/gpac/ -name '*.c' 2>/dev/null)"
SRC_HASH="$(find ../src/thirdparty/lib_hash/ -name '*.c')"
SRC_PROTOBUF="$(find ../src/thirdparty/protobuf-c/ -name '*.c')"
SRC_UTF8PROC="../src/thirdparty/utf8proc/utf8proc.c"
SRC_FREETYPE="../src/thirdparty/freetype/autofit/autofit.c
../src/thirdparty/freetype/base/ftbase.c
@@ -54,13 +84,37 @@ SRC_FREETYPE="../src/thirdparty/freetype/autofit/autofit.c
../src/thirdparty/freetype/type1/type1.c
../src/thirdparty/freetype/type42/type42.c
../src/thirdparty/freetype/winfonts/winfnt.c"
BLD_SOURCES="../src/ccextractor.c $SRC_CCX $SRC_GPAC $SRC_ZLIB $SRC_LIBPNG $SRC_HASH $SRC_PROTOBUF $SRC_UTF8PROC $SRC_FREETYPE"
BLD_LINKER="$BLD_LINKER -lm -zmuldefs -l tesseract -l lept -lpthread -ldl"
BLD_SOURCES="../src/ccextractor.c $SRC_CCX $SRC_GPAC $SRC_ZLIB $SRC_LIBPNG $SRC_HASH $SRC_UTF8PROC $SRC_FREETYPE"
BLD_LINKER="$BLD_LINKER -lm -zmuldefs -l tesseract -l leptonica -lpthread -ldl -lgpac"
echo "Running pre-build script..."
./pre-build.sh
echo "Trying to compile..."
BLD_LINKER="$BLD_LINKER ./libccx_rust.a"
echo "Checking for cargo..."
if ! [ -x "$(command -v cargo)" ]; then
echo 'Error: cargo is not installed.' >&2
exit 1
fi
rustc_version="$(rustc --version)"
semver=( ${rustc_version//./ } )
version="${semver[1]}.${semver[2]}.${semver[3]}"
MSRV="1.87.0"
if [ "$(printf '%s\n' "$MSRV" "$version" | sort -V | head -n1)" = "$MSRV" ]; then
echo "rustc >= MSRV(${MSRV})"
else
echo "Minimum supported rust version(MSRV) is ${MSRV}, please upgrade rust"
exit 1
fi
echo "Building rust files..."
(cd ../src/rust && CARGO_TARGET_DIR=../../linux/rust cargo build $RUST_PROFILE $RUST_FEATURES) || { echo "Failed. " ; exit 1; }
cp $RUST_LIB ./libccx_rust.a
echo "Building ccextractor"
out=$((LC_ALL=C gcc $BLD_FLAGS $BLD_INCLUDE -o ccextractor $BLD_SOURCES $BLD_LINKER)2>&1)
res=$?
if [[ $out == *"gcc: command not found"* ]]

View File

@@ -1,109 +0,0 @@
#!/usr/bin/env sh -ex
####################################################################
# setup by tracey apr 2012
# updated version dec 2016
# see: http://www.ccextractor.org/doku.php
####################################################################
# build it static!
# simplest way is with linux alpine
# hop onto box with docker on it and cd to dir of the file you are staring at
# You will get a static-compiled binary and english language library file in the end.
if [ ! -e /tmp/cc/ccextractor-README.txt ]; then
rm -rf /tmp/cc;
mkdir -p -m777 /tmp/cc;
mkdir -p -m777 ../lib/tessdata/;
cp ccextractor-README.txt /tmp/cc/;
sudo docker run -v /tmp/cc:/tmp/cc --rm -it alpine:latest /tmp/cc/ccextractor-README.txt;
# NOTE: _AFTER_ testing/validating, you can promote it from "ccextractor.next" to "ccextractor"... ;-)
cp /tmp/cc/*traineddata ../lib/tessdata/;
chmod go-w ../lib/tessdata/;
exit 0;
fi
# NOW we are inside docker container...
cd /tmp/cc;
# we want tesseract (for OCR)
echo '
http://dl-cdn.alpinelinux.org/alpine/v3.5/main
http://dl-cdn.alpinelinux.org/alpine/v3.5/community
' >| /etc/apk/repositories;
apk update; apk upgrade;
apk add --update bash zsh alpine-sdk perl;
# (needed by various static builds below)
# Even though we're going to (re)builid tesseract from source statically, get its dependencies setup by
# installing it now, too.
apk add autoconf automake libtool tesseract-ocr-dev;
# Now comes the not-so-fun parts... Many packages _only_ provide .so files in their distros -- not the .a
# needed files for building something with it statically. Step through them now...
# libgif
wget https://sourceforge.net/projects/giflib/files/giflib-5.1.4.tar.gz;
zcat giflib*tar.gz | tar xf -;
cd giflib*/;
./configure --disable-shared --enable-static; make; make install;
hash -r;
cd -;
# libwebp
git clone https://github.com/webmproject/libwebp;
cd libwebp;
./autogen.sh;
./configure --disable-shared --enable-static; make; make install;
cd -;
# leptonica
wget http://www.leptonica.org/source/leptonica-1.73.tar.gz;
zcat leptonica*tar.gz | tar xf -;
cd leptonica*/;
./configure --disable-shared --enable-static; make; make install;
hash -r;
cd -;
# tesseract
git clone https://github.com/tesseract-ocr/tesseract;
cd tesseract;
./autogen.sh;
./configure --disable-shared --enable-static; make; make install;
cd -;
# ccextractor -- build static
git clone https://github.com/CCExtractor/ccextractor;
cd ccextractor/linux/;
perl -i -pe 's/O3 /O3 -static /' Makefile;
# quick patch:
perl -i -pe 's/(strchr|strstr)\(/$1((char *)/' ../src/thirdparty/gpacmp4/url.c ../src/thirdparty/gpacmp4/error.c;
set +e; # this _will_ FAIL at the end..
make ENABLE_OCR=yes;
set -e;
# I confess hand-compiling (cherrypicking which .a to use when there are 2, etc.) is fragile...
# But it was the _only_ way I could get a fully static build after hours of thrashing...
gcc -Wno-write-strings -Wno-pointer-sign -D_FILE_OFFSET_BITS=64 -DVERSION_FILE_PRESENT -O3 -std=gnu99 -s -DGPAC_CONFIG_LINUX -DENABLE_OCR -DPNG_NO_CONFIG_H -I/usr/local/include/tesseract -I/usr/local/include/leptonica objs/*.o -o ccextractor \
--static -lm \
/usr/local/lib/libtesseract.a \
/usr/local/lib/liblept.a \
/usr/local/lib/libgif.a \
/usr/local/lib/libwebp.a \
/usr/lib/libjpeg.a \
/usr/lib/libtiff.a \
/usr/lib/libgomp.a \
-lstdc++;
cp ccextractor /tmp/cc/ccextractor.next;
cd -;
# get english lang trained data
wget https://github.com/tesseract-ocr/tessdata/raw/master/eng.traineddata;

230
linux/build_appimage.sh Executable file
View File

@@ -0,0 +1,230 @@
#!/bin/bash
#
# CCExtractor AppImage Build Script
#
# Build variants via BUILD_TYPE environment variable:
# - minimal: Basic CCExtractor without OCR (smallest size)
# - ocr: CCExtractor with OCR support (default)
# - hardsubx: CCExtractor with burned-in subtitle extraction (requires FFmpeg)
#
# Usage:
# ./build_appimage.sh # Builds 'ocr' variant (default)
# BUILD_TYPE=minimal ./build_appimage.sh
# BUILD_TYPE=hardsubx ./build_appimage.sh
#
# Requirements:
# - CMake, GCC, pkg-config, Rust toolchain
# - For OCR: tesseract-ocr, libtesseract-dev, libleptonica-dev
# - For HardSubX: libavcodec-dev, libavformat-dev, libswscale-dev, etc.
# - wget for downloading linuxdeploy
#
set -e
# Build type: minimal, ocr, hardsubx (default: ocr)
BUILD_TYPE="${BUILD_TYPE:-ocr}"
echo "=========================================="
echo "CCExtractor AppImage Builder"
echo "Build type: $BUILD_TYPE"
echo "=========================================="
# Validate build type
case "$BUILD_TYPE" in
minimal|ocr|hardsubx)
;;
*)
echo "Error: Invalid BUILD_TYPE '$BUILD_TYPE'"
echo "Valid options: minimal, ocr, hardsubx"
exit 1
;;
esac
# Store paths
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(dirname "$SCRIPT_DIR")"
BUILD_DIR="$SCRIPT_DIR/appimage_build"
# Clean up function
cleanup() {
if [ -d "$BUILD_DIR" ]; then
echo "Cleaning up build directory..."
rm -rf "$BUILD_DIR"
fi
}
# Cleanup on exit (comment out for debugging)
trap cleanup EXIT
# Create fresh build directory
rm -rf "$BUILD_DIR" 2>/dev/null || true
mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR"
# Determine CMake options based on build type
CMAKE_OPTIONS=""
case "$BUILD_TYPE" in
minimal)
CMAKE_OPTIONS=""
;;
ocr)
CMAKE_OPTIONS="-DWITH_OCR=ON"
;;
hardsubx)
CMAKE_OPTIONS="-DWITH_OCR=ON -DWITH_HARDSUBX=ON -DWITH_FFMPEG=ON"
;;
esac
echo "CMake options: $CMAKE_OPTIONS"
# Configure with CMake
echo "Configuring with CMake..."
cmake $CMAKE_OPTIONS "$REPO_ROOT/src"
# Build
echo "Building CCExtractor..."
make -j$(nproc)
# Verify binary was built
if [ ! -f "$BUILD_DIR/ccextractor" ]; then
echo "Error: ccextractor binary not found after build"
exit 1
fi
echo "Build successful!"
"$BUILD_DIR/ccextractor" --version
# Download linuxdeploy
echo "Downloading linuxdeploy..."
LINUXDEPLOY_URL="https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage"
wget -q --show-progress "$LINUXDEPLOY_URL" -O linuxdeploy-x86_64.AppImage
chmod +x linuxdeploy-x86_64.AppImage
# Create AppDir structure
echo "Creating AppDir structure..."
mkdir -p AppDir/usr/bin
mkdir -p AppDir/usr/share/icons/hicolor/256x256/apps
mkdir -p AppDir/usr/share/applications
mkdir -p AppDir/usr/share/tessdata
# Copy binary
cp "$BUILD_DIR/ccextractor" AppDir/usr/bin/
# Download icon
echo "Downloading icon..."
PNG_URL="https://ccextractor.org/images/ccextractor.png"
if wget -q "$PNG_URL" -O AppDir/usr/share/icons/hicolor/256x256/apps/ccextractor.png 2>/dev/null; then
echo "Icon downloaded successfully"
else
# Create a simple placeholder icon if download fails
echo "Warning: Could not download icon, creating placeholder"
convert -size 256x256 xc:navy -fill white -gravity center -pointsize 40 -annotate 0 "CCX" \
AppDir/usr/share/icons/hicolor/256x256/apps/ccextractor.png 2>/dev/null || \
echo "P3 256 256 255" > AppDir/usr/share/icons/hicolor/256x256/apps/ccextractor.ppm
fi
# Create desktop file
cat > AppDir/usr/share/applications/ccextractor.desktop << 'EOF'
[Desktop Entry]
Type=Application
Name=CCExtractor
Comment=Extract closed captions and subtitles from video files
Exec=ccextractor
Icon=ccextractor
Categories=AudioVideo;Video;
Terminal=true
NoDisplay=true
EOF
# Copy desktop file to AppDir root (required by linuxdeploy)
cp AppDir/usr/share/applications/ccextractor.desktop AppDir/
# Copy icon to AppDir root
cp AppDir/usr/share/icons/hicolor/256x256/apps/ccextractor.png AppDir/ 2>/dev/null || true
# For OCR builds, bundle tessdata
if [ "$BUILD_TYPE" = "ocr" ] || [ "$BUILD_TYPE" = "hardsubx" ]; then
echo "Bundling tessdata for OCR support..."
# Try to find system tessdata
TESSDATA_PATHS=(
"/usr/share/tesseract-ocr/5/tessdata"
"/usr/share/tesseract-ocr/4.00/tessdata"
"/usr/share/tessdata"
"/usr/local/share/tessdata"
)
TESSDATA_SRC=""
for path in "${TESSDATA_PATHS[@]}"; do
if [ -d "$path" ] && [ -f "$path/eng.traineddata" ]; then
TESSDATA_SRC="$path"
break
fi
done
if [ -n "$TESSDATA_SRC" ]; then
echo "Found tessdata at: $TESSDATA_SRC"
# Copy English language data (most common)
cp "$TESSDATA_SRC/eng.traineddata" AppDir/usr/share/tessdata/ 2>/dev/null || true
# Copy OSD (orientation and script detection) if available
cp "$TESSDATA_SRC/osd.traineddata" AppDir/usr/share/tessdata/ 2>/dev/null || true
else
echo "Warning: tessdata not found, downloading English language data..."
wget -q "https://github.com/tesseract-ocr/tessdata/raw/main/eng.traineddata" \
-O AppDir/usr/share/tessdata/eng.traineddata || true
fi
# Create wrapper script that sets TESSDATA_PREFIX
mv AppDir/usr/bin/ccextractor AppDir/usr/bin/ccextractor.bin
cat > AppDir/usr/bin/ccextractor << 'WRAPPER'
#!/bin/bash
SELF_DIR="$(dirname "$(readlink -f "$0")")"
export TESSDATA_PREFIX="${SELF_DIR}/../share/tessdata"
exec "${SELF_DIR}/ccextractor.bin" "$@"
WRAPPER
chmod +x AppDir/usr/bin/ccextractor
fi
# Determine output name based on build type
ARCH="x86_64"
case "$BUILD_TYPE" in
minimal)
OUTPUT_NAME="ccextractor-minimal-${ARCH}.AppImage"
;;
ocr)
OUTPUT_NAME="ccextractor-${ARCH}.AppImage"
;;
hardsubx)
OUTPUT_NAME="ccextractor-hardsubx-${ARCH}.AppImage"
;;
esac
# Build AppImage
echo "Building AppImage..."
export OUTPUT="$OUTPUT_NAME"
# Determine which executable to pass to linuxdeploy
# For OCR builds, we have a wrapper script, so pass the actual binary (.bin)
if [ -f "AppDir/usr/bin/ccextractor.bin" ]; then
LINUXDEPLOY_EXEC="AppDir/usr/bin/ccextractor.bin"
else
LINUXDEPLOY_EXEC="AppDir/usr/bin/ccextractor"
fi
./linuxdeploy-x86_64.AppImage \
--appdir=AppDir \
--executable="$LINUXDEPLOY_EXEC" \
--desktop-file=AppDir/ccextractor.desktop \
--icon-file=AppDir/ccextractor.png \
--output=appimage
# Move to output directory
mv "$OUTPUT_NAME" "$SCRIPT_DIR/"
echo "=========================================="
echo "AppImage built successfully!"
echo "Output: $SCRIPT_DIR/$OUTPUT_NAME"
echo ""
echo "Test with: $SCRIPT_DIR/$OUTPUT_NAME --version"
echo "=========================================="

View File

@@ -1,4 +1,3 @@
#!/usr/bin/env bash
export BLD_FLAGS="-DENABLE_HARDSUBX"
export BLD_LINKER="-lswscale -lavutil -pthread -lavformat -lavcodec -lxcb-shm -lxcb -lX11 -llzma -lswresample"
./build
./build -hardsubx

View File

@@ -1,3 +1,3 @@
#!/usr/bin/env bash
export BLD_FLAGS="-g"
./build
./build -debug

View File

@@ -1,12 +1,12 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
AC_INIT([CCExtractor], [0.92], [carlos@ccextractor.org])
AC_PREREQ([2.71])
AC_INIT([CCExtractor], [0.96], [carlos@ccextractor.org])
AC_CONFIG_AUX_DIR([build-conf])
AC_CONFIG_SRCDIR([../src/ccextractor.c])
AM_INIT_AUTOMAKE([foreign subdir-objects])
AC_CONFIG_MACRO_DIRS([m4])
# Checks for programs.
AC_PROG_CC
@@ -15,7 +15,7 @@ AC_PROG_MAKE_SET
#Checks for "pkg-config" utility
AC_MSG_CHECKING([pkg-config m4 macros])
if test m4_ifdef([PKG_CHECK_MODULES], [yes], [no]) == yes; then
if test m4_ifdef([PKG_CHECK_MODULES], [yes], [no]) = yes; then
AC_MSG_RESULT([yes]);
else
AC_MSG_RESULT([no]);
@@ -25,13 +25,18 @@ fi
# Checks for libraries.
AC_CHECK_LIB([m], [sin], [], [AC_MSG_ERROR(Math library not installed. Install it before proceeding.)])
AC_CHECK_LIB([lept], [getLeptonicaVersion], [HAS_LEPT=1 && PKG_CHECK_MODULES([lept], [lept])], [HAS_LEPT=0])
AC_CHECK_LIB([leptonica], [getLeptonicaVersion], [HAS_LEPT=1 && PKG_CHECK_MODULES([lept], [lept])], [HAS_LEPT=0])
AC_CHECK_LIB([tesseract], [TessVersion], [HAS_TESSERACT=1 && PKG_CHECK_MODULES([tesseract], [tesseract])], [HAS_TESSERACT=0])
AC_CHECK_LIB([avcodec], [avcodec_version], [HAS_AVCODEC=1 && PKG_CHECK_MODULES([libavcodec], [libavcodec])], [HAS_AVCODEC=0])
AC_CHECK_LIB([avformat], [avformat_version], [HAS_AVFORMAT=1 && PKG_CHECK_MODULES([libavformat], [libavformat])], [HAS_AVFORMAT=0])
AC_CHECK_LIB([avutil], [avutil_version], [HAS_AVUTIL=1 && PKG_CHECK_MODULES([libavutil], [libavutil])], [HAS_AVUTIL=0])
AC_CHECK_LIB([swscale], [swscale_version], [HAS_SWSCALE=1 && PKG_CHECK_MODULES([libswscale], [libswscale])], [HAS_SWSCALE=0])
# Check for GPAC library (required for MP4 support)
PKG_CHECK_MODULES([gpac], [gpac], [HAS_GPAC=1], [HAS_GPAC=0])
AS_IF([test $HAS_GPAC -eq 0],
[AC_MSG_ERROR([GPAC library not found. Install gpac-devel (Fedora/RHEL), libgpac-dev (Debian/Ubuntu), or gpac (Arch) before proceeding.])])
# Checks for header files.
AC_CHECK_HEADERS([arpa/inet.h fcntl.h float.h inttypes.h limits.h locale.h malloc.h netdb.h netinet/in.h stddef.h stdint.h stdlib.h string.h sys/socket.h sys/time.h sys/timeb.h termios.h unistd.h wchar.h])
@@ -63,7 +68,7 @@ AC_CHECK_FUNCS([floor ftruncate gethostbyname gettimeofday inet_ntoa mblen memch
# Checks for arguments with configure
AC_ARG_ENABLE([hardsubx],
AC_HELP_STRING([--enable-hardsubx], [Enables extraction of burnt subtitles (hard subtitles)]),
AS_HELP_STRING([--enable-hardsubx], [Enables extraction of burnt subtitles (hard subtitles)]),
[case "${enableval}" in
yes) hardsubx=true ;;
no) hardsubx=false ;;
@@ -71,7 +76,7 @@ AC_HELP_STRING([--enable-hardsubx], [Enables extraction of burnt subtitles (hard
esac],[hardsubx=false])
AC_ARG_ENABLE([ocr],
AC_HELP_STRING([--enable-ocr], [Enables Optical Character Recognition]),
AS_HELP_STRING([--enable-ocr], [Enables Optical Character Recognition]),
[case "${enableval}" in
yes) ocr=true ;;
no) ocr=false ;;
@@ -79,18 +84,57 @@ AC_HELP_STRING([--enable-ocr], [Enables Optical Character Recognition]),
esac],[ocr=false])
AC_ARG_ENABLE([ffmpeg],
AC_HELP_STRING([--enable-ffmpeg], [Enable FFmpeg integration]),
AS_HELP_STRING([--enable-ffmpeg], [Enable FFmpeg integration]),
[case "${enableval}" in
yes) ffmpeg=true ;;
no) ffmpeg=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-ffmpeg]) ;;
esac],[ffmpeg=false])
AC_ARG_WITH([gui],
AC_HELP_STRING([--with-gui], [Builds CCExtractor with GUI (requires GLFW and GLEW)]),
[PKG_CHECK_MODULES([glfw3], [glfw3]) && PKG_CHECK_MODULES([glew], [glew])],
[with_gui=no])
#Add argument for rust
AC_ARG_WITH([rust],
AS_HELP_STRING([--with-rust], [Builds CCExtractor with rust library]),
[with_rust=$withval],
[with_rust=yes])
AC_MSG_CHECKING(whether to build with rust library)
if test "x$with_rust" = "xyes" ; then
AC_MSG_RESULT(yes)
#Check if cargo and rust is installed
AC_PATH_PROG([CARGO], [cargo], [notfound])
AS_IF([test "$CARGO" = "notfound"], [AC_MSG_ERROR([cargo is required])])
AC_PATH_PROG([RUSTC], [rustc], [notfound])
AS_IF([test "$RUSTC" = "notfound"], [AC_MSG_ERROR([rustc is required])])
rustc_version=$(rustc --version)
MSRV="1.87.0"
AX_COMPARE_VERSION($rustc_version, [ge], [$MSRV],
[AC_MSG_RESULT(rustc >= $MSRV)],
[AC_MSG_ERROR([Minimum supported rust version(MSRV) is $MSRV, please upgrade rust])])
else
AC_MSG_RESULT(no)
fi
AM_CONDITIONAL([WITH_RUST], [test "x$with_rust" = "xyes"])
AC_ARG_ENABLE(debug,
AS_HELP_STRING([--enable-debug],
[Build Rust code with debugging information [default=no]]),
[debug_release=$enableval],
[debug_release=no])
AC_MSG_CHECKING(whether to build Rust code with debugging information)
if test "x$debug_release" = "xyes" ; then
AC_MSG_RESULT(yes)
RUST_TARGET_SUBDIR=debug
else
AC_MSG_RESULT(no)
RUST_TARGET_SUBDIR=release
fi
AM_CONDITIONAL([DEBUG_RELEASE], [test "x$debug_release" = "xyes"])
AC_SUBST([RUST_TARGET_SUBDIR])
#Checks and prompts if libraries found/not found to avoild failure while building
AS_IF([ test x$hardsubx = xtrue && test $HAS_AVCODEC -gt 0 ], [AC_MSG_NOTICE(avcodec library found)])
@@ -101,21 +145,21 @@ AS_IF([ test x$hardsubx = xtrue && test $HAS_AVUTIL -gt 0 ], [AC_MSG_NOTICE(avut
AS_IF([ test x$hardsubx = xtrue && test ! $HAS_AVUTIL -gt 0 ], [AC_MSG_ERROR(avutil library not found. Please install the avutil library before proceeding)])
AS_IF([ test x$hardsubx = xtrue && test $HAS_SWSCALE -gt 0 ], [AC_MSG_NOTICE(swscale library found)])
AS_IF([ test x$hardsubx = xtrue && test ! $HAS_SWSCALE -gt 0 ], [AC_MSG_ERROR(swscale library not found. Please install the swscale library before proceeding)])
AS_IF([ (test x$ocr = xtrue || test x$hardsubx = xtrue) && test $HAS_TESSERACT -gt 0 ], [TESS_VERSION=`tesseract --version 2>&1 | grep tesseract` && AC_MSG_NOTICE(tesseract library found... $TESS_VERSION)])
AS_IF([ (test x$ocr = xtrue || test x$hardsubx = xtrue) && test $HAS_TESSERACT -gt 0 ], [TESS_VERSION=$(tesseract --version 2>&1 | grep tesseract) && AC_MSG_NOTICE(tesseract library found... $TESS_VERSION)])
AS_IF([ (test x$ocr = xtrue || test x$hardsubx = xtrue) && test ! $HAS_TESSERACT -gt 0 ], [AC_MSG_ERROR(tesserect library not found. Please install the tesseract library before proceeding)])
AS_IF([ (test x$ocr = xtrue || test x$hardsubx = xtrue) && test $HAS_LEPT -gt 0 ], [LEPT_VERSION=`tesseract --version 2>&1 | grep leptonica` && AC_MSG_NOTICE(leptonica library found... $LEPT_VERSION)])
AS_IF([ (test x$ocr = xtrue || test x$hardsubx = xtrue) && test $HAS_LEPT -gt 0 ], [LEPT_VERSION=$(tesseract --version 2>&1 | grep leptonica) && AC_MSG_NOTICE(leptonica library found... $LEPT_VERSION)])
AS_IF([ (test x$ocr = xtrue || test x$hardsubx = xtrue) && test ! $HAS_LEPT -gt 0 ], [AC_MSG_ERROR(leptonica library not found. Please install the leptonica library before proceeding)])
#AM_CONDITIONAL(s) for setting values to enable/disable flags in Makefile.am
AM_CONDITIONAL(HARDSUBX_IS_ENABLED, [ test x$hardsubx = xtrue ])
AM_CONDITIONAL(OCR_IS_ENABLED, [ test x$ocr = xtrue || test x$hardsubx = xtrue ])
AM_CONDITIONAL(FFMPEG_IS_ENABLED, [ test x$ffmpeg = xtrue ])
AM_CONDITIONAL(TESSERACT_PRESENT, [ test ! -z `pkg-config --libs-only-l --silence-errors tesseract` ])
AM_CONDITIONAL(TESSERACT_PRESENT_RPI, [ test -d "/usr/include/tesseract" && test `ls -A /usr/include/tesseract | wc -l` -gt 0 ])
AM_CONDITIONAL(SYS_IS_LINUX, [ test `uname -s` = "Linux"])
AM_CONDITIONAL(SYS_IS_MAC, [ test `uname -s` = "Darwin"])
AM_CONDITIONAL(BUILD_WITH_GUI, [test "x$with_gui" = "xyes"])
AM_CONDITIONAL(SYS_IS_64_BIT,[test `getconf LONG_BIT` = "64"])
AM_CONDITIONAL(TESSERACT_PRESENT, [ test ! -z "$(pkg-config --libs-only-l --silence-errors tesseract)" ])
AM_CONDITIONAL(TESSERACT_PRESENT_RPI, [ test -d "/usr/include/tesseract" && test $(ls -A /usr/include/tesseract | wc -l) -gt 0 ])
AM_CONDITIONAL(SYS_IS_LINUX, [ test $(uname -s) = "Linux"])
AM_CONDITIONAL(SYS_IS_MAC, [ test $(uname -s) = "Darwin"])
AM_CONDITIONAL(SYS_IS_APPLE_SILICON, [ test $(uname -a | awk '{print $NF}') = "arm64" ])
AM_CONDITIONAL(SYS_IS_64_BIT,[test $(getconf LONG_BIT) = "64"])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

View File

@@ -0,0 +1,177 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_compare_version.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_COMPARE_VERSION(VERSION_A, OP, VERSION_B, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
#
# DESCRIPTION
#
# This macro compares two version strings. Due to the various number of
# minor-version numbers that can exist, and the fact that string
# comparisons are not compatible with numeric comparisons, this is not
# necessarily trivial to do in a autoconf script. This macro makes doing
# these comparisons easy.
#
# The six basic comparisons are available, as well as checking equality
# limited to a certain number of minor-version levels.
#
# The operator OP determines what type of comparison to do, and can be one
# of:
#
# eq - equal (test A == B)
# ne - not equal (test A != B)
# le - less than or equal (test A <= B)
# ge - greater than or equal (test A >= B)
# lt - less than (test A < B)
# gt - greater than (test A > B)
#
# Additionally, the eq and ne operator can have a number after it to limit
# the test to that number of minor versions.
#
# eq0 - equal up to the length of the shorter version
# ne0 - not equal up to the length of the shorter version
# eqN - equal up to N sub-version levels
# neN - not equal up to N sub-version levels
#
# When the condition is true, shell commands ACTION-IF-TRUE are run,
# otherwise shell commands ACTION-IF-FALSE are run. The environment
# variable 'ax_compare_version' is always set to either 'true' or 'false'
# as well.
#
# Examples:
#
# AX_COMPARE_VERSION([3.15.7],[lt],[3.15.8])
# AX_COMPARE_VERSION([3.15],[lt],[3.15.8])
#
# would both be true.
#
# AX_COMPARE_VERSION([3.15.7],[eq],[3.15.8])
# AX_COMPARE_VERSION([3.15],[gt],[3.15.8])
#
# would both be false.
#
# AX_COMPARE_VERSION([3.15.7],[eq2],[3.15.8])
#
# would be true because it is only comparing two minor versions.
#
# AX_COMPARE_VERSION([3.15.7],[eq0],[3.15])
#
# would be true because it is only comparing the lesser number of minor
# versions of the two values.
#
# Note: The characters that separate the version numbers do not matter. An
# empty string is the same as version 0. OP is evaluated by autoconf, not
# configure, so must be a string, not a variable.
#
# The author would like to acknowledge Guido Draheim whose advice about
# the m4_case and m4_ifvaln functions make this macro only include the
# portions necessary to perform the specific comparison specified by the
# OP argument in the final configure script.
#
# LICENSE
#
# Copyright (c) 2008 Tim Toolan <toolan@ele.uri.edu>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 13
dnl #########################################################################
AC_DEFUN([AX_COMPARE_VERSION], [
AC_REQUIRE([AC_PROG_AWK])
# Used to indicate true or false condition
ax_compare_version=false
# Convert the two version strings to be compared into a format that
# allows a simple string comparison. The end result is that a version
# string of the form 1.12.5-r617 will be converted to the form
# 0001001200050617. In other words, each number is zero padded to four
# digits, and non digits are removed.
AS_VAR_PUSHDEF([A],[ax_compare_version_A])
A=`echo "$1" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \
-e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \
-e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \
-e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \
-e 's/[[^0-9]]//g'`
AS_VAR_PUSHDEF([B],[ax_compare_version_B])
B=`echo "$3" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \
-e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \
-e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \
-e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \
-e 's/[[^0-9]]//g'`
dnl # In the case of le, ge, lt, and gt, the strings are sorted as necessary
dnl # then the first line is used to determine if the condition is true.
dnl # The sed right after the echo is to remove any indented white space.
m4_case(m4_tolower($2),
[lt],[
ax_compare_version=`echo "x$A
x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/false/;s/x${B}/true/;1q"`
],
[gt],[
ax_compare_version=`echo "x$A
x$B" | sed 's/^ *//' | sort | sed "s/x${A}/false/;s/x${B}/true/;1q"`
],
[le],[
ax_compare_version=`echo "x$A
x$B" | sed 's/^ *//' | sort | sed "s/x${A}/true/;s/x${B}/false/;1q"`
],
[ge],[
ax_compare_version=`echo "x$A
x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/true/;s/x${B}/false/;1q"`
],[
dnl Split the operator from the subversion count if present.
m4_bmatch(m4_substr($2,2),
[0],[
# A count of zero means use the length of the shorter version.
# Determine the number of characters in A and B.
ax_compare_version_len_A=`echo "$A" | $AWK '{print(length)}'`
ax_compare_version_len_B=`echo "$B" | $AWK '{print(length)}'`
# Set A to no more than B's length and B to no more than A's length.
A=`echo "$A" | sed "s/\(.\{$ax_compare_version_len_B\}\).*/\1/"`
B=`echo "$B" | sed "s/\(.\{$ax_compare_version_len_A\}\).*/\1/"`
],
[[0-9]+],[
# A count greater than zero means use only that many subversions
A=`echo "$A" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"`
B=`echo "$B" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"`
],
[.+],[
AC_WARNING(
[invalid OP numeric parameter: $2])
],[])
# Pad zeros at end of numbers to make same length.
ax_compare_version_tmp_A="$A`echo $B | sed 's/./0/g'`"
B="$B`echo $A | sed 's/./0/g'`"
A="$ax_compare_version_tmp_A"
# Check for equality or inequality as necessary.
m4_case(m4_tolower(m4_substr($2,0,2)),
[eq],[
test "x$A" = "x$B" && ax_compare_version=true
],
[ne],[
test "x$A" != "x$B" && ax_compare_version=true
],[
AC_WARNING([invalid OP parameter: $2])
])
])
AS_VAR_POPDEF([A])dnl
AS_VAR_POPDEF([B])dnl
dnl # Execute ACTION-IF-TRUE / ACTION-IF-FALSE.
if test "$ax_compare_version" = "true" ; then
m4_ifvaln([$4],[$4],[:])dnl
m4_ifvaln([$5],[else $5])dnl
fi
]) dnl AX_COMPARE_VERSION

View File

@@ -1,12 +1,10 @@
#!/usr/bin/env bash
SRC_LIBPNG="$(find ../src/thirdparty/libpng/ -name '*.c')"
SRC_ZLIB="$(find ../sr/thirdpartyc/zlib/ -name '*.c')"
SRC_ZVBI="$(find ../sr/thirdpartyc/zvbi/ -name '*.c')"
SRC_ZLIB="$(find ../src/thirdparty/zlib/ -name '*.c')"
SRC_ZVBI="$(find ../src/thirdparty/zvbi/ -name '*.c')"
SRC_CCX="$(find ../src/lib_ccx/ -name '*.c')"
SRC_GPAC="$(find ../sr/thirdpartyc/gpacmp4/ -name '*.c')"
SRC_HASH="$(find ../sr/thirdpartyc/lib_hash/ -name '*.c')"
SRC_PROTOBUF="$(find ../src/thirdparty/protobuf-c/ -name '*.c')"
SRC_HASH="$(find ../src/thirdparty/lib_hash/ -name '*.c')"
SRC_UTF8PROC="../src/utf8proc/utf8proc.c"
BLD_SOURCES="../src/ccextractor.c ../src/ccextractorapi_wrap.c $SRC_CCX $SRC_GPAC $SRC_ZLIB $SRC_ZVBI $SRC_LIBPNG $SRC_HASH $SRC_PROTOBUF $SRC_UTF8PROC"
BLD_SOURCES="../src/ccextractor.c ../src/ccextractorapi_wrap.c $SRC_CCX $SRC_ZLIB $SRC_ZVBI $SRC_LIBPNG $SRC_HASH $SRC_UTF8PROC"
python setup.py $BLD_SOURCES

View File

@@ -1,91 +1,10 @@
AUTOMAKE_OPTIONS = foreign
ACLOCAL_AMFLAGS = -I m4/
bin_PROGRAMS = ccextractor
ccextractor_SOURCES = \
../src/ccextractor.c \
../src/ccextractor.h \
../src/thirdparty/gpacmp4/avc_ext.c \
../src/thirdparty/gpacmp4/avilib.c \
../src/thirdparty/gpacmp4/av_parsers.c \
../src/thirdparty/gpacmp4/base_encoding.c \
../src/thirdparty/gpacmp4/bitstream.c \
../src/thirdparty/gpacmp4/box_code_3gpp.c \
../src/thirdparty/gpacmp4/box_code_adobe.c \
../src/thirdparty/gpacmp4/box_code_apple.c \
../src/thirdparty/gpacmp4/box_code_base.c \
../src/thirdparty/gpacmp4/box_code_drm.c \
../src/thirdparty/gpacmp4/box_dump.c \
../src/thirdparty/gpacmp4/box_code_meta.c \
../src/thirdparty/gpacmp4/box_funcs.c \
../src/thirdparty/gpacmp4/color.c \
../src/thirdparty/gpacmp4/configfile.c \
../src/thirdparty/gpacmp4/data_map.c \
../src/thirdparty/gpacmp4/desc_private.c \
../src/thirdparty/gpacmp4/descriptors.c \
../src/thirdparty/gpacmp4/drm_sample.c \
../src/thirdparty/gpacmp4/error.c \
../src/thirdparty/gpacmp4/gpac_ogg.c \
../src/thirdparty/gpacmp4/hint_track.c \
../src/thirdparty/gpacmp4/hinting.c \
../src/thirdparty/gpacmp4/ipmpx_code.c \
../src/thirdparty/gpacmp4/ipmpx_parse.c \
../src/thirdparty/gpacmp4/isom_intern.c \
../src/thirdparty/gpacmp4/isom_read.c \
../src/thirdparty/gpacmp4/isom_store.c \
../src/thirdparty/gpacmp4/isom_write.c \
../src/thirdparty/gpacmp4/list.c \
../src/thirdparty/gpacmp4/math.c \
../src/thirdparty/gpacmp4/media.c \
../src/thirdparty/gpacmp4/media_odf.c \
../src/thirdparty/gpacmp4/meta.c \
../src/thirdparty/gpacmp4/movie_fragments.c \
../src/thirdparty/gpacmp4/odf_code.c \
../src/thirdparty/gpacmp4/odf_codec.c \
../src/thirdparty/gpacmp4/odf_command.c \
../src/thirdparty/gpacmp4/os_config_init.c \
../src/thirdparty/gpacmp4/os_divers.c \
../src/thirdparty/gpacmp4/os_file.c \
../src/thirdparty/gpacmp4/qos.c \
../src/thirdparty/gpacmp4/sample_descs.c \
../src/thirdparty/gpacmp4/slc.c \
../src/thirdparty/gpacmp4/stbl_read.c \
../src/thirdparty/gpacmp4/stbl_write.c \
../src/thirdparty/gpacmp4/track.c \
../src/thirdparty/gpacmp4/tx3g.c \
../src/thirdparty/gpacmp4/url.c \
../src/thirdparty/gpacmp4/utf.c \
../src/thirdparty/gpacmp4/os_thread.c \
../src/thirdparty/gpacmp4/module.c \
../src/thirdparty/gpacmp4/os_module.c \
../src/thirdparty/gpacmp4/xml_parser.c \
../src/thirdparty/gpacmp4/constants.c \
../src/thirdparty/gpacmp4/gpac/avparse.h \
../src/thirdparty/gpacmp4/gpac/base_coding.h \
../src/thirdparty/gpacmp4/gpac/bitstream.h \
../src/thirdparty/gpacmp4/gpac/color.h \
../src/thirdparty/gpacmp4/gpac/config_file.h \
../src/thirdparty/gpacmp4/gpac/configuration.h \
../src/thirdparty/gpacmp4/gpac/constants.h \
../src/thirdparty/gpacmp4/gpac/events_constants.h \
../src/thirdparty/gpacmp4/gpac/ietf.h \
../src/thirdparty/gpacmp4/gpac/isomedia.h \
../src/thirdparty/gpacmp4/gpac/list.h \
../src/thirdparty/gpacmp4/gpac/maths.h \
../src/thirdparty/gpacmp4/gpac/media_tools.h \
../src/thirdparty/gpacmp4/gpac/mpeg4_odf.h \
../src/thirdparty/gpacmp4/gpac/network.h \
../src/thirdparty/gpacmp4/gpac/revision.h \
../src/thirdparty/gpacmp4/gpac/setup.h \
../src/thirdparty/gpacmp4/gpac/tools.h \
../src/thirdparty/gpacmp4/gpac/utf.h \
../src/thirdparty/gpacmp4/gpac/version.h \
../src/thirdparty/gpacmp4/gpac/internal/avilib.h \
../src/thirdparty/gpacmp4/gpac/internal/isomedia_dev.h \
../src/thirdparty/gpacmp4/gpac/internal/media_dev.h \
../src/thirdparty/gpacmp4/gpac/internal/odf_dev.h \
../src/thirdparty/gpacmp4/gpac/internal/odf_parse_common.h \
../src/thirdparty/gpacmp4/gpac/internal/ogg.h \
../src/thirdparty/libpng/pngstruct.h \
../src/thirdparty/libpng/pngpriv.h \
../src/thirdparty/libpng/pnginfo.h \
@@ -114,7 +33,7 @@ ccextractor_SOURCES = \
../src/lib_ccx/activity.h \
../src/lib_ccx/asf_constants.h \
../src/lib_ccx/avc_functions.h \
../src/lib_ccx/bitstream.h \
../src/lib_ccx/cc_bitstream.h \
../src/lib_ccx/ccx_common_option.c \
../src/lib_ccx/ccx_common_common.c \
../src/lib_ccx/utility.c \
@@ -176,10 +95,6 @@ ccextractor_SOURCES = \
../src/lib_ccx/ccx_gxf.c \
../src/lib_ccx/ccx_gxf.h \
../src/lib_ccx/ccx_mp4.h \
../src/lib_ccx/ccx_share.c \
../src/lib_ccx/ccx_share.h \
../src/lib_ccx/ccx_sub_entry_message.pb-c.c \
../src/lib_ccx/ccx_sub_entry_message.pb-c.h \
../src/lib_ccx/compile_info.h \
../src/lib_ccx/compile_info_real.h \
../src/lib_ccx/configuration.c \
@@ -259,20 +174,19 @@ ccextractor_SOURCES = \
../src/thirdparty/utf8proc/utf8proc.h \
../src/thirdparty/lib_hash/sha2.c \
../src/thirdparty/lib_hash/sha2.h \
../src/thirdparty/protobuf-c/protobuf-c.c \
../src/thirdparty/protobuf-c/protobuf-c.h \
../src/thirdparty/zvbi/bcd.h \
../src/thirdparty/zvbi/bit_slicer.c \
../src/thirdparty/zvbi/bit_slicer.h \
../src/thirdparty/zvbi/decoder.c \
../src/thirdparty/zvbi/macros.h \
../src/thirdparty/zvbi/misc.h \
../src/thirdparty/zvbi/raw_decoder.c \
../src/thirdparty/zvbi/raw_decoder.h \
../src/thirdparty/zvbi/sampling_par.c \
../src/thirdparty/zvbi/sampling_par.h \
../src/thirdparty/zvbi/sliced.h \
../src/thirdparty/zvbi/zvbi_decoder.h \
../src/lib_ccx/zvbi/bcd.h \
../src/lib_ccx/zvbi/bit_slicer.c \
../src/lib_ccx/zvbi/bit_slicer.h \
../src/lib_ccx/zvbi/decoder.c \
../src/lib_ccx/zvbi/macros.h \
../src/lib_ccx/zvbi/misc.h \
../src/lib_ccx/zvbi/raw_decoder.c \
../src/lib_ccx/zvbi/raw_decoder.h \
../src/lib_ccx/zvbi/sampling_par.c \
../src/lib_ccx/zvbi/sampling_par.h \
../src/lib_ccx/zvbi/sliced.h \
../src/lib_ccx/zvbi/zvbi_decoder.h \
../src/freetype/* \
../src/thirdparty/freetype/autofit/autofit.c \
../src/thirdparty/freetype/base/ftbase.c \
../src/thirdparty/freetype/base/ftbbox.c \
@@ -301,6 +215,7 @@ ccextractor_SOURCES = \
../src/thirdparty/freetype/cff/cff.c \
../src/thirdparty/freetype/cid/type1cid.c \
../src/thirdparty/freetype/gzip/ftgzip.c \
../src/thirdparty/freetype/include/ft2build.h \
../src/thirdparty/freetype/lzw/ftlzw.c \
../src/thirdparty/freetype/pcf/pcf.c \
../src/thirdparty/freetype/pfr/pfr.c \
@@ -314,35 +229,51 @@ ccextractor_SOURCES = \
../src/thirdparty/freetype/type1/type1.c \
../src/thirdparty/freetype/type42/type42.c \
../src/thirdparty/freetype/winfonts/winfnt.c
ccextractor_CFLAGS = -std=gnu99 -Wno-write-strings -Wno-pointer-sign -D_FILE_OFFSET_BITS=64 -DVERSION_FILE_PRESENT -DFT2_BUILD_LIBRARY -DGPAC_DISABLE_VTT -DGPAC_DISABLE_OD_DUMP -DGPAC_DISABLE_REMOTERY -DNO_GZIP -DGPAC_HAVE_CONFIG_H
if SYS_IS_APPLE_SILICON
ccextractor_SOURCES += ../src/thirdparty/libpng/arm/arm_init.c \
../src/thirdparty/libpng/arm/filter_neon_intrinsics.c \
../src/thirdparty/libpng/arm/palette_neon_intrinsics.c
endif
ccextractor_CPPFLAGS =-I../src/lib_ccx/ -I../src/thirdparty/gpacmp4/ -I../src/thirdparty/libpng/ -I../src/thirdparty/zlib/ -I../src/thirdparty/zvbi/ -I../src/thirdparty/lib_hash/ -I../src/thirdparty/protobuf-c -I../src/thirdparty -I../src -I../src/thirdparty/freetype/include
ccextractor_CFLAGS = -std=gnu99 -Wno-write-strings -Wno-pointer-sign -D_FILE_OFFSET_BITS=64 -DVERSION_FILE_PRESENT -DFT2_BUILD_LIBRARY -DGPAC_DISABLE_VTT -DGPAC_DISABLE_OD_DUMP -DGPAC_DISABLE_REMOTERY -DNO_GZIP
ccextractor_LDFLAGS = $(shell pkg-config --libs gpac)
GPAC_CPPFLAGS = $(shell pkg-config --cflags gpac)
ccextractor_CPPFLAGS =-I../src/lib_ccx/ -I../src/thirdparty/libpng/ -I../src/thirdparty/zlib/ -I../src/lib_ccx/zvbi/ -I../src/thirdparty/lib_hash/ -I../src/thirdparty -I../src/ -I../src/thirdparty/freetype/include/
ccextractor_CPPFLAGS += $(GPAC_CPPFLAGS)
ccextractor_CPPFLAGS += $(FFMPEG_CPPFLAGS)
ccextractor_LDADD=-lm -lpthread -ldl
if SYS_IS_LINUX
ccextractor_CFLAGS += -O3 -s -DGPAC_CONFIG_LINUX
ccextractor_CFLAGS += -O3 -s
endif
if SYS_IS_MAC
ccextractor_CFLAGS += -DPAC_CONFIG_DARWIN -Dfopen64=fopen -Dopen64=open -Dlseek64=lseek
ccextractor_LDADD += -liconv -lz
ccextractor_CFLAGS += -Dfopen64=fopen -Dopen64=open -Dlseek64=lseek
ccextractor_LDADD += -liconv -lz
endif
if SYS_IS_64_BIT
ccextractor_CFLAGS += -DGPAC_64_BITS
endif
HARDSUBX_FEATURE_RUST=
if HARDSUBX_IS_ENABLED
ccextractor_CFLAGS += -DENABLE_HARDSUBX
ccextractor_CPPFLAGS+= ${libavcodec_CFLAGS}
ccextractor_CPPFLAGS+= ${libavformat_CFLAGS}
ccextractor_CPPFLAGS+= ${libavutil_CFALGS}
ccextractor_CPPFLAGS+= ${libavutil_CFLAGS}
ccextractor_CPPFLAGS+= ${libswscale_CFLAGS}
AV_LIB = ${libavcodec_LIBS}
AV_LIB += ${libavformat_LIBS}
AV_LIB += ${libavutil_LIBS}
AV_LIB += ${libswscale_LIBS}
ccextractor_LDADD += $(AV_LIB)
HARDSUBX_FEATURE_RUST += --features "hardsubx_ocr"
endif
if OCR_IS_ENABLED
@@ -369,64 +300,18 @@ ccextractor_LDADD += $(TESS_LIB)
ccextractor_LDADD += $(LEPT_LIB)
endif
EXTRA_DIST = ../src/thirdparty/gpacmp4/gpac/sync_layer.h ../src/lib_ccx/ccfont2.xbm ../src/thirdparty/utf8proc/utf8proc_data.c fonts/ icon/
#For GUI
if BUILD_WITH_GUI
bin_PROGRAMS += ccextractorGUI
ccextractorGUI_SOURCES = \
../src/GUI/ccextractorGUI.c \
../src/GUI/ccextractorGUI.h \
../src/GUI/activity.c \
../src/GUI/activity.h \
../src/GUI/terminal.c \
../src/GUI/preview.c \
../src/GUI/preview.h \
../src/GUI/ccx_cli_thread.c \
../src/GUI/ccx_cli_thread.h \
../src/GUI/command_builder.c \
../src/GUI/command_builder.h \
../src/GUI/save_load_data.c \
../src/GUI/save_load_data.h \
../src/GUI/file_browser.c \
../src/GUI/file_browser.h \
../src/GUI/popups.c \
../src/GUI/popups.h \
../src/GUI/tabs.c \
../src/GUI/tabs.h \
../src/GUI/stb_image.h \
../src/GUI/nuklear_lib/nuklear.h \
../src/GUI/nuklear_lib/nuklear_glfw_gl2.h
ccextractorGUI_CFLAGS = -std=gnu99
ccextractor_LDADD += ./rust/@RUST_TARGET_SUBDIR@/libccx_rust.a
ccextractorGUI_LDADD = ${glfw3_LIBS}
if SYS_IS_LINUX
ccextractorGUI_CFLAGS += -s -O3 -DUNIX
ccextractorGUI_CFLAGS += ${glew_CFLAGS}
ccextractorGUI_LDADD += ${glew_LIBS}
ccextractorGUI_LDADD += -lX11 -lXinerama -lXcursor -lXi -lXrandr -lXxf86vm -lm -ldl -lpthread
if DEBUG_RELEASE
CARGO_RELEASE_ARGS=
else
CARGO_RELEASE_ARGS=--release
endif
if SYS_IS_MAC
ccextractorGUI_CFLAGS += -O3 -DUNIX
ccextractorGUI_CFLAGS += ${glew_CFLAGS}
ccextractorGUI_LDADD += ${glew_LIBS}
ccextractorGUI_LDFLAGS = -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo
ccextractorGUI_LDADD += -lm -L/usr/local/lib -lpthread
endif
./rust/@RUST_TARGET_SUBDIR@/libccx_rust.a:
cd ../src/rust && \
CARGO_TARGET_DIR=../../mac/rust $(CARGO) build $(HARDSUBX_FEATURE_RUST) $(CARGO_RELEASE_ARGS);
if HARDSUBX_IS_ENABLED
if OCR_IS_ENABLED
ccextractorGUI_CFLAGS += -DENABLE_OCR
endif
endif
EXTRA_DIST += ../icon/ ../fonts/
endif
EXTRA_DIST = ../src/lib_ccx/ccfont2.xbm ../src/thirdparty/utf8proc/utf8proc_data.c fonts/ icon/

View File

@@ -1,61 +1,311 @@
#!/bin/bash
cd `dirname $0`
BLD_FLAGS="-std=gnu99 -Wno-write-strings -Wno-pointer-sign -DGPAC_CONFIG_DARWIN -D_FILE_OFFSET_BITS=64 -DVERSION_FILE_PRESENT -Dfopen64=fopen -Dopen64=open -Dlseek64=lseek -DFT2_BUILD_LIBRARY -DGPAC_DISABLE_VTT -DGPAC_DISABLE_OD_DUMP -DGPAC_DISABLE_REMOTERY -DNO_GZIP -DGPAC_HAVE_CONFIG_H"
[[ $1 = "OCR" ]] && BLD_FLAGS="$BLD_FLAGS -DENABLE_OCR"
BLD_INCLUDE="-I../src/ -I../src/lib_ccx -I../src/thirdparty/gpacmp4 -I../src/lib_hash -I../src/thirdparty/libpng -I../src/thirdparty -I../src/thirdparty/protobuf-c -I../src/thirdparty/zlib -I../src/thirdparty/zvbi -I../src/thirdparty/freetype/include"
[[ $1 = "OCR" ]] && BLD_INCLUDE="$BLD_INCLUDE `pkg-config --cflags --silence-errors tesseract`"
SRC_CCX="$(find ../src/lib_ccx -name '*.c')"
SRC_GPAC="$(find ../src/thirdparty/gpacmp4 -name '*.c')"
SRC_LIB_HASH="$(find ../src/thirdparty/lib_hash -name '*.c')"
SRC_LIBPNG="$(find ../src/thirdparty/libpng -name '*.c')"
SRC_PROTOBUF="$(find ../src/thirdparty/protobuf-c -name '*.c')"
SRC_UTF8="../src/thirdparty/utf8proc/utf8proc.c"
SRC_ZLIB="$(find ../src/thirdparty/zlib -name '*.c')"
SRC_ZVBI="$(find ../src/thirdparty/zvbi -name '*.c')"
SRC_FREETYPE="../src/thirdparty/freetype/autofit/autofit.c \
../src/thirdparty/freetype/base/ftbase.c \
../src/thirdparty/freetype/base/ftbbox.c \
../src/thirdparty/freetype/base/ftbdf.c \
../src/thirdparty/freetype/base/ftbitmap.c \
../src/thirdparty/freetype/base/ftcid.c \
../src/thirdparty/freetype/base/ftfntfmt.c \
../src/thirdparty/freetype/base/ftfstype.c \
../src/thirdparty/freetype/base/ftgasp.c \
../src/thirdparty/freetype/base/ftglyph.c \
../src/thirdparty/freetype/base/ftgxval.c \
../src/thirdparty/freetype/base/ftinit.c \
../src/thirdparty/freetype/base/ftlcdfil.c \
../src/thirdparty/freetype/base/ftmm.c \
../src/thirdparty/freetype/base/ftotval.c \
../src/thirdparty/freetype/base/ftpatent.c \
../src/thirdparty/freetype/base/ftpfr.c \
../src/thirdparty/freetype/base/ftstroke.c \
../src/thirdparty/freetype/base/ftsynth.c \
../src/thirdparty/freetype/base/ftsystem.c \
../src/thirdparty/freetype/base/fttype1.c \
../src/thirdparty/freetype/base/ftwinfnt.c \
../src/thirdparty/freetype/bdf/bdf.c \
../src/thirdparty/freetype/bzip2/ftbzip2.c \
../src/thirdparty/freetype/cache/ftcache.c \
../src/thirdparty/freetype/cff/cff.c \
../src/thirdparty/freetype/cid/type1cid.c \
../src/thirdparty/freetype/gzip/ftgzip.c \
../src/thirdparty/freetype/lzw/ftlzw.c \
../src/thirdparty/freetype/pcf/pcf.c \
../src/thirdparty/freetype/pfr/pfr.c \
../src/thirdparty/freetype/psaux/psaux.c \
../src/thirdparty/freetype/pshinter/pshinter.c \
../src/thirdparty/freetype/psnames/psnames.c \
../src/thirdparty/freetype/raster/raster.c \
../src/thirdparty/freetype/sfnt/sfnt.c \
../src/thirdparty/freetype/smooth/smooth.c \
../src/thirdparty/freetype/truetype/truetype.c \
../src/thirdparty/freetype/type1/type1.c \
../src/thirdparty/freetype/type42/type42.c \
../src/thirdparty/freetype/winfonts/winfnt.c"
BLD_SOURCES="../src/ccextractor.c $SRC_API $SRC_CCX $SRC_GPAC $SRC_LIB_HASH $SRC_LIBPNG $SRC_PROTOBUF $SRC_UTF8 $SRC_ZLIB $SRC_ZVBI $SRC_FREETYPE"
BLD_LINKER="-lm -liconv -lpthread -ldl"
[[ $1 = "OCR" ]] && BLD_LINKER="$BLD_LINKER `pkg-config --libs --silence-errors tesseract` `pkg-config --libs --silence-errors lept`"
RUST_LIB="rust/release/libccx_rust.a"
RUST_PROFILE="--release"
RUST_FEATURES=""
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
OCR)
ENABLE_OCR=true
shift
;;
-debug)
DEBUG=true
RUST_PROFILE=""
RUST_LIB="rust/debug/libccx_rust.a"
shift
;;
-hardsubx)
HARDSUBX=true
ENABLE_OCR=true
# Allow overriding FFmpeg version via environment variable
if [ -n "$FFMPEG_VERSION" ]; then
RUST_FEATURES="--features hardsubx_ocr,$FFMPEG_VERSION"
else
RUST_FEATURES="--features hardsubx_ocr"
fi
shift
;;
-system-libs)
# Use system-installed libraries via pkg-config instead of bundled ones
# This is required for Homebrew formula compatibility
USE_SYSTEM_LIBS=true
shift
;;
-*)
echo "Unknown option $1"
exit 1
;;
esac
done
BLD_FLAGS="-std=gnu99 -Wno-write-strings -Wno-pointer-sign -D_FILE_OFFSET_BITS=64 -DVERSION_FILE_PRESENT -Dfopen64=fopen -Dopen64=open -Dlseek64=lseek"
# Add flags for bundled libraries (not needed when using system libs)
if [[ "$USE_SYSTEM_LIBS" != "true" ]]; then
BLD_FLAGS="$BLD_FLAGS -DFT2_BUILD_LIBRARY -DGPAC_DISABLE_VTT -DGPAC_DISABLE_OD_DUMP -DGPAC_DISABLE_REMOTERY -DNO_GZIP"
fi
# Add debug flags if needed
if [[ "$DEBUG" == "true" ]]; then
BLD_FLAGS="$BLD_FLAGS -g -fsanitize=address"
fi
# Add OCR support if requested
if [[ "$ENABLE_OCR" == "true" ]]; then
BLD_FLAGS="$BLD_FLAGS -DENABLE_OCR"
fi
# Add hardsubx support if requested
if [[ "$HARDSUBX" == "true" ]]; then
BLD_FLAGS="$BLD_FLAGS -DENABLE_HARDSUBX"
fi
# Set up include paths based on whether we're using system libs or bundled
if [[ "$USE_SYSTEM_LIBS" == "true" ]]; then
# Use system libraries via pkg-config (for Homebrew compatibility)
# Note: -I../src/thirdparty/lib_hash is needed so that "../lib_hash/sha2.h" resolves correctly
# (the .. goes up from lib_hash to thirdparty, then lib_hash/sha2.h finds the file)
BLD_INCLUDE="-I../src/ -I../src/lib_ccx -I../src/thirdparty/lib_hash -I../src/thirdparty"
BLD_INCLUDE="$BLD_INCLUDE $(pkg-config --cflags --silence-errors freetype2)"
BLD_INCLUDE="$BLD_INCLUDE $(pkg-config --cflags --silence-errors gpac)"
BLD_INCLUDE="$BLD_INCLUDE $(pkg-config --cflags --silence-errors libpng)"
BLD_INCLUDE="$BLD_INCLUDE $(pkg-config --cflags --silence-errors libprotobuf-c)"
BLD_INCLUDE="$BLD_INCLUDE $(pkg-config --cflags --silence-errors libutf8proc)"
else
# Use bundled libraries (default for standalone builds)
BLD_INCLUDE="-I../src/ -I../src/lib_ccx -I../src/thirdparty/lib_hash -I../src/thirdparty/libpng -I../src/thirdparty -I../src/thirdparty/zlib -I../src/thirdparty/freetype/include $(pkg-config --cflags --silence-errors gpac)"
fi
# Add FFmpeg include path for Mac
if [[ -d "/opt/homebrew/Cellar/ffmpeg" ]]; then
FFMPEG_VERSION=$(ls -1 /opt/homebrew/Cellar/ffmpeg | head -1)
if [[ -n "$FFMPEG_VERSION" ]]; then
BLD_INCLUDE="$BLD_INCLUDE -I/opt/homebrew/Cellar/ffmpeg/$FFMPEG_VERSION/include"
fi
elif [[ -d "/usr/local/Cellar/ffmpeg" ]]; then
FFMPEG_VERSION=$(ls -1 /usr/local/Cellar/ffmpeg | head -1)
if [[ -n "$FFMPEG_VERSION" ]]; then
BLD_INCLUDE="$BLD_INCLUDE -I/usr/local/Cellar/ffmpeg/$FFMPEG_VERSION/include"
fi
fi
# Add Leptonica include path for Mac
if [[ -d "/opt/homebrew/Cellar/leptonica" ]]; then
LEPT_VERSION=$(ls -1 /opt/homebrew/Cellar/leptonica | head -1)
if [[ -n "$LEPT_VERSION" ]]; then
BLD_INCLUDE="$BLD_INCLUDE -I/opt/homebrew/Cellar/leptonica/$LEPT_VERSION/include"
fi
elif [[ -d "/usr/local/Cellar/leptonica" ]]; then
LEPT_VERSION=$(ls -1 /usr/local/Cellar/leptonica | head -1)
if [[ -n "$LEPT_VERSION" ]]; then
BLD_INCLUDE="$BLD_INCLUDE -I/usr/local/Cellar/leptonica/$LEPT_VERSION/include"
fi
elif [[ -d "/opt/homebrew/include/leptonica" ]]; then
BLD_INCLUDE="$BLD_INCLUDE -I/opt/homebrew/include"
elif [[ -d "/usr/local/include/leptonica" ]]; then
BLD_INCLUDE="$BLD_INCLUDE -I/usr/local/include"
fi
# Add Tesseract include path for Mac
if [[ -d "/opt/homebrew/Cellar/tesseract" ]]; then
TESS_VERSION=$(ls -1 /opt/homebrew/Cellar/tesseract | head -1)
if [[ -n "$TESS_VERSION" ]]; then
BLD_INCLUDE="$BLD_INCLUDE -I/opt/homebrew/Cellar/tesseract/$TESS_VERSION/include"
fi
elif [[ -d "/usr/local/Cellar/tesseract" ]]; then
TESS_VERSION=$(ls -1 /usr/local/Cellar/tesseract | head -1)
if [[ -n "$TESS_VERSION" ]]; then
BLD_INCLUDE="$BLD_INCLUDE -I/usr/local/Cellar/tesseract/$TESS_VERSION/include"
fi
elif [[ -d "/opt/homebrew/include/tesseract" ]]; then
BLD_INCLUDE="$BLD_INCLUDE -I/opt/homebrew/include"
elif [[ -d "/usr/local/include/tesseract" ]]; then
BLD_INCLUDE="$BLD_INCLUDE -I/usr/local/include"
fi
if [[ "$ENABLE_OCR" == "true" ]]; then
BLD_INCLUDE="$BLD_INCLUDE `pkg-config --cflags --silence-errors tesseract`"
fi
SRC_CCX="$(find ../src/lib_ccx -name '*.c')"
SRC_LIB_HASH="$(find ../src/thirdparty/lib_hash -name '*.c')"
# Set up sources and linker based on whether we're using system libs or bundled
if [[ "$USE_SYSTEM_LIBS" == "true" ]]; then
# Use system libraries - don't compile bundled sources
BLD_SOURCES="../src/ccextractor.c $SRC_CCX $SRC_LIB_HASH"
BLD_LINKER="-lm -liconv -lpthread -ldl"
BLD_LINKER="$BLD_LINKER $(pkg-config --libs --silence-errors freetype2)"
BLD_LINKER="$BLD_LINKER $(pkg-config --libs --silence-errors gpac)"
BLD_LINKER="$BLD_LINKER $(pkg-config --libs --silence-errors libpng)"
BLD_LINKER="$BLD_LINKER $(pkg-config --libs --silence-errors libprotobuf-c)"
BLD_LINKER="$BLD_LINKER $(pkg-config --libs --silence-errors libutf8proc)"
BLD_LINKER="$BLD_LINKER $(pkg-config --libs --silence-errors zlib)"
else
# Use bundled libraries (default)
SRC_LIBPNG="$(find ../src/thirdparty/libpng -name '*.c')"
SRC_UTF8="../src/thirdparty/utf8proc/utf8proc.c"
SRC_ZLIB="$(find ../src/thirdparty/zlib -name '*.c')"
SRC_FREETYPE="../src/thirdparty/freetype/autofit/autofit.c \
../src/thirdparty/freetype/base/ftbase.c \
../src/thirdparty/freetype/base/ftbbox.c \
../src/thirdparty/freetype/base/ftbdf.c \
../src/thirdparty/freetype/base/ftbitmap.c \
../src/thirdparty/freetype/base/ftcid.c \
../src/thirdparty/freetype/base/ftfntfmt.c \
../src/thirdparty/freetype/base/ftfstype.c \
../src/thirdparty/freetype/base/ftgasp.c \
../src/thirdparty/freetype/base/ftglyph.c \
../src/thirdparty/freetype/base/ftgxval.c \
../src/thirdparty/freetype/base/ftinit.c \
../src/thirdparty/freetype/base/ftlcdfil.c \
../src/thirdparty/freetype/base/ftmm.c \
../src/thirdparty/freetype/base/ftotval.c \
../src/thirdparty/freetype/base/ftpatent.c \
../src/thirdparty/freetype/base/ftpfr.c \
../src/thirdparty/freetype/base/ftstroke.c \
../src/thirdparty/freetype/base/ftsynth.c \
../src/thirdparty/freetype/base/ftsystem.c \
../src/thirdparty/freetype/base/fttype1.c \
../src/thirdparty/freetype/base/ftwinfnt.c \
../src/thirdparty/freetype/bdf/bdf.c \
../src/thirdparty/freetype/bzip2/ftbzip2.c \
../src/thirdparty/freetype/cache/ftcache.c \
../src/thirdparty/freetype/cff/cff.c \
../src/thirdparty/freetype/cid/type1cid.c \
../src/thirdparty/freetype/gzip/ftgzip.c \
../src/thirdparty/freetype/lzw/ftlzw.c \
../src/thirdparty/freetype/pcf/pcf.c \
../src/thirdparty/freetype/pfr/pfr.c \
../src/thirdparty/freetype/psaux/psaux.c \
../src/thirdparty/freetype/pshinter/pshinter.c \
../src/thirdparty/freetype/psnames/psnames.c \
../src/thirdparty/freetype/raster/raster.c \
../src/thirdparty/freetype/sfnt/sfnt.c \
../src/thirdparty/freetype/smooth/smooth.c \
../src/thirdparty/freetype/truetype/truetype.c \
../src/thirdparty/freetype/type1/type1.c \
../src/thirdparty/freetype/type42/type42.c \
../src/thirdparty/freetype/winfonts/winfnt.c"
BLD_SOURCES="../src/ccextractor.c $SRC_CCX $SRC_LIB_HASH $SRC_LIBPNG $SRC_UTF8 $SRC_ZLIB $SRC_FREETYPE"
BLD_LINKER="-lm -liconv -lpthread -ldl $(pkg-config --libs --silence-errors gpac)"
fi
if [[ "$ENABLE_OCR" == "true" ]]; then
BLD_LINKER="$BLD_LINKER `pkg-config --libs --silence-errors tesseract` `pkg-config --libs --silence-errors lept`"
fi
if [[ "$HARDSUBX" == "true" ]]; then
# Add FFmpeg library path for Mac
if [[ -d "/opt/homebrew/Cellar/ffmpeg" ]]; then
FFMPEG_VERSION=$(ls -1 /opt/homebrew/Cellar/ffmpeg | head -1)
if [[ -n "$FFMPEG_VERSION" ]]; then
BLD_LINKER="$BLD_LINKER -L/opt/homebrew/Cellar/ffmpeg/$FFMPEG_VERSION/lib"
fi
elif [[ -d "/usr/local/Cellar/ffmpeg" ]]; then
FFMPEG_VERSION=$(ls -1 /usr/local/Cellar/ffmpeg | head -1)
if [[ -n "$FFMPEG_VERSION" ]]; then
BLD_LINKER="$BLD_LINKER -L/usr/local/Cellar/ffmpeg/$FFMPEG_VERSION/lib"
fi
fi
# Add library paths for Leptonica and Tesseract from Cellar
if [[ -d "/opt/homebrew/Cellar/leptonica" ]]; then
LEPT_VERSION=$(ls -1 /opt/homebrew/Cellar/leptonica | head -1)
if [[ -n "$LEPT_VERSION" ]]; then
BLD_LINKER="$BLD_LINKER -L/opt/homebrew/Cellar/leptonica/$LEPT_VERSION/lib"
fi
fi
if [[ -d "/opt/homebrew/Cellar/tesseract" ]]; then
TESS_VERSION=$(ls -1 /opt/homebrew/Cellar/tesseract | head -1)
if [[ -n "$TESS_VERSION" ]]; then
BLD_LINKER="$BLD_LINKER -L/opt/homebrew/Cellar/tesseract/$TESS_VERSION/lib"
fi
fi
# Also add homebrew lib path as fallback
if [[ -d "/opt/homebrew/lib" ]]; then
BLD_LINKER="$BLD_LINKER -L/opt/homebrew/lib"
elif [[ -d "/usr/local/lib" ]]; then
BLD_LINKER="$BLD_LINKER -L/usr/local/lib"
fi
BLD_LINKER="$BLD_LINKER -lswscale -lavutil -pthread -lavformat -lavcodec -lavfilter -lleptonica -ltesseract"
fi
echo "Running pre-build script..."
./pre-build.sh
gcc $BLD_FLAGS $BLD_INCLUDE -o ccextractor $BLD_SOURCES $BLD_LINKER
echo "Trying to compile..."
# Check for cargo
echo "Checking for cargo..."
if ! [ -x "$(command -v cargo)" ]; then
echo 'Error: cargo is not installed.' >&2
exit 1
fi
# Check rust version
rustc_version="$(rustc --version)"
semver=( ${rustc_version//./ } )
version="${semver[1]}.${semver[2]}.${semver[3]}"
MSRV="1.87.0"
if [ "$(printf '%s\n' "$MSRV" "$version" | sort -V | head -n1)" = "$MSRV" ]; then
echo "rustc >= MSRV(${MSRV})"
else
echo "Minimum supported rust version(MSRV) is ${MSRV}, please upgrade rust"
exit 1
fi
echo "Building rust files..."
(cd ../src/rust && CARGO_TARGET_DIR=../../mac/rust cargo build $RUST_PROFILE $RUST_FEATURES) || { echo "Failed building Rust components." ; exit 1; }
# Copy the Rust library
cp $RUST_LIB ./libccx_rust.a
# Add Rust library to linker flags
BLD_LINKER="$BLD_LINKER ./libccx_rust.a"
echo "Building ccextractor"
out=$((LC_ALL=C gcc $BLD_FLAGS $BLD_INCLUDE -o ccextractor $BLD_SOURCES $BLD_LINKER) 2>&1)
res=$?
# Handle common error cases
if [[ $out == *"gcc: command not found"* ]]; then
echo "Error: please install gcc or Xcode command line tools"
exit 1
fi
if [[ $out == *"curl.h: No such file or directory"* ]]; then
echo "Error: please install curl development library"
exit 2
fi
if [[ $out == *"capi.h: No such file or directory"* ]]; then
echo "Error: please install tesseract development library"
exit 3
fi
if [[ $out == *"allheaders.h: No such file or directory"* ]]; then
echo "Error: please install leptonica development library"
exit 4
fi
if [[ $res -ne 0 ]]; then # Unknown error
echo "Compiled with errors"
>&2 echo "$out"
exit 5
fi
if [[ "$out" != "" ]]; then
echo "$out"
echo "Compilation successful, compiler message shown in previous lines"
else
echo "Compilation successful, no compiler messages."
fi

View File

@@ -1,12 +1,12 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
AC_INIT([CCExtractor], [0.92], [carlos@ccextractor.org])
AC_PREREQ([2.71])
AC_INIT([CCExtractor],[0.96],[carlos@ccextractor.org])
AC_CONFIG_AUX_DIR([build-conf])
AC_CONFIG_SRCDIR([../src/ccextractor.c])
AM_INIT_AUTOMAKE([foreign subdir-objects])
AC_CONFIG_MACRO_DIRS([m4])
# Checks for programs.
AC_PROG_CC
@@ -15,7 +15,7 @@ AC_PROG_MAKE_SET
#Checks for "pkg-config" utility
AC_MSG_CHECKING([pkg-config m4 macros])
if test m4_ifdef([PKG_CHECK_MODULES], [yes], [no]) == yes; then
if test m4_ifdef([PKG_CHECK_MODULES], [yes], [no]) = yes; then
AC_MSG_RESULT([yes]);
else
AC_MSG_RESULT([no]);
@@ -25,7 +25,7 @@ fi
# Checks for libraries.
AC_CHECK_LIB([m], [sin], [], [AC_MSG_ERROR(Math library not installed. Install it before proceeding.)])
AC_CHECK_LIB([lept], [getLeptonicaVersion], [HAS_LEPT=1 && PKG_CHECK_MODULES([lept], [lept])], [HAS_LEPT=0])
AC_CHECK_LIB([leptonica], [getLeptonicaVersion], [HAS_LEPT=1 && PKG_CHECK_MODULES([lept], [lept])], [HAS_LEPT=0])
AC_CHECK_LIB([tesseract], [TessVersion], [HAS_TESSERACT=1 && PKG_CHECK_MODULES([tesseract], [tesseract])], [HAS_TESSERACT=0])
AC_CHECK_LIB([avcodec], [avcodec_version], [HAS_AVCODEC=1 && PKG_CHECK_MODULES([libavcodec], [libavcodec])], [HAS_AVCODEC=0])
AC_CHECK_LIB([avformat], [avformat_version], [HAS_AVFORMAT=1 && PKG_CHECK_MODULES([libavformat], [libavformat])], [HAS_AVFORMAT=0])
@@ -63,7 +63,7 @@ AC_CHECK_FUNCS([floor ftruncate gethostbyname gettimeofday inet_ntoa mblen memch
# Checks for arguments with configure
AC_ARG_ENABLE([hardsubx],
AC_HELP_STRING([--enable-hardsubx], [Enables extraction of burnt subtitles (hard subtitles)]),
AS_HELP_STRING([--enable-hardsubx],[Enables extraction of burnt subtitles (hard subtitles)]),
[case "${enableval}" in
yes) hardsubx=true ;;
no) hardsubx=false ;;
@@ -71,7 +71,7 @@ AC_HELP_STRING([--enable-hardsubx], [Enables extraction of burnt subtitles (hard
esac],[hardsubx=false])
AC_ARG_ENABLE([ocr],
AC_HELP_STRING([--enable-ocr], [Enables Optical Character Recognition]),
AS_HELP_STRING([--enable-ocr],[Enables Optical Character Recognition]),
[case "${enableval}" in
yes) ocr=true ;;
no) ocr=false ;;
@@ -79,20 +79,58 @@ AC_HELP_STRING([--enable-ocr], [Enables Optical Character Recognition]),
esac],[ocr=false])
AC_ARG_ENABLE([ffmpeg],
AC_HELP_STRING([--enable-ffmpeg], [Enable FFmpeg integration]),
AS_HELP_STRING([--enable-ffmpeg],[Enable FFmpeg integration]),
[case "${enableval}" in
yes) ffmpeg=true ;;
no) ffmpeg=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-ffmpeg]) ;;
esac],[ffmpeg=false])
AC_ARG_WITH([gui],
AC_HELP_STRING([--with-gui], [Builds CCExtractor with GUI (requires GLFW and GLEW)]),
[PKG_CHECK_MODULES([glfw3], [glfw3]) && PKG_CHECK_MODULES([glew], [glew])],
[with_gui=no])
#Add argument for rust
AC_ARG_WITH([rust],
AS_HELP_STRING([--with-rust],[Builds CCExtractor with rust library]),
[with_rust=$withval],
[with_rust=yes])
AC_MSG_CHECKING(whether to build with rust library)
if test "x$with_rust" = "xyes" ; then
AC_MSG_RESULT(yes)
#Checks and prompts if libraries found/not found to avoild failure while building
#Check if cargo and rust is installed
AC_PATH_PROG([CARGO], [cargo], [notfound])
AS_IF([test "$CARGO" = "notfound"], [AC_MSG_ERROR([cargo is required])])
AC_PATH_PROG([RUSTC], [rustc], [notfound])
AS_IF([test "$RUSTC" = "notfound"], [AC_MSG_ERROR([rustc is required])])
rustc_version=$(rustc --version)
MSRV="1.87.0"
AX_COMPARE_VERSION($rustc_version, [ge], [$MSRV],
[AC_MSG_RESULT(rustc >= $MSRV)],
[AC_MSG_ERROR([Minimum supported rust version(MSRV) is $MSRV, please upgrade rust])])
else
AC_MSG_RESULT(no)
fi
AM_CONDITIONAL([WITH_RUST], [test "x$with_rust" = "xyes"])
AC_ARG_ENABLE(debug,
AS_HELP_STRING([--enable-debug],[Build Rust code with debugging information [default=no]]),
[debug_release=$enableval],
[debug_release=no])
AC_MSG_CHECKING(whether to build Rust code with debugging information)
if test "x$debug_release" = "xyes" ; then
AC_MSG_RESULT(yes)
RUST_TARGET_SUBDIR=debug
else
AC_MSG_RESULT(no)
RUST_TARGET_SUBDIR=release
fi
AM_CONDITIONAL([DEBUG_RELEASE], [test "x$debug_release" = "xyes"])
AC_SUBST([RUST_TARGET_SUBDIR])
#Checks and prompts if libraries found/not found to avoid failure while building
AS_IF([ test x$hardsubx = xtrue && test $HAS_AVCODEC -gt 0 ], [AC_MSG_NOTICE(avcodec library found)])
AS_IF([ test x$hardsubx = xtrue && test ! $HAS_AVCODEC -gt 0 ], [AC_MSG_ERROR(avcodec library not found. Please install the avcodec library before proceeding)])
AS_IF([ test x$hardsubx = xtrue && test $HAS_AVFORMAT -gt 0 ], [AC_MSG_NOTICE(avformat library found)])
@@ -101,20 +139,21 @@ AS_IF([ test x$hardsubx = xtrue && test $HAS_AVUTIL -gt 0 ], [AC_MSG_NOTICE(avut
AS_IF([ test x$hardsubx = xtrue && test ! $HAS_AVUTIL -gt 0 ], [AC_MSG_ERROR(avutil library not found. Please install the avutil library before proceeding)])
AS_IF([ test x$hardsubx = xtrue && test $HAS_SWSCALE -gt 0 ], [AC_MSG_NOTICE(swscale library found)])
AS_IF([ test x$hardsubx = xtrue && test ! $HAS_SWSCALE -gt 0 ], [AC_MSG_ERROR(swscale library not found. Please install the swscale library before proceeding)])
AS_IF([ (test x$ocr = xtrue || test x$hardsubx = xtrue) && test $HAS_TESSERACT -gt 0 ], [TESS_VERSION=`tesseract --version 2>&1 | grep tesseract` && AC_MSG_NOTICE(tesseract library found... $TESS_VERSION)])
AS_IF([ (test x$ocr = xtrue || test x$hardsubx = xtrue) && test $HAS_TESSERACT -gt 0 ], [TESS_VERSION=$(tesseract --version 2>&1 | grep tesseract) && AC_MSG_NOTICE(tesseract library found... $TESS_VERSION)])
AS_IF([ (test x$ocr = xtrue || test x$hardsubx = xtrue) && test ! $HAS_TESSERACT -gt 0 ], [AC_MSG_ERROR(tesserect library not found. Please install the tesseract library before proceeding)])
AS_IF([ (test x$ocr = xtrue || test x$hardsubx = xtrue) && test $HAS_LEPT -gt 0 ], [LEPT_VERSION=`tesseract --version 2>&1 | grep leptonica` && AC_MSG_NOTICE(leptonica library found... $LEPT_VERSION)])
AS_IF([ (test x$ocr = xtrue || test x$hardsubx = xtrue) && test $HAS_LEPT -gt 0 ], [LEPT_VERSION=$(tesseract --version 2>&1 | grep leptonica) && AC_MSG_NOTICE(leptonica library found... $LEPT_VERSION)])
AS_IF([ (test x$ocr = xtrue || test x$hardsubx = xtrue) && test ! $HAS_LEPT -gt 0 ], [AC_MSG_ERROR(leptonica library not found. Please install the leptonica library before proceeding)])
#AM_CONDITIONAL(s) for setting values to enable/disable flags in Makefile.am
AM_CONDITIONAL(HARDSUBX_IS_ENABLED, [ test x$hardsubx = xtrue ])
AM_CONDITIONAL(OCR_IS_ENABLED, [ test x$ocr = xtrue || test x$hardsubx = xtrue ])
AM_CONDITIONAL(FFMPEG_IS_ENABLED, [ test x$ffmpeg = xtrue ])
AM_CONDITIONAL(TESSERACT_PRESENT, [ test ! -z `pkg-config --libs-only-l --silence-errors tesseract`])
AM_CONDITIONAL(TESSERACT_PRESENT_RPI, [ test -d "/usr/include/tesseract" && test `ls -A /usr/include/tesseract | wc -l` -gt 0 ])
AM_CONDITIONAL(SYS_IS_LINUX, [ test `uname -s` = "Linux"])
AM_CONDITIONAL(SYS_IS_MAC, [ test `uname -s` = "Darwin"])
AM_CONDITIONAL(BUILD_WITH_GUI, [test "x$with_gui" = "xyes"])
AM_CONDITIONAL(TESSERACT_PRESENT, [ test ! -z "$(pkg-config --libs-only-l --silence-errors tesseract)" ])
AM_CONDITIONAL(TESSERACT_PRESENT_RPI, [ test -d "/usr/include/tesseract" && test $(ls -A /usr/include/tesseract | wc -l) -gt 0 ])
AM_CONDITIONAL(SYS_IS_LINUX, [ test $(uname -s) = "Linux"])
AM_CONDITIONAL(SYS_IS_MAC, [ test $(uname -s) = "Darwin"])
AM_CONDITIONAL(SYS_IS_APPLE_SILICON, [ test $(uname -a | awk '{print $NF}') = "arm64" ])
AM_CONDITIONAL(SYS_IS_64_BIT,[test $(getconf LONG_BIT) = "64"])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

View File

@@ -0,0 +1,177 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_compare_version.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_COMPARE_VERSION(VERSION_A, OP, VERSION_B, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
#
# DESCRIPTION
#
# This macro compares two version strings. Due to the various number of
# minor-version numbers that can exist, and the fact that string
# comparisons are not compatible with numeric comparisons, this is not
# necessarily trivial to do in a autoconf script. This macro makes doing
# these comparisons easy.
#
# The six basic comparisons are available, as well as checking equality
# limited to a certain number of minor-version levels.
#
# The operator OP determines what type of comparison to do, and can be one
# of:
#
# eq - equal (test A == B)
# ne - not equal (test A != B)
# le - less than or equal (test A <= B)
# ge - greater than or equal (test A >= B)
# lt - less than (test A < B)
# gt - greater than (test A > B)
#
# Additionally, the eq and ne operator can have a number after it to limit
# the test to that number of minor versions.
#
# eq0 - equal up to the length of the shorter version
# ne0 - not equal up to the length of the shorter version
# eqN - equal up to N sub-version levels
# neN - not equal up to N sub-version levels
#
# When the condition is true, shell commands ACTION-IF-TRUE are run,
# otherwise shell commands ACTION-IF-FALSE are run. The environment
# variable 'ax_compare_version' is always set to either 'true' or 'false'
# as well.
#
# Examples:
#
# AX_COMPARE_VERSION([3.15.7],[lt],[3.15.8])
# AX_COMPARE_VERSION([3.15],[lt],[3.15.8])
#
# would both be true.
#
# AX_COMPARE_VERSION([3.15.7],[eq],[3.15.8])
# AX_COMPARE_VERSION([3.15],[gt],[3.15.8])
#
# would both be false.
#
# AX_COMPARE_VERSION([3.15.7],[eq2],[3.15.8])
#
# would be true because it is only comparing two minor versions.
#
# AX_COMPARE_VERSION([3.15.7],[eq0],[3.15])
#
# would be true because it is only comparing the lesser number of minor
# versions of the two values.
#
# Note: The characters that separate the version numbers do not matter. An
# empty string is the same as version 0. OP is evaluated by autoconf, not
# configure, so must be a string, not a variable.
#
# The author would like to acknowledge Guido Draheim whose advice about
# the m4_case and m4_ifvaln functions make this macro only include the
# portions necessary to perform the specific comparison specified by the
# OP argument in the final configure script.
#
# LICENSE
#
# Copyright (c) 2008 Tim Toolan <toolan@ele.uri.edu>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 13
dnl #########################################################################
AC_DEFUN([AX_COMPARE_VERSION], [
AC_REQUIRE([AC_PROG_AWK])
# Used to indicate true or false condition
ax_compare_version=false
# Convert the two version strings to be compared into a format that
# allows a simple string comparison. The end result is that a version
# string of the form 1.12.5-r617 will be converted to the form
# 0001001200050617. In other words, each number is zero padded to four
# digits, and non digits are removed.
AS_VAR_PUSHDEF([A],[ax_compare_version_A])
A=`echo "$1" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \
-e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \
-e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \
-e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \
-e 's/[[^0-9]]//g'`
AS_VAR_PUSHDEF([B],[ax_compare_version_B])
B=`echo "$3" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \
-e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \
-e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \
-e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \
-e 's/[[^0-9]]//g'`
dnl # In the case of le, ge, lt, and gt, the strings are sorted as necessary
dnl # then the first line is used to determine if the condition is true.
dnl # The sed right after the echo is to remove any indented white space.
m4_case(m4_tolower($2),
[lt],[
ax_compare_version=`echo "x$A
x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/false/;s/x${B}/true/;1q"`
],
[gt],[
ax_compare_version=`echo "x$A
x$B" | sed 's/^ *//' | sort | sed "s/x${A}/false/;s/x${B}/true/;1q"`
],
[le],[
ax_compare_version=`echo "x$A
x$B" | sed 's/^ *//' | sort | sed "s/x${A}/true/;s/x${B}/false/;1q"`
],
[ge],[
ax_compare_version=`echo "x$A
x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/true/;s/x${B}/false/;1q"`
],[
dnl Split the operator from the subversion count if present.
m4_bmatch(m4_substr($2,2),
[0],[
# A count of zero means use the length of the shorter version.
# Determine the number of characters in A and B.
ax_compare_version_len_A=`echo "$A" | $AWK '{print(length)}'`
ax_compare_version_len_B=`echo "$B" | $AWK '{print(length)}'`
# Set A to no more than B's length and B to no more than A's length.
A=`echo "$A" | sed "s/\(.\{$ax_compare_version_len_B\}\).*/\1/"`
B=`echo "$B" | sed "s/\(.\{$ax_compare_version_len_A\}\).*/\1/"`
],
[[0-9]+],[
# A count greater than zero means use only that many subversions
A=`echo "$A" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"`
B=`echo "$B" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"`
],
[.+],[
AC_WARNING(
[invalid OP numeric parameter: $2])
],[])
# Pad zeros at end of numbers to make same length.
ax_compare_version_tmp_A="$A`echo $B | sed 's/./0/g'`"
B="$B`echo $A | sed 's/./0/g'`"
A="$ax_compare_version_tmp_A"
# Check for equality or inequality as necessary.
m4_case(m4_tolower(m4_substr($2,0,2)),
[eq],[
test "x$A" = "x$B" && ax_compare_version=true
],
[ne],[
test "x$A" != "x$B" && ax_compare_version=true
],[
AC_WARNING([invalid OP parameter: $2])
])
])
AS_VAR_POPDEF([A])dnl
AS_VAR_POPDEF([B])dnl
dnl # Execute ACTION-IF-TRUE / ACTION-IF-FALSE.
if test "$ax_compare_version" = "true" ; then
m4_ifvaln([$4],[$4],[:])dnl
m4_ifvaln([$5],[else $5])dnl
fi
]) dnl AX_COMPARE_VERSION

View File

@@ -1,22 +1,21 @@
pkgname=ccextractor
pkgver=0.92
pkgver=0.96
pkgrel=1
pkgdesc="A closed captions and teletext subtitles extractor for video streams."
arch=('i686' 'x86_64')
url="http://www.ccextractor.org"
url="https://www.ccextractor.org"
license=('GPL')
depends=('gcc-libs' 'tesseract')
depends=('gcc-libs' 'tesseract' 'leptonica' 'ffmpeg' 'rust' 'clang')
source=(
$pkgname-$pkgver.tar.gz
https://github.com/CCExtractor/ccextractor/releases/download/v$pkgver/ccextractor_minimal.tar.gz
)
build() {
cd "$srcdir/$pkgname-$pkgver"
CC=gcc ./configure --enable-ocr --prefix="$pkgdir/usr/local"
make -j4
cd "$srcdir/$pkgname/linux"
./build_hardsubx
}
package() {
cd "$srcdir/$pkgname-$pkgver"
make install
cd "$srcdir/$pkgname/linux"
install -Dm755 "$pkgname" "$pkgdir/usr/bin/$pkgname"
}

View File

@@ -1,10 +1,10 @@
Name: ccextractor
Version: 0.88
Version: 0.96
Release: 1
Summary: A closed captions and teletext subtitles extractor for video streams.
Group: Applications/Internet
License: GPL
URL: http://ccextractor.org/
URL: https://ccextractor.org/
Source0: %{name}-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root

View File

@@ -1,7 +1,7 @@
#!/bin/bash
TYPE="debian" # can be one of 'slackware', 'debian', 'rpm'
PROGRAM_NAME="ccextractor"
VERSION="0.88"
VERSION="0.96"
RELEASE="1"
LICENSE="GPL-2.0"
MAINTAINER="carlos@ccextractor.org"

View File

@@ -4,12 +4,10 @@ cc_binary(
"ccextractor.h"],
deps = [
"//src/lib_ccx:lib_ccx",
"//src/thirdparty/protobuf-c:protobuf-c",
"//src/thirdparty/gpacmp4:gpacmp4",
"//src/thirdparty/zlib:zlib",
"//src/thirdparty/freetype:freetype"
],
copts = [ "-Isrc/thirdparty/protobuf-c", "-Isrc/thirdparty/libpng", "-Isrc" ]
copts = [ "-Isrc/thirdparty/libpng", "-Isrc" ]
)
exports_files (["ccextractor.h"], ["//src/lib_ccx:__pkg__"])

View File

@@ -1,12 +1,11 @@
cmake_minimum_required (VERSION 3.0.2)
cmake_minimum_required (VERSION 3.24.0)
project (CCExtractor)
include (CTest)
option (WITH_FFMPEG "Build using FFmpeg demuxer and decoder" OFF)
option (WITH_OCR "Build with OCR (Optical Character Recognition) feature" OFF)
option (WITH_SHARING "Build with sharing and translation support" OFF)
option (WITH_HARDSUBX "Build with support for burned-in subtitles" OFF)
option (WITH_RUST "Build with Rust library" OFF)
# Version number
set (CCEXTRACTOR_VERSION_MAJOR 0)
@@ -41,11 +40,7 @@ configure_file (
"${PROJECT_SOURCE_DIR}/lib_ccx/compile_info_real.h"
)
add_definitions(-DVERSION_FILE_PRESENT -DFT2_BUILD_LIBRARY -DGPAC_DISABLE_VTT -DGPAC_DISABLE_OD_DUMP -DGPAC_DISABLE_REMOTERY -DNO_GZIP -DGPAC_HAVE_CONFIG_H)
if(UNIX)
add_definitions(-DGPAC_CONFIG_LINUX)
endif(UNIX)
add_definitions(-DVERSION_FILE_PRESENT -DFT2_BUILD_LIBRARY -DGPAC_DISABLE_VTT -DGPAC_DISABLE_OD_DUMP -DGPAC_DISABLE_REMOTERY -DNO_GZIP)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
add_definitions(-DGPAC_64_BITS)
@@ -55,16 +50,25 @@ include_directories(${PROJECT_SOURCE_DIR})
include_directories(${PROJECT_SOURCE_DIR}/lib_ccx)
include_directories(${PROJECT_SOURCE_DIR}/lib_ccx/zvbi)
include_directories(${PROJECT_SOURCE_DIR}/thirdparty)
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/gpacmp4)
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/protobuf-c)
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/lib_hash)
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/libpng)
# Check if the operating system is macOS (Darwin)
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
if(${CMAKE_HOST_SYSTEM_PROCESSOR} MATCHES "arm64")
# ARM Macs
include_directories("/opt/homebrew/include")
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/libpng/arm)
aux_source_directory(${PROJECT_SOURCE_DIR}/thirdparty/libpng/arm SOURCEFILE)
else()
include_directories("/usr/local/include")
endif()
endif()
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/zlib)
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/freetype/include)
aux_source_directory(${PROJECT_SOURCE_DIR}/thirdparty/gpacmp4/ SOURCEFILE)
aux_source_directory(${PROJECT_SOURCE_DIR}/thirdparty/lib_hash/ SOURCEFILE)
aux_source_directory(${PROJECT_SOURCE_DIR}/thirdparty/libpng/ SOURCEFILE)
aux_source_directory(${PROJECT_SOURCE_DIR}/thirdparty/protobuf-c/ SOURCEFILE)
aux_source_directory(${PROJECT_SOURCE_DIR}/thirdparty/zlib/ SOURCEFILE)
aux_source_directory(${PROJECT_SOURCE_DIR}/lib_ccx/zvbi/ SOURCEFILE)
@@ -115,14 +119,23 @@ set(FREETYPE_SOURCE
)
#Windows specific libraries and linker flags
if(WIN32)
include_directories ("${PROJECT_SOURCE_DIR}/thirdparty/win_spec_incld/")
if(NOT MINGW)
include_directories ("${PROJECT_SOURCE_DIR}/thirdparty/win_spec_incld/")
endif()
include_directories ("${PROJECT_SOURCE_DIR}/thirdparty/win_iconv/")
aux_source_directory ("${PROJECT_SOURCE_DIR}/thirdparty/win_iconv/" SOURCEFILE)
set (EXTRA_LIBS ${EXTRA_LIBS} ws2_32 winmm)
set (EXTRA_LIBS ${EXTRA_LIBS} ws2_32 winmm Bcrypt)
else (WIN32)
# Adding some platform specific library path
link_directories (/opt/local/lib)
link_directories (/usr/local/lib)
if(UNIX AND NOT APPLE)
link_directories (/usr/local/lib)
endif()
if(APPLE)
# Homebrew library paths
link_directories(/usr/local/lib)
link_directories(/opt/homebrew/lib)
endif()
endif(WIN32)
if(MSVC)
@@ -136,6 +149,7 @@ add_subdirectory (lib_ccx)
aux_source_directory(${PROJECT_SOURCE_DIR} SOURCEFILE)
set (EXTRA_LIBS ${EXTRA_LIBS} ccx)
set (EXTRA_LIBS ${EXTRA_LIBS} ${GPAC_LIBRARIES})
# set (EXTRA_LIBS ${EXTRA_LIBS} m)
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
@@ -190,21 +204,6 @@ if (PKG_CONFIG_FOUND AND WITH_OCR)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DENABLE_OCR")
endif (PKG_CONFIG_FOUND AND WITH_OCR)
########################################################
# Build with CC sharing and translation support
########################################################
if (PKG_CONFIG_FOUND AND WITH_SHARING)
pkg_check_modules (NANOMSG REQUIRED libnanomsg)
set (EXTRA_LIBS ${EXTRA_LIBS} ${NANOMSG_STATIC_LIBRARIES})
include_directories ("${PROJECT_SOURCE_DIR}/thirdparty/protobuf-c/")
aux_source_directory ("${PROJECT_SOURCE_DIR}/thirdparty/protobuf-c/" SOURCEFILE)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DENABLE_SHARING")
endif (PKG_CONFIG_FOUND AND WITH_SHARING)
########################################################
# Build for hardsubx using avformat, avutil, avcodec and
# swscale
@@ -215,19 +214,30 @@ if (PKG_CONFIG_FOUND AND WITH_HARDSUBX)
pkg_check_modules (AVFORMAT REQUIRED libavformat)
pkg_check_modules (AVUTIL REQUIRED libavutil)
pkg_check_modules (AVCODEC REQUIRED libavcodec)
pkg_check_modules (AVFILTER REQUIRED libavfilter)
pkg_check_modules (SWSCALE REQUIRED libswscale)
set (EXTRA_LIBS ${EXTRA_LIBS} ${AVFORMAT_LIBRARIES})
set (EXTRA_LIBS ${EXTRA_LIBS} ${AVUTIL_LIBRARIES})
set (EXTRA_LIBS ${EXTRA_LIBS} ${AVCODEC_LIBRARIES})
set (EXTRA_LIBS ${EXTRA_LIBS} ${AVFILTER_LIBRARIES})
set (EXTRA_LIBS ${EXTRA_LIBS} ${SWSCALE_LIBRARIES})
set (EXTRA_INCLUDES ${EXTRA_INCLUDES} ${AVFORMAT_INCLUDE_DIRS})
set (EXTRA_INCLUDES ${EXTRA_INCLUDES} ${AVUTIL_INCLUDE_DIRS})
set (EXTRA_INCLUDES ${EXTRA_INCLUDES} ${AVCODEC_INCLUDE_DIRS})
set (EXTRA_INCLUDES ${EXTRA_INCLUDES} ${AVFILTER_INCLUDE_DIRS})
set (EXTRA_INCLUDES ${EXTRA_INCLUDES} ${SWSCALE_INCLUDE_DIRS})
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DENABLE_HARDSUBX")
pkg_check_modules (TESSERACT REQUIRED tesseract)
pkg_check_modules (LEPTONICA REQUIRED lept)
set (EXTRA_LIBS ${EXTRA_LIBS} ${TESSERACT_LIBRARIES})
set (EXTRA_LIBS ${EXTRA_LIBS} ${LEPTONICA_LIBRARIES})
set (EXTRA_INCLUDES ${EXTRA_INCLUDES} ${TESSERACT_INCLUDE_DIRS})
set (EXTRA_INCLUDES ${EXTRA_INCLUDES} ${LEPTONICA_INCLUDE_DIRS})
endif (PKG_CONFIG_FOUND AND WITH_HARDSUBX)
add_executable (ccextractor ${SOURCEFILE} ${FREETYPE_SOURCE} ${UTF8PROC_SOURCE})
@@ -236,13 +246,11 @@ add_executable (ccextractor ${SOURCEFILE} ${FREETYPE_SOURCE} ${UTF8PROC_SOURCE})
# Build with Rust library
########################################################
if (PKG_CONFIG_FOUND AND WITH_RUST)
if (PKG_CONFIG_FOUND)
add_subdirectory (rust)
get_target_property(RUST_LIB ccx_rust LOCATION)
set (EXTRA_LIBS ${EXTRA_LIBS} ${RUST_LIB})
add_dependencies(ccextractor ccx_rust)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DENABLE_RUST")
endif (PKG_CONFIG_FOUND AND WITH_RUST)
set (EXTRA_LIBS ${EXTRA_LIBS} ccx_rust)
endif (PKG_CONFIG_FOUND)
target_link_libraries (ccextractor ${EXTRA_LIBS})
target_include_directories (ccextractor PUBLIC ${EXTRA_INCLUDES})

View File

@@ -1,18 +0,0 @@
#ifndef NK_IMPLEMENTATION
#include "nuklear_lib/nuklear.h"
#endif // !NK_IMPLEMENTATION
#include "activity.h"
int activity(struct nk_context *ctx, int x, int y, int width, int height, struct main_tab *main_settings)
{
static int i;
if (nk_begin(ctx, "Activity", nk_rect(x, y, width, height), NK_WINDOW_TITLE | NK_WINDOW_BACKGROUND))
{
nk_layout_row_dynamic(ctx, 40, 1);
for (i = 0; i < main_settings->activity_string_count; i++)
nk_label_wrap(ctx, main_settings->activity_string[i]);
}
nk_end(ctx);
return !nk_window_is_closed(ctx, "Activity");
}

View File

@@ -1,8 +0,0 @@
#ifndef ACTIVITY_H
#define ACTIVITY_H
#include "ccextractorGUI.h"
int activity(struct nk_context *ctx, int x, int y, int width, int height, struct main_tab *main_settings);
#endif

View File

@@ -1,902 +0,0 @@
/* nuklear - v1.32.0 - public domain */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <math.h>
#include <limits.h>
#include <time.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#define PATH_LENGTH 66
#define NAME_LENGTH 56
#define PREFIX_LENGTH_TRUNCATED 10
#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_STANDARD_IO
#define NK_INCLUDE_STANDARD_VARARGS
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
#define NK_INCLUDE_FONT_BAKING
#define NK_INCLUDE_DEFAULT_FONT
#define NK_IMPLEMENTATION
#define NK_GLFW_GL2_IMPLEMENTATION
#include "nuklear_lib/nuklear.h"
#include "nuklear_lib/nuklear_glfw_gl2.h"
#include "icon_data.c"
//#define WINDOW_WIDTH 1200
//#define WINDOW_HEIGHT 800
//#define true 1
//#define false 0
//#define UNUSED(a) (void)a
//#define MIN(a,b) ((a) < (b) ? (a) : (b))
//#define MAX(a,b) ((a) < (b) ? (b) : (a))
//#define LEN(a) (sizeof(a)/sizeof(a)[0])
#include "ccextractorGUI.h"
#include "tabs.h"
#include "activity.h"
#include "terminal.c"
#include "preview.h"
#include "popups.h"
#include "command_builder.h"
#include "ccx_cli_thread.h"
#include "file_browser.h"
#include "save_load_data.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
static struct main_tab main_settings;
/*Trigger command for CLI*/
char command[20];
/*Global Variables for Drag and Drop files*/
/* Width and Height of all frames*/
const GLint WIDTH_mainPanelAndWindow = 530, HEIGHT_mainPanelandWindow = 550;
const GLint WIDTH_termORPreviewPanel = 530, HEIGHT_termORPreviewPanel = 100;
const GLint WIDTH_termANDPreviewPanel = 400, HEIGHT_termANDPreviewPanel = 650;
const GLint WIDTH_activityPanel = 400, HEIGHT_activityPanelSolo = 550, HEIGHT_activityPanelDuo = 650;
const GLint WIDTH_mainTermORPreviewWindow = 530, HEIGHT_mainORPreviewTermWindow = 650;
const GLint WIDTH_mainTermANDPreviewWindow = 930, HEIGHT_mainTermAndPreviewWindow = 650;
const GLint WIDTH_mainActivityWindow = 930, HEIGHT_mainActivityWindowSolo = 550, HEIGHT_mainActivityWindowDuo = 650;
/*Tab constants*/
static int tab_screen_height;
/*Parameter Constants*/
static int modifiedParams = 0;
static void error_callback(int e, const char *d)
{
printf("Error %d: %s\n", e, d);
}
void drop_callback(GLFWwindow *window, int count, const char **paths)
{
int i, j, k, z, copycount, prefix_length, slash_length, fileNameTruncated_index;
printf("Number of selected paths:%d\n", count);
if (main_settings.filename_count == 0 && main_settings.filenames == NULL)
main_settings.filenames = (char **)calloc(count + 1, sizeof(char *));
else
main_settings.filenames = (char **)realloc(main_settings.filenames, (main_settings.filename_count + count + 1) * sizeof(char *));
for (i = 0; i < count; i++)
{
printf("\n%d", main_settings.filename_count);
main_settings.filenames[main_settings.filename_count] = (char *)calloc((strlen(paths[i]) + 5), sizeof(char));
main_settings.filenames[main_settings.filename_count][0] = '\"';
strcat(main_settings.filenames[main_settings.filename_count], paths[i]);
strcat(main_settings.filenames[main_settings.filename_count], "\"");
puts(main_settings.filenames[main_settings.filename_count]);
main_settings.filename_count++;
}
main_settings.filenames[main_settings.filename_count] = NULL;
}
/*Rectangle to hold file names*/
//void draw_file_rectangle_widget(struct nk_context *ctx, struct nk_font *font)
//{
// struct nk_command_buffer *canvas;
// struct nk_input *input = &ctx->input;
// canvas = nk_window_get_canvas(ctx);
//
// struct nk_rect space;
// enum nk_widget_layout_states state;
// state = nk_widget(&space, ctx);
// if (!state) return;
//
// /*if (state != NK_WIDGET_ROM)
// update_your_widget_by_user_input(...);*/
// nk_fill_rect(canvas, space, 5, nk_rgb(88, 81, 96));
// if (!strcmp(filePath[0], "\0")) {
// space.y = space.y + (space.h / 2) -10;
// space.x = space.x + 90;
// nk_draw_text(canvas, space, "Drag and Drop files here for Extraction.", 40, &font->handle, nk_rgb(88, 81, 96), nk_rgb(0, 0, 0));
// }
// else {
// for (int i = 0; i < fileCount; i++)
// {
// nk_draw_text(canvas, space, filePath[i], strlen(filePath[i]), &font->handle, nk_rgb(88, 81, 96), nk_rgb(0, 0, 0));
// space.y = space.y + 20;
// }
// }
//
//}
/*Rectangle to hold extraction info*/
//void draw_info_rectangle_widget(struct nk_context *ctx, struct nk_font *font)
//{
// struct nk_command_buffer *canvas;
// struct nk_input *input = &ctx->input;
// canvas = nk_window_get_canvas(ctx);
//
// struct nk_rect space;
// enum nk_widget_layout_states state;
// state = nk_widget(&space, ctx);
// if (!state) return;
//
// /*if (state != NK_WIDGET_ROM)
// update_your_widget_by_user_input(...);*/
// nk_fill_rect(canvas, space, 5, nk_rgb(88, 81, 96));
// space.x = space.x + 3;
// nk_draw_text(canvas, space, "Input Type: Auto", 16, &font->handle, nk_rgb(88, 81, 96), nk_rgb(0, 0, 0));
// space.y = space.y + 20;
// nk_draw_text(canvas, space, "Output Type: Default(.srt)", 26, &font->handle, nk_rgb(88, 81, 96), nk_rgb(0, 0, 0));
// space.y = space.y + 20;
// nk_draw_text(canvas, space, "Output Path: Default", 20, &font->handle, nk_rgb(88, 81, 96), nk_rgb(0, 0, 0));
// space.y = space.y + 20;
// nk_draw_text(canvas, space, "Hardsubs Extraction: Yes", 24, &font->handle, nk_rgb(88, 81, 96), nk_rgb(0, 0, 0));
//}
int main(void)
{
//Platform
static GLFWwindow *win;
struct nk_context *ctx;
int screenWidth, screenHeight;
//int winWidth, winHeight;
//GLFW
glfwSetErrorCallback(error_callback);
if (!glfwInit())
{
fprintf(stdout, "GLFW failed to initialise.\n");
}
win = glfwCreateWindow(WIDTH_mainPanelAndWindow, HEIGHT_mainPanelandWindow, "CCExtractor", NULL, NULL);
if (win == NULL)
printf("Window Could not be created!\n");
glfwMakeContextCurrent(win);
glfwSetWindowSizeLimits(win, WIDTH_mainPanelAndWindow, HEIGHT_mainPanelandWindow, WIDTH_mainPanelAndWindow, HEIGHT_mainPanelandWindow);
glfwSetWindowUserPointer(win, &ctx);
glfwSetDropCallback(win, drop_callback);
if (glewInit() != GLEW_OK)
{
fprintf(stderr, "Failed to setup GLEW\n");
exit(1);
}
//GUI
struct file_browser browser;
static const struct file_browser reset_browser;
struct media media;
ctx = nk_glfw3_init(win, NK_GLFW3_INSTALL_CALLBACKS);
struct nk_font_atlas *font_atlas;
nk_glfw3_font_stash_begin(&font_atlas);
struct nk_font *droid = nk_font_atlas_add_from_memory(font_atlas, roboto_regular_font, sizeof(roboto_regular_font), 16, 0);
struct nk_font *droid_big = nk_font_atlas_add_from_memory(font_atlas, roboto_regular_font, sizeof(roboto_regular_font), 25, 0);
struct nk_font *droid_head = nk_font_atlas_add_from_memory(font_atlas, roboto_regular_font, sizeof(roboto_regular_font), 20, 0);
nk_glfw3_font_stash_end();
nk_style_set_font(ctx, &droid->handle);
//CHECKBOX VALUES
static int show_terminal_check = nk_false;
static int show_preview_check = nk_false;
static int show_activity_check = nk_false;
static int advanced_mode_check = nk_false;
static int file_extension_check = nk_true;
/*Settings and tab options*/
setup_main_settings(&main_settings);
static struct network_popup network_settings;
setup_network_settings(&network_settings);
static struct output_tab output;
setup_output_tab(&output);
static struct decoders_tab decoders;
setup_decoders_tab(&decoders);
static struct credits_tab credits;
setup_credits_tab(&credits);
static struct input_tab input;
setup_input_tab(&input);
static struct advanced_input_tab advanced_input;
setup_advanced_input_tab(&advanced_input);
static struct debug_tab debug;
setup_debug_tab(&debug);
static struct hd_homerun_tab hd_homerun;
setup_hd_homerun_tab(&hd_homerun);
static struct burned_subs_tab burned_subs;
setup_burned_subs_tab(&burned_subs);
static struct built_string command;
/* icons */
media.icons.home = icon_load(home_icon_data, sizeof(home_icon_data));
media.icons.directory = icon_load(directory_icon_data, sizeof(directory_icon_data));
media.icons.computer = icon_load(computer_icon_data, sizeof(computer_icon_data));
#ifdef _WIN32
media.icons.drives = icon_load(drive_icon_data, sizeof(drive_icon_data));
#endif
media.icons.desktop = icon_load(desktop_icon_data, sizeof(desktop_icon_data));
media.icons.default_file = icon_load(default_icon_data, sizeof(default_icon_data));
media.icons.text_file = icon_load(text_icon_data, sizeof(text_icon_data));
media.icons.music_file = icon_load(music_icon_data, sizeof(music_icon_data));
media.icons.font_file = icon_load(font_icon_data, sizeof(font_icon_data));
media.icons.img_file = icon_load(img_icon_data, sizeof(img_icon_data));
media.icons.movie_file = icon_load(movie_icon_data, sizeof(movie_icon_data));
media_init(&media);
file_browser_init(&browser, &media);
/*Read Last run state*/
FILE *loadFile;
loadFile = fopen("ccxGUI.ini", "r");
if (loadFile != NULL)
{
printf("File found and reading it!\n");
load_data(loadFile, &main_settings, &input, &advanced_input, &output, &decoders, &credits, &debug, &hd_homerun, &burned_subs, &network_settings);
fclose(loadFile);
}
/*Main GUI loop*/
while (nk_true)
{
if (glfwWindowShouldClose(win))
{
FILE *saveFile;
saveFile = fopen("ccxGUI.ini", "w");
save_data(saveFile, &main_settings, &input, &advanced_input, &output, &decoders, &credits, &debug, &hd_homerun, &burned_subs, &network_settings);
fclose(saveFile);
break;
}
//Input
glfwPollEvents();
nk_glfw3_new_frame();
//Popups
static int show_progress_details = nk_false;
static int show_about_ccx = nk_false;
static int show_getting_started = nk_false;
//GUI
if (nk_begin(ctx, "CCExtractor", nk_rect(0, 0, WIDTH_mainPanelAndWindow, HEIGHT_mainPanelandWindow),
NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_BACKGROUND))
{
//MENUBAR
nk_menubar_begin(ctx);
nk_layout_row_begin(ctx, NK_STATIC, 30, 3);
nk_layout_row_push(ctx, 80);
if (nk_menu_begin_label(ctx, "Preferences", NK_TEXT_LEFT, nk_vec2(120, 200)))
{
nk_layout_row_dynamic(ctx, 30, 1);
if (nk_menu_item_label(ctx, "Reset Defaults", NK_TEXT_LEFT))
{
remove("ccxGUI.ini");
setup_main_settings(&main_settings);
setup_network_settings(&network_settings);
setup_output_tab(&output);
setup_decoders_tab(&decoders);
setup_credits_tab(&credits);
setup_input_tab(&input);
setup_advanced_input_tab(&advanced_input);
setup_debug_tab(&debug);
setup_hd_homerun_tab(&hd_homerun);
setup_burned_subs_tab(&burned_subs);
}
if (nk_menu_item_label(ctx, "Network Settings", NK_TEXT_LEFT))
network_settings.show_network_settings = nk_true;
nk_menu_end(ctx);
}
nk_layout_row_push(ctx, 70);
if (nk_menu_begin_label(ctx, "Windows", NK_TEXT_LEFT, nk_vec2(120, 200)))
{
nk_layout_row_dynamic(ctx, 30, 1);
nk_checkbox_label(ctx, "Activity", &show_activity_check);
nk_checkbox_label(ctx, "Terminal", &show_terminal_check);
nk_checkbox_label(ctx, "Preview", &show_preview_check);
nk_menu_end(ctx);
}
nk_layout_row_push(ctx, 45);
if (nk_menu_begin_label(ctx, "Help", NK_TEXT_LEFT, nk_vec2(120, 200)))
{
nk_layout_row_dynamic(ctx, 30, 1);
if (nk_menu_item_label(ctx, "Getting Started", NK_TEXT_LEFT))
show_getting_started = nk_true;
if (nk_menu_item_label(ctx, "About CCExtractor", NK_TEXT_LEFT))
show_about_ccx = nk_true;
nk_menu_end(ctx);
}
//Network Settings
if (network_settings.show_network_settings)
draw_network_popup(ctx, &network_settings);
//About CCExtractor Popup
if (show_about_ccx)
draw_about_ccx_popup(ctx, &show_about_ccx, &droid_big->handle, &droid_head->handle);
//Getting Started
if (show_getting_started)
draw_getting_started_popup(ctx, &show_getting_started);
//Color Popup
if (output.color_popup)
draw_color_popup(ctx, &output);
//File Browser as Popup
if (main_settings.scaleWindowForFileBrowser)
{
int width = 0, height = 0;
glfwGetWindowSize(win, &width, &height);
glfwSetWindowSize(win, 930, 650);
glfwSetWindowSizeLimits(win, 930, 650, 930, 650);
file_browser_run(&browser, ctx, &main_settings, &output, &debug, &hd_homerun);
}
//Thread popop when file can't be read
if (main_settings.threadPopup)
draw_thread_popup(ctx, &main_settings.threadPopup);
//Thread popup for hd_homerun thread
if (hd_homerun.threadPopup)
draw_thread_popup(ctx, &hd_homerun.threadPopup);
nk_layout_row_end(ctx);
nk_menubar_end(ctx);
nk_layout_space_begin(ctx, NK_STATIC, 15, 1);
nk_layout_space_end(ctx);
/*TABS TRIGGERED IN ADVANCED MODE FLAG*/
if (advanced_mode_check)
{
static int current_tab = 0;
enum tab_name
{
MAIN,
INPUT,
ADV_INPUT,
OUTPUT,
DECODERS,
CREDITS,
DEBUG,
HDHOMERUN,
BURNEDSUBS
};
const char *names[] = {"Main", "Input", "Advanced Input", "Output", "Decoders", "Credits", "Debug", "HDHomeRun", "BurnedSubs"};
float id = 0;
int i;
nk_style_push_vec2(ctx, &ctx->style.window.spacing, nk_vec2(0, 0));
nk_style_push_float(ctx, &ctx->style.button.rounding, 0);
nk_layout_row_begin(ctx, NK_STATIC, 20, 9);
for (i = 0; i < 9; ++i)
{
/*Make sure button perfectly fits text*/
const struct nk_user_font *f = ctx->style.font;
float text_width = f->width(f->userdata, f->height, names[i], nk_strlen(names[i]));
float widget_width = text_width + 3 * ctx->style.button.padding.x;
nk_layout_row_push(ctx, widget_width);
if (current_tab == i)
{
/*Active tab gets highlighted*/
struct nk_style_item button_color = ctx->style.button.normal;
ctx->style.button.normal = ctx->style.button.active;
current_tab = nk_button_label(ctx, names[i]) ? i : current_tab;
ctx->style.button.normal = button_color;
}
else
current_tab = nk_button_label(ctx, names[i]) ? i : current_tab;
}
nk_style_pop_float(ctx);
/*Body*/
nk_layout_row_dynamic(ctx, tab_screen_height, 1);
if (nk_group_begin(ctx, "Advanced Tabs", NK_WINDOW_NO_SCROLLBAR))
{
nk_style_pop_vec2(ctx);
switch (current_tab)
{
case MAIN:
tab_screen_height = 0;
break;
case INPUT:
draw_input_tab(ctx, &tab_screen_height, &input, &decoders);
break;
case ADV_INPUT:
draw_advanced_input_tab(ctx, &tab_screen_height, &advanced_input);
break;
case OUTPUT:
draw_output_tab(ctx, &tab_screen_height, &output, &main_settings);
break;
case DECODERS:
draw_decoders_tab(ctx, &tab_screen_height, &decoders);
break;
case CREDITS:
draw_credits_tab(ctx, &tab_screen_height, &credits);
break;
case DEBUG:
draw_debug_tab(ctx, &tab_screen_height, &main_settings, &output, &debug);
break;
case HDHOMERUN:
draw_hd_homerun_tab(ctx, &tab_screen_height, &hd_homerun, &main_settings);
break;
case BURNEDSUBS:
draw_burned_subs_tab(ctx, &tab_screen_height, &burned_subs);
break;
}
nk_group_end(ctx);
}
else
nk_style_pop_vec2(ctx);
}
//ADVANCED MODE FLAG
static const float ratio_adv_mode[] = {0.75f, 0.22f, .03f};
nk_layout_row(ctx, NK_DYNAMIC, 20, 3, ratio_adv_mode);
nk_spacing(ctx, 1);
nk_checkbox_label(ctx, "Advanced Mode", &advanced_mode_check);
//RADIO BUTTON 1
static const float ratio_button[] = {.10f, .90f};
static const float check_extension_ratio[] = {.10f, .53f, .12f, .15f, .10f};
//static int op = FILES;
nk_layout_row(ctx, NK_DYNAMIC, 20, 2, ratio_button);
nk_spacing(ctx, 1);
if (nk_option_label(ctx, "Extract from files below:", main_settings.port_or_files == FILES))
{
//op = FILES;
main_settings.port_or_files = FILES;
}
//CHECKBOX FOR FILE TYPES
static int add_remove_button = nk_false;
nk_layout_row(ctx, NK_DYNAMIC, 20, 5, check_extension_ratio);
nk_spacing(ctx, 1);
nk_checkbox_label(ctx, "Check for common video file extensions", &file_extension_check);
if (main_settings.filename_count > 0)
{
if (nk_button_label(ctx, "Add"))
{
main_settings.is_file_browser_active = nk_true;
main_settings.scaleWindowForFileBrowser = nk_true;
}
for (int i = 0; i < main_settings.filename_count; i++)
{
if (main_settings.is_file_selected[i])
{
add_remove_button = nk_true;
break;
}
else
add_remove_button = nk_false;
}
if (add_remove_button)
{
if (nk_button_label(ctx, "Remove"))
{
for (int i = main_settings.filename_count - 1; i != -1; i--)
if (main_settings.is_file_selected[i])
{
remove_path_entry(&main_settings, i);
main_settings.is_file_selected[i] = nk_false;
}
}
}
else if (nk_button_label(ctx, "Clear"))
{
free(main_settings.filenames);
main_settings.filename_count = 0;
}
}
//RECTANGLE-FILES
static const float ratio_rect_files[] = {0.10f, 0.80f};
nk_layout_row(ctx, NK_DYNAMIC, 180, 2, ratio_rect_files);
nk_spacing(ctx, 1);
if (nk_group_begin(ctx, "Files in extraction queue:", NK_WINDOW_BORDER | NK_WINDOW_TITLE))
{
if (main_settings.filename_count != 0)
{
int i = 0;
nk_layout_row_static(ctx, 18, 380, 1);
for (i = 0; i < main_settings.filename_count; ++i)
nk_selectable_label(ctx, truncate_path_string(main_settings.filenames[i]), NK_TEXT_LEFT, &main_settings.is_file_selected[i]);
}
else
{
nk_layout_row_dynamic(ctx, 1, 1);
nk_spacing(ctx, 1);
nk_layout_row_dynamic(ctx, 25, 1);
nk_label(ctx, "Drag and Drop files for extraction.", NK_TEXT_CENTERED);
nk_layout_row_dynamic(ctx, 25, 1);
nk_label(ctx, "OR", NK_TEXT_CENTERED);
nk_layout_row_dynamic(ctx, 25, 3);
nk_spacing(ctx, 1);
if (nk_button_label(ctx, "Browse Files"))
{
main_settings.is_file_browser_active = nk_true;
main_settings.scaleWindowForFileBrowser = nk_true;
}
nk_spacing(ctx, 1);
}
nk_group_end(ctx);
}
//RadioButton 2 along with combobox
static const float ratio_port[] = {0.10f, 0.20f, 0.20f, 0.20f, 0.20f, 0.10f};
nk_layout_row(ctx, NK_DYNAMIC, 20, 6, ratio_port);
nk_spacing(ctx, 1);
if (nk_option_label(ctx, "Extract from", main_settings.port_or_files == PORT))
{
//op = PORT;
main_settings.port_or_files = PORT;
}
main_settings.port_select = nk_combo(ctx, main_settings.port_type, 2, main_settings.port_select, 20, nk_vec2(85, 100));
nk_label(ctx, " stream, on port:", NK_TEXT_LEFT);
//RADDIO BUTTON 2, TEXTEDIT FOR ENTERING PORT NUMBER
static int len;
static char buffer[10];
nk_edit_string(ctx, NK_EDIT_SIMPLE, main_settings.port_num, &main_settings.port_num_len, 8, nk_filter_decimal);
nk_layout_space_begin(ctx, NK_STATIC, 10, 1);
nk_layout_space_end(ctx);
//Extraction Information
nk_layout_row_dynamic(ctx, 10, 1);
nk_text(ctx, "Extraction Info:", 16, NK_TEXT_CENTERED);
//RECTANGLE-INFO
static const float ratio_rect_info[] = {0.10f, 0.80f, 0.10f};
nk_layout_row(ctx, NK_DYNAMIC, 75, 2, ratio_rect_info);
nk_spacing(ctx, 1);
if (nk_group_begin(ctx, "Extraction Info:", NK_WINDOW_BORDER))
{
if (main_settings.filename_count != 0)
{
nk_layout_row_static(ctx, 18, 380, 1);
nk_label(ctx, concat("Input type: ", input.type[input.type_select]), NK_TEXT_LEFT);
nk_label(ctx, concat("Output type: ", output.type[output.type_select]), NK_TEXT_LEFT);
if (output.is_filename)
nk_label(ctx, concat("Output path: ", output.filename), NK_TEXT_LEFT);
else
nk_label(ctx, "Output path: Default", NK_TEXT_LEFT);
if (burned_subs.is_burned_subs)
nk_label(ctx, "Hardsubtitles extraction: Yes", NK_TEXT_LEFT);
else
nk_label(ctx, "Hardsubtitles extraction: No", NK_TEXT_LEFT);
}
nk_group_end(ctx);
}
nk_layout_space_begin(ctx, NK_STATIC, 10, 1);
nk_layout_space_end(ctx);
//PROGRESSBAR
static const float ratio_progress[] = {0.10f, 0.03f, 0.57f, 0.03f, 0.17f, 0.10f};
nk_layout_row(ctx, NK_DYNAMIC, 20, 6, ratio_progress);
nk_spacing(ctx, 1);
nk_spacing(ctx, 1);
nk_progress(ctx, &main_settings.progress_cursor, 101, nk_false);
//Extract Button
nk_spacing(ctx, 1);
if (nk_button_label(ctx, "Extract"))
{
setup_and_create_thread(&main_settings, &command);
}
nk_layout_space_begin(ctx, NK_STATIC, 10, 1);
nk_layout_space_end(ctx);
//PROGRESS_DETAILS_BUTTON
if (!show_activity_check)
{
nk_layout_row_dynamic(ctx, 20, 3);
nk_spacing(ctx, 1);
if (nk_button_label(ctx, "Progress Details"))
{
show_progress_details = nk_true;
}
nk_spacing(ctx, 1);
}
//PROGRESS_DETAILS_POPUP
if (show_progress_details)
draw_progress_details_popup(ctx, &show_progress_details, &main_settings);
//build command string
command_builder(&command, &main_settings, &network_settings, &input, &advanced_input, &output, &decoders, &credits, &debug, &burned_subs);
}
nk_end(ctx);
glfwGetWindowSize(win, &screenWidth, &screenHeight);
if (!main_settings.scaleWindowForFileBrowser)
{
if (show_activity_check && show_preview_check && show_terminal_check)
{
if (screenWidth != 930 || screenHeight != 650)
{
glfwSetWindowSize(win, 930, 550);
glfwSetWindowSizeLimits(win, 930, 650, 930, 650);
}
preview(ctx, 530, 0, 400, 550, &main_settings);
terminal(ctx, 0, 550, 530, 100, &command.term_string);
activity(ctx, 530, 550, 400, 100, &main_settings);
}
if (show_activity_check && show_preview_check && !show_terminal_check)
{
if (screenWidth != 930 || screenHeight != 650)
{
glfwSetWindowSize(win, 930, 650);
glfwSetWindowSizeLimits(win, 930, 650, 930, 650);
}
preview(ctx, 530, 0, 400, 650, &main_settings);
activity(ctx, 0, 550, 530, 100, &main_settings);
}
if (show_activity_check && !show_preview_check && show_terminal_check)
{
if (screenWidth != 930 || screenHeight != 650)
{
glfwSetWindowSize(win, 930, 650);
glfwSetWindowSizeLimits(win, 930, 650, 930, 650);
}
activity(ctx, 530, 0, 400, 650, &main_settings);
terminal(ctx, 0, 550, 530, 100, &command.term_string);
}
if (show_terminal_check && show_preview_check && !show_activity_check)
{
if (screenWidth != 930 || screenHeight != 650)
{
glfwSetWindowSize(win, 930, 650);
glfwSetWindowSizeLimits(win, 930, 650, 930, 650);
}
terminal(ctx, 0, 550, 530, 100, &command.term_string);
preview(ctx, 530, 0, 400, 650, &main_settings);
}
if (show_activity_check && !show_preview_check && !show_terminal_check)
{
if (screenWidth != 930 || screenHeight == 650)
{
glfwSetWindowSize(win, 930, 550);
glfwSetWindowSizeLimits(win, 930, 550, 930, 550);
}
activity(ctx, 530, 0, 400, 550, &main_settings);
}
if (show_terminal_check && !show_activity_check && !show_preview_check)
{
if (screenHeight != 650 || screenWidth == 930)
{
glfwSetWindowSize(win, 530, 650);
glfwSetWindowSizeLimits(win, 530, 650, 530, 650);
}
terminal(ctx, 0, 550, 530, 100, &command.term_string);
}
if (show_preview_check && !show_terminal_check && !show_activity_check)
{
if (screenHeight != 650 || screenWidth == 930)
{
glfwSetWindowSize(win, 930, 550);
glfwSetWindowSizeLimits(win, 930, 550, 930, 550);
}
preview(ctx, 530, 0, 400, 550, &main_settings);
}
if (!show_preview_check && !show_terminal_check && !show_activity_check)
{
glfwSetWindowSize(win, WIDTH_mainPanelAndWindow, HEIGHT_mainPanelandWindow);
glfwSetWindowSizeLimits(win, WIDTH_mainPanelAndWindow, HEIGHT_mainPanelandWindow,
WIDTH_mainPanelAndWindow, HEIGHT_mainPanelandWindow);
}
}
else
{
glfwSetWindowSize(win, 930, 650);
glfwSetWindowSizeLimits(win, 930, 650, 930, 650);
}
glViewport(0, 0, screenWidth, screenHeight);
glClear(GL_COLOR_BUFFER_BIT);
/* IMPORTANT: `nk_glfw_render` modifies some global OpenGL state
* with blending, scissor, face culling and depth test and defaults everything
* back into a default state. Make sure to either save and restore or
* reset your own state after drawing rendering the UI. */
nk_glfw3_render(NK_ANTI_ALIASING_ON);
glfwSwapBuffers(win);
}
glDeleteTextures(1, (const GLuint *)&media.icons.home.handle.id);
glDeleteTextures(1, (const GLuint *)&media.icons.directory.handle.id);
glDeleteTextures(1, (const GLuint *)&media.icons.computer.handle.id);
#ifdef _WIN32
glDeleteTextures(1, (const GLuint *)&media.icons.drives.handle.id);
#endif
glDeleteTextures(1, (const GLuint *)&media.icons.desktop.handle.id);
glDeleteTextures(1, (const GLuint *)&media.icons.default_file.handle.id);
glDeleteTextures(1, (const GLuint *)&media.icons.text_file.handle.id);
glDeleteTextures(1, (const GLuint *)&media.icons.music_file.handle.id);
glDeleteTextures(1, (const GLuint *)&media.icons.font_file.handle.id);
glDeleteTextures(1, (const GLuint *)&media.icons.img_file.handle.id);
glDeleteTextures(1, (const GLuint *)&media.icons.movie_file.handle.id);
file_browser_free(&browser);
//free(main_settings.filenames);
nk_glfw3_shutdown();
glfwTerminate();
return 0;
}
void setup_main_settings(struct main_tab *main_settings)
{
main_settings->is_check_common_extension = nk_false;
main_settings->port_num_len = 0;
main_settings->port_or_files = FILES;
main_settings->port_type = (char **)malloc(2 * sizeof(char *));
main_settings->port_type[0] = "UDP";
main_settings->port_type[1] = "TCP";
main_settings->port_select = 0;
main_settings->is_file_browser_active = nk_false;
main_settings->scaleWindowForFileBrowser = nk_false;
main_settings->preview_string_count = 0;
main_settings->activity_string_count = 0;
main_settings->threadPopup = nk_false;
}
char *truncate_path_string(char *filePath)
{
char *file_path = strdup(filePath);
int i, j, z, slash_length, fileNameTruncated_index, copycount, prefix_length;
char file_name[PATH_LENGTH], *ptr_slash, fileNameTruncated[NAME_LENGTH];
//strcpy(filePath[i], paths[i]);
if (strlen(filePath) >= PATH_LENGTH - 1)
{
#ifdef _WIN32
ptr_slash = strrchr(file_path, '\\');
#else
ptr_slash = strrchr(file_path, '/');
#endif
slash_length = strlen(ptr_slash);
if (slash_length >= NAME_LENGTH)
{
fileNameTruncated_index = NAME_LENGTH - 1;
for (z = 0; z < 6; z++)
{
fileNameTruncated[fileNameTruncated_index] = ptr_slash[slash_length];
fileNameTruncated_index--;
slash_length--;
}
for (z = 0; z < 4; z++)
{
fileNameTruncated[fileNameTruncated_index] = '.';
fileNameTruncated_index--;
}
strncpy(fileNameTruncated, ptr_slash, 47);
strncpy(file_name, file_path, 7);
file_name[7] = '.';
file_name[8] = '.';
file_name[9] = '.';
file_name[10] = '\0';
file_name[11] = '\0';
file_name[12] = '\0';
strcat(file_name, fileNameTruncated);
strcpy(file_path, file_name);
}
else
{
copycount = PATH_LENGTH - 1;
prefix_length = copycount - slash_length - 3;
strncpy(file_name, file_path, prefix_length);
while (slash_length >= 0)
{
file_name[copycount] = ptr_slash[slash_length];
copycount--;
slash_length--;
}
for (j = 0; j < 3; j++, copycount--)
file_name[copycount] = '.';
file_name[65] = '\0';
strcpy(file_path, file_name);
}
return file_path;
}
else
return filePath;
}
void remove_path_entry(struct main_tab *main_settings, int indexToRemove)
{
//printf("Beginning processing. Array is currently: ");
//for (int i = 0; i < arraySize; ++i)
// printf("%d ", (*array)[i]);
//printf("\n");
char **temp = (char **)calloc(main_settings->filename_count, sizeof(char *)); // allocate an array with a size 1 less than the current one
memmove(
temp,
main_settings->filenames,
(indexToRemove + 1) * sizeof(char *)); // copy everything BEFORE the index
memmove(
temp + indexToRemove,
(main_settings->filenames) + (indexToRemove + 1),
(main_settings->filename_count - indexToRemove) * sizeof(char *)); // copy everything AFTER the index
free(main_settings->filenames);
main_settings->filenames = temp;
main_settings->filename_count--;
main_settings->filenames[main_settings->filename_count] = NULL;
}
struct nk_image
icon_load(char icon_data[], int len)
{
int x, y, n;
GLuint tex;
unsigned char *data = stbi_load_from_memory(icon_data, len, &x, &y, &n, 0);
if (!data)
die("[SDL]: failed to load icons");
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
stbi_image_free(data);
return nk_image_id((int)tex);
}
char *concat(char *string1, char *string2)
{
static char prefix[300], suffix[300];
strcpy(prefix, string1);
strcpy(suffix, string2);
return strcat(prefix, suffix);
}

View File

@@ -1,35 +0,0 @@
#ifndef CCEXTRACTORGUI_H
#define CCEXTRACTORGUI_H
#ifndef NK_IMPLEMENTATION
#include "nuklear_lib/nuklear.h"
#endif // !NK_IMPLEMENTATION
struct main_tab
{
enum {PORT, FILES} port_or_files;
char port_num[8];
int port_num_len;
int is_check_common_extension;
char **port_type;
int port_select;
char **filenames;
int filename_count;
int is_file_selected[1000];
int is_file_browser_active;
int scaleWindowForFileBrowser;
nk_size progress_cursor;
char** activity_string;
int activity_string_count;
char** preview_string;
int preview_string_count;
int threadPopup;
};
void setup_main_settings(struct main_tab *main_settings);
char* truncate_path_string(char *filePath);
void remove_path_entry(struct main_tab *main_settings, int indexToRemove);
char* concat(char* string1, char *string2);
#endif //!CCEXTRACTORGUI_H

View File

@@ -1,374 +0,0 @@
#include "ccx_cli_thread.h"
#include "ccextractorGUI.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_WAIT 10
#define PROGRESS_COMPLETE 100
void *extract_thread(void *extract_args)
{
struct args_extract *params = (struct args_extract *)extract_args;
static char term_string[500];
strcpy(term_string, params->command_string);
strcat(term_string, " ");
strcat(term_string, params->file_string);
strcat(term_string, " 1>>ccx.log 2>>gui_report.log");
printf("%s", term_string);
system(term_string);
pthread_exit(0);
}
void *read_activity_data(void *read_args)
{
puts("Inside activity thread!");
char line[500];
char buffer[500];
#if UNIX
struct timespec time;
time.tv_sec = 0;
time.tv_nsec = 10000000L;
#endif
int wait = 0;
struct args_extract *read_params = (struct args_extract *)read_args;
FILE *file;
char current_input[500];
int concat_index = 0;
file = fopen("ccx.log", "r");
while (file == NULL)
{
printf("Cannot open ccx.log, trying again.\n");
file = fopen("ccx.log", "r");
#if UNIX
nanosleep(&time, NULL);
#else
_sleep(10);
#endif
wait++;
if (wait == MAX_WAIT)
{
read_params->main_threadsettings->threadPopup = nk_true;
return 0;
}
}
while (!feof(file))
{
if (fgets(current_input, sizeof(current_input), file) == NULL)
continue;
if (concat_index == 0)
{
strcpy(line, current_input);
}
else
{
strcat(line, current_input);
}
concat_index++;
if (current_input[strlen(current_input) - 1] != '\n')
continue;
sscanf(line, "%[^\n]", buffer);
if (read_params->main_threadsettings->activity_string_count == 0)
read_params->main_threadsettings->activity_string =
malloc(sizeof(*read_params->main_threadsettings->activity_string));
else
read_params->main_threadsettings->activity_string =
realloc(read_params->main_threadsettings->activity_string,
(read_params->main_threadsettings->activity_string_count + 1) * sizeof(char *));
read_params->main_threadsettings->activity_string[read_params->main_threadsettings->activity_string_count] = strdup(buffer);
read_params->main_threadsettings->activity_string_count++;
memset(line, 0, sizeof(line));
memset(buffer, 0, sizeof(buffer));
concat_index = 0;
}
}
void *read_data_from_thread(void *read_args)
{
pthread_t tid_activity;
pthread_attr_t attr_activity;
static char buffer[500];
char t_start[6], t_end[6], subtitle1[100], subtitle2[100];
#if UNIX
struct timespec time;
time.tv_sec = 0;
time.tv_nsec = 10000000L;
#endif
int wait = 0;
struct args_extract *read_params = (struct args_extract *)read_args;
int unknown1 = 0, unknown2 = 0, progress_count = 0;
FILE *file;
char prev_line[500];
char line[500];
char current_input[500];
int concat_index = 0;
char sub_line[500];
char prog_line[500];
int subs_success1, subs_success2, progress_success;
/*Setup activity thread*/
pthread_attr_init(&attr_activity);
int err = pthread_create(&tid_activity, &attr_activity, read_activity_data, read_params);
if (!err)
puts("Activity Thread created");
file = fopen("gui_report.log", "r");
while (file == NULL)
{
printf("Cannot open gui_report.log, trying again.\n");
file = fopen("gui_report.log", "r");
#if UNIX
nanosleep(&time, NULL);
#else
_sleep(10);
#endif
wait++;
if (wait >= MAX_WAIT)
{
read_params->main_threadsettings->threadPopup = nk_true;
return 0;
}
}
while (1)
{
if (fgets(current_input, sizeof(current_input), file) == NULL)
continue;
if (concat_index == 0)
{
strcpy(line, current_input);
}
else
{
strcat(line, current_input);
}
concat_index++;
if (current_input[strlen(current_input) - 1] != '\n')
continue;
progress_success = sscanf(line, "###PROGRESS#%d#%d#%d", &progress_count, &unknown1, &unknown2);
if (progress_success == 3)
read_params->main_threadsettings->progress_cursor = progress_count;
subs_success1 = sscanf(line, "###SUBTITLE#%[^#]#%[^#]#%[^\n]", t_start, t_end, subtitle1);
subs_success2 = sscanf(line, "###SUBTITLE###%[^\n]", subtitle2);
if (subs_success1 == 3)
{
sprintf(buffer, "%s-%s: %s", t_start, t_end, subtitle1);
if (read_params->main_threadsettings->preview_string_count == 0)
read_params->main_threadsettings->preview_string =
malloc(sizeof(*read_params->main_threadsettings->preview_string));
else
read_params->main_threadsettings->preview_string =
realloc(read_params->main_threadsettings->preview_string,
(read_params->main_threadsettings->preview_string_count + 1) * sizeof(char *));
read_params->main_threadsettings->preview_string[read_params->main_threadsettings->preview_string_count] = strdup(buffer);
read_params->main_threadsettings->preview_string_count++;
}
if (subs_success2 == 1)
{
sprintf(buffer, " %s", subtitle2);
if (read_params->main_threadsettings->preview_string_count == 0)
read_params->main_threadsettings->preview_string =
malloc(sizeof(*read_params->main_threadsettings->preview_string));
else
read_params->main_threadsettings->preview_string =
realloc(read_params->main_threadsettings->preview_string,
(read_params->main_threadsettings->preview_string_count + 1) * sizeof(char *));
read_params->main_threadsettings->preview_string[read_params->main_threadsettings->preview_string_count] = strdup(buffer);
read_params->main_threadsettings->preview_string_count++;
}
if (progress_count == PROGRESS_COMPLETE)
break;
memset(line, 0, sizeof(line));
concat_index = 0;
}
printf("progress count:%d\n", progress_count);
fclose(file);
printf("File closed\n");
for (int i = 0; i < read_params->main_threadsettings->preview_string_count; i++)
printf("%s\n", read_params->main_threadsettings->preview_string[i]);
pthread_exit(0);
}
void *feed_files_for_extraction(void *file_args)
{
printf("Inside feeder\n");
struct args_extract *extract_params = (struct args_extract *)file_args;
printf("count:%d\n", extract_params->main_threadsettings->filename_count);
extract_params->command_string = extract_params->threadcommand->term_string;
int count = extract_params->main_threadsettings->filename_count;
pthread_t tid_extract, tid_read;
pthread_attr_t attr_extract, attr_read;
for (int i = 0; count != 0; i++, count--)
{
pthread_t tid_extract, tid_read;
pthread_attr_t attr_extract, attr_read;
pthread_attr_init(&attr_extract);
pthread_attr_init(&attr_read);
extract_params->main_threadsettings->is_file_selected[i] = nk_true;
extract_args.file_string = extract_params->main_threadsettings->filenames[i];
int err1 = pthread_create(&tid_extract, &attr_extract, extract_thread, extract_params);
int err2 = pthread_create(&tid_read, &attr_read, read_data_from_thread, extract_params);
if (!err1)
printf("Extraction Thread Complete:%d\n", i);
if (!err2)
printf("Read Thread Complete:%d\n", i);
pthread_join(tid_extract, NULL);
printf("Extract thread joined\n");
pthread_join(tid_read, NULL);
printf("Read thread joined\n");
extract_params->main_threadsettings->is_file_selected[i] = nk_false;
remove("gui_report.log");
remove("ccx.log");
}
printf("File feeding over\n");
}
void setup_and_create_thread(struct main_tab *main_settings, struct built_string *command)
{
extract_args.main_threadsettings = (struct main_tab *)main_settings;
extract_args.threadcommand = (struct built_string *)command;
pthread_attr_init(&attr_launch);
int err = pthread_create(&tid_launch, &attr_launch, feed_files_for_extraction, &extract_args);
if (!err)
printf("Feeder created!\n");
}
/*THREAD FUNCTIONS FOR HD_HOMERUN*/
void *find_hd_homerun_devices(void *args)
{
char command[300];
extract_args.homerun_thread = (struct hd_homerun_tab *)args;
int wait = 0;
FILE *file;
char line[200];
int device_success;
char device[200];
#if UNIX
struct timespec time;
time.tv_sec = 0;
time.tv_nsec = 10000000L;
#endif
#if HD_HOMERUN
strcpy(command, "hdhomerun_config");
#else
strncpy(command, extract_args.homerun_thread->location, extract_args.homerun_thread->location_len);
#endif
strcpy(command, " discover >> homerun.log");
system(command);
file = fopen("homerun.log", "r");
while (file == NULL)
{
printf("Cannot open file! Trying again.\n");
file = fopen("homerun.log", "r");
#if UNIX
nanosleep(&time, NULL);
#else
_sleep(10);
#endif
wait++;
if (wait >= MAX_WAIT)
{
extract_args.homerun_thread->threadPopup = nk_true;
return 0;
}
}
while (1)
{
fgets(line, sizeof(line), file);
device_success = sscanf(line, "hdhomerun device %[^\n]", device);
if (feof(file))
break;
if (device_success == 1)
{
if (extract_args.homerun_thread->device_num == 0)
{
extract_args.homerun_thread->devices = malloc(sizeof(char *));
extract_args.homerun_thread->devices[extract_args.homerun_thread->device_num] = strdup(device);
extract_args.homerun_thread->device_num++;
}
else
{
extract_args.homerun_thread->devices = realloc(extract_args.homerun_thread->devices,
(extract_args.homerun_thread->device_num + 1) * sizeof(char *));
extract_args.homerun_thread->devices[extract_args.homerun_thread->device_num] = strdup(device);
extract_args.homerun_thread->device_num++;
}
}
}
printf("Find device thread finished\n");
}
void *setup_hd_homerun_device(void *args)
{
char device[20];
extract_args.homerun_thread = (struct hd_homerun_tab *)args;
char channel_command[300];
char program_command[300];
char target_command[300];
sscanf(extract_args.homerun_thread->devices[extract_args.homerun_thread->selected], "%s", device);
#if HD_HOMERUN
strcpy(channel_command, "hdhomerun_config");
strcpy(program_command, "hdhomerun_config");
strcpy(target_command, "hdhomerun_config");
#else
strncpy(channel_command, extract_args.homerun_thread->location, extract_args.homerun_thread->location_len);
strncpy(program_command, extract_args.homerun_thread->location, extract_args.homerun_thread->location_len);
strncpy(target_command, extract_args.homerun_thread->location, extract_args.homerun_thread->location_len);
#endif
strcat(channel_command, " ");
strcat(program_command, " ");
strcat(target_command, " ");
strcat(channel_command, device);
strcat(program_command, device);
strcat(target_command, device);
strcat(channel_command, " set /tuner");
strcat(program_command, " set /tuner");
strcat(target_command, " set /tuner");
strncat(channel_command, extract_args.homerun_thread->tuner, extract_args.homerun_thread->tuner_len);
strncat(program_command, extract_args.homerun_thread->tuner, extract_args.homerun_thread->tuner_len);
strncat(target_command, extract_args.homerun_thread->tuner, extract_args.homerun_thread->tuner_len);
strcat(channel_command, "/channel ");
strcat(program_command, "/program ");
strcat(target_command, "/target ");
strncat(channel_command, extract_args.homerun_thread->channel, extract_args.homerun_thread->channel_len);
strncat(program_command, extract_args.homerun_thread->program, extract_args.homerun_thread->program_len);
strncat(target_command, extract_args.homerun_thread->ipv4_address, extract_args.homerun_thread->ipv4_address_len);
system(channel_command);
system(program_command);
system(target_command);
pthread_exit(0);
}

View File

@@ -1,40 +0,0 @@
#ifndef CCX_CLI_THREAD_H
#define CCX_CLI_THREAD_H
#define HAVE_STRUCT_TIMESPEC
#include "ccextractorGUI.h"
#include "popups.h"
#include "tabs.h"
#include "command_builder.h"
#include "pthread.h"
struct args_extract {
struct main_tab *main_threadsettings;
struct built_string *threadcommand;
struct hd_homerun_tab *homerun_thread;
char *file_string;
char *command_string;
};
static struct args_extract extract_args;
//FOR EXTRACT BUTTON TRIGGER ---- MAIN_TAB
pthread_t tid_launch;
pthread_attr_t attr_launch;
//FOR FIND DEVICES BUTTON TRIGGER ----- HD_HOMERUN_TAB
pthread_t tid_find;
pthread_attr_t attr_find;
//FOR SETUP DEVICE BUTTON TRIGGER ------ HD_HOMERUN_TAB
pthread_t tid_setup;
pthread_attr_t attr_setup;
void* read_activity_data(void *read_args);
void* read_data_from_thread(void* read_args);
void* extract_thread(void* extract_args);
void* feed_files_for_extraction(void* file_args);
void setup_and_create_thread(struct main_tab *main_settings, struct built_string *command);
void* find_hd_homerun_devices(void *args);
void* setup_hd_homerun_device(void *args);
#endif //!CCX_CLI_THREAD_H

View File

@@ -1,504 +0,0 @@
#ifndef NK_IMPLEMENTATION
#include "nuklear_lib/nuklear.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#endif //!NK_IMPLEMENTATION
#include "ccextractorGUI.h"
#include "tabs.h"
#include "command_builder.h"
void command_builder(struct built_string *command,
struct main_tab *main_settings,
struct network_popup *network_settings, struct input_tab *input,
struct advanced_input_tab *advanced_input,
struct output_tab *output,
struct decoders_tab *decoders,
struct credits_tab *credits,
struct debug_tab *debug,
struct burned_subs_tab *burned_subs)
{
static char buffer[1000];
#ifdef _WIN32
strcpy(buffer, "ccextractorwin --gui_mode_reports");
#else
strcpy(buffer, "./ccextractor --gui_mode_reports");
#endif
/*INPUT COMMANDS*/
if (main_settings->port_or_files == FILES)
{
if (input->type_select != 0)
{
strcat(buffer, " -in=");
strcat(buffer, input->type[input->type_select]);
}
if (input->is_split)
strcat(buffer, " --videoedited");
if (input->is_process_from)
{
strcat(buffer, " -startat ");
strcat(buffer, input->from_time_buffer);
}
if (input->is_process_until)
{
strcat(buffer, " -endat ");
strcat(buffer, input->until_time_buffer);
}
switch (input->elementary_stream)
{
case AUTO_DETECT:
break;
case STREAM_TYPE:
strcat(buffer, " -datastreamtype ");
strncat(buffer, input->stream_type, input->stream_type_len);
break;
case STREAM_PID:
strcat(buffer, " -datapid ");
strncat(buffer, input->stream_pid, input->stream_pid_len);
}
if (input->is_assume_mpeg)
{
strcat(buffer, " -streamtype ");
strncat(buffer, input->mpeg_type, input->mpeg_type_len);
}
if (decoders->teletext_dvb == TELETEXT)
{
switch (input->teletext_decoder)
{
case AUTO_DECODE:
break;
case FORCE:
strcat(buffer, " -teletext");
break;
case DISABLE:
strcat(buffer, " -noteletext");
}
if (input->is_process_teletext_page)
{
strcat(buffer, " -tpage ");
strncat(buffer, input->teletext_page_number, input->teletext_page_numer_len);
}
}
switch (input->is_limit)
{
case NO_LIMIT:
break;
case LIMITED:
strcat(buffer, " --screenfuls ");
strcat(buffer, input->screenful_limit_buffer);
}
switch (input->clock_input)
{
case AUTO:
break;
case GOP:
strcat(buffer, " --goptime");
break;
case PTS:
strcat(buffer, " --nogoptime");
break;
}
}
/*Main tab and network settings*/
if (main_settings->port_or_files == PORT)
{
switch (main_settings->port_select)
{
case 0:
strcat(buffer, " -udp ");
if (!strstr(network_settings->udp_ipv4, "None"))
{
strncat(buffer, network_settings->udp_ipv4, network_settings->udp_ipv4_len);
strcat(buffer, ":");
}
strncat(buffer, main_settings->port_num, main_settings->port_num_len);
break;
case 1:
strcat(buffer, " -tcp ");
strncat(buffer, main_settings->port_num, main_settings->port_num_len);
if (!strstr(network_settings->tcp_pass, "None"))
{
strcat(buffer, " -tcppassword ");
strncat(buffer, network_settings->tcp_pass, network_settings->tcp_pass_len);
}
if (!strstr(network_settings->tcp_desc, "None"))
{
strcat(buffer, " -tcpdesc ");
strncat(buffer, network_settings->tcp_desc, network_settings->tcp_desc_len);
}
break;
default:
break;
}
if (input->is_live_stream)
{
strcat(buffer, " -s ");
strncat(buffer, input->wait_data_sec, input->wait_data_sec_len);
}
if (input->is_process_from)
{
strcat(buffer, " -startat ");
strcat(buffer, input->from_time_buffer);
}
if (input->is_process_until)
{
strcat(buffer, " -endat ");
strcat(buffer, input->until_time_buffer);
}
switch (input->elementary_stream)
{
case AUTO_DETECT:
break;
case STREAM_TYPE:
strcat(buffer, " -datastreamtype ");
strncat(buffer, input->stream_type, input->stream_type_len);
break;
case STREAM_PID:
strcat(buffer, " -datapid ");
strncat(buffer, input->stream_pid, input->stream_pid_len);
}
if (input->is_assume_mpeg)
{
strcat(buffer, " -streamtype ");
strncat(buffer, input->mpeg_type, input->mpeg_type_len);
}
switch (input->teletext_decoder)
{
case AUTO_DECODE:
break;
case FORCE:
strcat(buffer, " -teletext");
break;
case DISABLE:
strcat(buffer, " -noteletext");
}
if (input->is_process_teletext_page)
{
strcat(buffer, " -tpage ");
strncat(buffer, input->teletext_page_number, input->teletext_page_numer_len);
}
switch (input->is_limit)
{
case NO_LIMIT:
break;
case LIMITED:
strcat(buffer, " --screenfuls ");
strcat(buffer, input->screenful_limit_buffer);
}
switch (input->clock_input)
{
case AUTO:
break;
case GOP:
strcat(buffer, " --goptime");
break;
case PTS:
strcat(buffer, " --nogoptime");
break;
}
}
/*ADVANCED INPUT SETTINGS*/
if (advanced_input->is_multiple_program)
{
switch (advanced_input->multiple_program)
{
case FIRST_PROG:
strcat(buffer, " -autoprogram");
break;
case PROG_NUM:
strcat(buffer, " -pn ");
strcat(buffer, advanced_input->prog_number);
break;
}
}
switch (advanced_input->set_myth)
{
case AUTO_MYTH:
break;
case FORCE_MYTH:
strcat(buffer, " -myth");
break;
case DISABLE_MYTH:
strcat(buffer, " -nomyth");
break;
}
if (advanced_input->is_mpeg_90090)
strcat(buffer, " -90090");
if (advanced_input->is_padding_0000)
strcat(buffer, " -fp");
if (advanced_input->is_order_ccinfo)
strcat(buffer, " -poc");
if (advanced_input->is_win_bug)
strcat(buffer, " -wtvconvertfix");
if (advanced_input->is_hauppage_file)
strcat(buffer, " -haup");
if (advanced_input->is_process_mp4)
strcat(buffer, " -mp4vidtrack");
if (advanced_input->is_ignore_broadcast)
strcat(buffer, " -noautotimeref");
/*DECODERS TAB*/
if (decoders->is_field2)
strcat(buffer, " -12");
switch (decoders->channel)
{
case CHANNEL_1:
break;
case CHANNEL_2:
strcat(buffer, " -cc2");
break;
}
if (decoders->is_708)
{
strcat(buffer, " -svc ");
strncat(buffer, decoders->services, decoders->services_len);
}
switch (decoders->teletext_dvb)
{
case TELETEXT:
if (strcmp(decoders->min_distance, "2"))
{
strcat(buffer, " -levdistmincnt ");
strncat(buffer, decoders->min_distance, decoders->min_distance_len);
}
if (strcmp(decoders->max_distance, "10"))
{
strcat(buffer, " -levdistmaxpct ");
strncat(buffer, decoders->max_distance, decoders->max_distance_len);
}
break;
case DVB:
strcat(buffer, " -codec dvdsub");
break;
}
/*CREDITS TAB*/
if (credits->is_start_text)
{
strcat(buffer, " --startcreditstext \"");
strncat(buffer, credits->start_text, credits->start_text_len);
strcat(buffer, "\" --startcreditsforatleast ");
strncat(buffer, credits->start_atleast_sec, credits->start_atleast_sec_len);
strcat(buffer, " --startcreditsforatmost ");
strncat(buffer, credits->start_atmost_sec, credits->start_atmost_sec_len);
if (credits->is_before)
{
strcat(buffer, " --startcreditsnotbefore ");
strcat(buffer, credits->before_time_buffer);
}
if (credits->is_after)
{
strcat(buffer, " --startcreditsnotafter ");
strcat(buffer, credits->after_time_buffer);
}
}
if (credits->is_end_text)
{
strcat(buffer, " --endcreditstext \"");
strncat(buffer, credits->end_text, credits->end_text_len);
strcat(buffer, "\" --endcreditsforatleast ");
strncat(buffer, credits->end_atleast_sec, credits->end_atleast_sec_len);
strcat(buffer, " --endcreditsforatmost ");
strncat(buffer, credits->end_atmost_sec, credits->end_atmost_sec_len);
}
/*DEBUG TAB*/
if (debug->is_elementary_stream)
{
strcat(buffer, " -cf ");
strncat(buffer, debug->elementary_stream, debug->elementary_stream_len);
}
if (debug->is_dump_packets)
strcat(buffer, " -debug");
if (debug->is_debug_608)
strcat(buffer, " -608");
if (debug->is_debug_708)
strcat(buffer, " -708");
if (debug->is_stamp_output)
strcat(buffer, " -goppts");
if (debug->is_debug_analysed_vid)
strcat(buffer, " -vides");
if (debug->is_raw_608_708)
strcat(buffer, " -cbraw");
if (debug->is_debug_parsed)
strcat(buffer, " -parsedebug");
if (!strcmp(output->type[output->type_select], "bin"))
{
if (debug->is_disable_sync)
strcat(buffer, " -nosync");
if (debug->is_no_padding)
strcat(buffer, " -fullbin");
}
if (debug->is_debug_xds)
strcat(buffer, " -xdsdebug");
if (debug->is_output_pat)
strcat(buffer, " -parsePAT");
if (debug->is_output_pmt)
strcat(buffer, " -parsePMT");
if (debug->is_scan_ccdata)
strcat(buffer, " -investigate_packets");
if (debug->is_output_levenshtein)
strcat(buffer, " -deblev");
/*HARD_BURNED SUBS SETTINGS*/
if (burned_subs->is_burned_subs)
{
strcat(buffer, " -hardsubx -ocr_mode");
switch (burned_subs->ocr_mode)
{
case FRAME_WISE:
strcat(buffer, " frame");
break;
case WORD_WISE:
strcat(buffer, " word");
break;
case LETTER_WISE:
strcat(buffer, " letter");
break;
}
strcat(buffer, " -min_sub_duration ");
strcat(buffer, burned_subs->min_duration);
if (!burned_subs->subs_color_select && burned_subs->color_type == PRESET)
sprintf(buffer, "%s -whiteness_thresh %d", buffer, burned_subs->luminance_threshold);
sprintf(buffer, "%s -conf_thresh %d", buffer, burned_subs->confidence_threshold);
if (burned_subs->is_italic)
strcat(buffer, " -detect_italics");
}
//Output
{
strcat(buffer, " -out=");
strcat(buffer, output->type[output->type_select]);
if (output->is_filename)
{
strcat(buffer, " -o \"");
strncat(buffer, output->filename, output->filename_len);
strcat(buffer, "\"");
}
if (output->is_delay)
{
strcat(buffer, " -delay ");
strcat(buffer, output->delay_sec_buffer);
}
if (output->is_export_xds)
strcat(buffer, " -xds");
switch (output->encoding)
{
case LATIN:
strcat(buffer, " -latin1");
break;
case UNIC:
strcat(buffer, " -unicode");
break;
case UTF:
strcat(buffer, " -utf8");
break;
}
if (output->is_bom)
strcat(buffer, " -bom");
else
strcat(buffer, " -nobom");
if (output->is_cap_standard)
strcat(buffer, " --sentencecap");
if (output->is_cap_file)
{
strcat(buffer, " --capfile \"");
strncat(buffer, output->cap_dictionary, output->cap_dictionary_len);
strcat(buffer, "\"");
}
switch (output->line_ending)
{
case CRLF:
break;
case LF:
strcat(buffer, " -lf");
break;
}
if (output->is_center)
strcat(buffer, " -trim");
if (output->is_dash)
strcat(buffer, " -autodash");
if (output->no_typesetting)
strcat(buffer, " --notypesetting");
switch (output->font_color)
{
case NO_COLOR:
strcat(buffer, " --nofontcolor");
break;
case DEFAULT_COLOR:
strcat(buffer, " --defaultcolor #");
strcat(buffer, output->color_hex);
break;
}
switch (output->onetime_or_realtime)
{
case ONETIME:
strcat(buffer, " --norollup");
break;
case REALTIME:
strcat(buffer, " -dru");
switch (output->roll_limit_select)
{
case 1:
strcat(buffer, " -ru1");
break;
case 2:
strcat(buffer, " -ru2");
break;
case 3:
strcat(buffer, " -ru3");
break;
default:
break;
}
}
}
memset(command->term_string, 0, sizeof(command->term_string));
strncpy(command->term_string, buffer, strlen(buffer));
}

View File

@@ -1,24 +0,0 @@
#ifndef COMMAND_BUILDER_H
#define COMMAND_BUILDER_H
#include "ccextractorGUI.h"
#include "tabs.h"
#include "popups.h"
struct built_string
{
char term_string[1000];
};
void command_builder(struct built_string *command,
struct main_tab *main_settings,
struct network_popup *network_settings,
struct input_tab *input,
struct advanced_input_tab *advanced_input,
struct output_tab *output,
struct decoders_tab *decoders,
struct credits_tab *credits,
struct debug_tab *debug,
struct burned_subs_tab *burned_subs);
#endif //!COMMAND_BUILDER_H

View File

@@ -1,598 +0,0 @@
#include "file_browser.h"
#ifdef _WIN32
#include "win_dirent.h"
#else
#include <dirent.h>
#endif
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdarg.h>
#ifndef STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#endif
#if UNIX
#include <unistd.h>
#endif
#include <GL/glew.h>
#include <string.h>
#ifndef NK_IMPLEMENTATION
#include "nuklear_lib/nuklear.h"
#endif
#include "ccextractorGUI.h"
#include "tabs.h"
void die(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
fputs("\n", stderr);
exit(EXIT_FAILURE);
}
char *
file_load(const char *path, size_t *siz)
{
char *buf;
FILE *fd = fopen(path, "rb");
if (!fd)
die("Failed to open file: %s\n", path);
fseek(fd, 0, SEEK_END);
*siz = (size_t)ftell(fd);
fseek(fd, 0, SEEK_SET);
buf = (char *)calloc(*siz, 1);
fread(buf, *siz, 1, fd);
fclose(fd);
return buf;
}
char *
str_duplicate(const char *src)
{
char *ret;
size_t len = strlen(src);
if (!len)
return 0;
ret = (char *)malloc(len + 1);
if (!ret)
return 0;
memcpy(ret, src, len);
ret[len] = '\0';
return ret;
}
void dir_free_list(char **list, size_t size)
{
size_t i;
for (i = 0; i < size; ++i)
free(list[i]);
free(list);
}
char **
dir_list(const char *dir, int return_subdirs, size_t *count)
{
size_t n = 0;
char buffer[MAX_PATH_LEN];
char **results = NULL;
const DIR *none = NULL;
size_t capacity = 32;
size_t size;
DIR *z;
assert(dir);
assert(count);
strncpy(buffer, dir, MAX_PATH_LEN);
n = strlen(buffer);
#ifdef _WIN32
if (n > 0 && (buffer[n - 1] != '\\'))
buffer[n++] = '\\';
#else
if (n > 0 && (buffer[n - 1] != '/'))
buffer[n++] = '/';
#endif
size = 0;
z = opendir(dir);
if (z != none)
{
int nonempty = 1;
struct dirent *data = readdir(z);
nonempty = (data != NULL);
if (!nonempty)
return NULL;
do
{
DIR *y;
char *p;
int is_subdir;
if (data->d_name[0] == '.')
continue;
strncpy(buffer + n, data->d_name, MAX_PATH_LEN - n);
y = opendir(buffer);
is_subdir = (y != NULL);
if (y != NULL)
closedir(y);
if ((return_subdirs && is_subdir) || (!is_subdir && !return_subdirs))
{
if (!size)
{
results = (char **)calloc(sizeof(char *), capacity);
}
else if (size >= capacity)
{
void *old = results;
capacity = capacity * 2;
results = (char **)realloc(results, capacity * sizeof(char *));
assert(results);
if (!results)
free(old);
}
p = str_duplicate(data->d_name);
results[size++] = p;
}
} while ((data = readdir(z)) != NULL);
}
if (z)
closedir(z);
*count = size;
return results;
}
struct file_group
FILE_GROUP(enum file_groups group, const char *name, struct nk_image *icon)
{
struct file_group fg;
fg.group = group;
fg.name = name;
fg.icon = icon;
return fg;
}
struct file
FILE_DEF(enum file_types type, const char *suffix, enum file_groups group)
{
struct file fd;
fd.type = type;
fd.suffix = suffix;
fd.group = group;
return fd;
}
struct nk_image *
media_icon_for_file(struct media *media, const char *file)
{
int i = 0;
const char *s = file;
char suffix[4];
int found = 0;
memset(suffix, 0, sizeof(suffix));
/* extract suffix .xxx from file */
while (*s++ != '\0')
{
if (found && i < 3)
suffix[i++] = *s;
if (*s == '.')
{
if (found)
{
found = 0;
break;
}
found = 1;
}
}
/* check for all file definition of all groups for fitting suffix*/
for (i = 0; i < FILE_MAX && found; ++i)
{
struct file *d = &media->files[i];
{
const char *f = d->suffix;
s = suffix;
while (f && *f && *s && *s == *f)
{
s++;
f++;
}
/* found correct file definition so */
if (f && *s == '\0' && *f == '\0')
return media->group[d->group].icon;
}
}
return &media->icons.default_file;
}
void media_init(struct media *media)
{
/* file groups */
struct icons *icons = &media->icons;
media->group[FILE_GROUP_DEFAULT] = FILE_GROUP(FILE_GROUP_DEFAULT, "default", &icons->default_file);
media->group[FILE_GROUP_TEXT] = FILE_GROUP(FILE_GROUP_TEXT, "textual", &icons->text_file);
media->group[FILE_GROUP_MUSIC] = FILE_GROUP(FILE_GROUP_MUSIC, "music", &icons->music_file);
media->group[FILE_GROUP_FONT] = FILE_GROUP(FILE_GROUP_FONT, "font", &icons->font_file);
media->group[FILE_GROUP_IMAGE] = FILE_GROUP(FILE_GROUP_IMAGE, "image", &icons->img_file);
media->group[FILE_GROUP_MOVIE] = FILE_GROUP(FILE_GROUP_MOVIE, "movie", &icons->movie_file);
/* files */
media->files[FILE_DEFAULT] = FILE_DEF(FILE_DEFAULT, NULL, FILE_GROUP_DEFAULT);
media->files[FILE_TEXT] = FILE_DEF(FILE_TEXT, "txt", FILE_GROUP_TEXT);
media->files[FILE_C_SOURCE] = FILE_DEF(FILE_C_SOURCE, "c", FILE_GROUP_TEXT);
media->files[FILE_CPP_SOURCE] = FILE_DEF(FILE_CPP_SOURCE, "cpp", FILE_GROUP_TEXT);
media->files[FILE_HEADER] = FILE_DEF(FILE_HEADER, "h", FILE_GROUP_TEXT);
media->files[FILE_CPP_HEADER] = FILE_DEF(FILE_HEADER, "hpp", FILE_GROUP_TEXT);
media->files[FILE_MP3] = FILE_DEF(FILE_MP3, "mp3", FILE_GROUP_MUSIC);
media->files[FILE_WAV] = FILE_DEF(FILE_WAV, "wav", FILE_GROUP_MUSIC);
media->files[FILE_OGG] = FILE_DEF(FILE_OGG, "ogg", FILE_GROUP_MUSIC);
media->files[FILE_TTF] = FILE_DEF(FILE_TTF, "ttf", FILE_GROUP_FONT);
media->files[FILE_BMP] = FILE_DEF(FILE_BMP, "bmp", FILE_GROUP_IMAGE);
media->files[FILE_PNG] = FILE_DEF(FILE_PNG, "png", FILE_GROUP_IMAGE);
media->files[FILE_JPEG] = FILE_DEF(FILE_JPEG, "jpg", FILE_GROUP_IMAGE);
media->files[FILE_PCX] = FILE_DEF(FILE_PCX, "pcx", FILE_GROUP_IMAGE);
media->files[FILE_TGA] = FILE_DEF(FILE_TGA, "tga", FILE_GROUP_IMAGE);
media->files[FILE_GIF] = FILE_DEF(FILE_GIF, "gif", FILE_GROUP_IMAGE);
}
void file_browser_reload_directory_content(struct file_browser *browser, const char *path)
{
strncpy(browser->directory, path, MAX_PATH_LEN);
dir_free_list(browser->files, browser->file_count);
dir_free_list(browser->directories, browser->dir_count);
browser->files = dir_list(path, 0, &browser->file_count);
browser->directories = dir_list(path, 1, &browser->dir_count);
}
#ifdef _WIN32
void get_drives(struct file_browser *browser)
{
static int drive_num;
static char drive_list[50][4];
int c, prev_char;
system("wmic logicaldisk get name 1> drive.txt");
FILE *file;
file = fopen("drive.txt", "r");
if (file == NULL)
{
printf("cannot find any drives! try again with different settings/permissions");
}
else
{
puts("File opened");
while ((c = getc(file)) != EOF)
{
if (c == ':')
{
sprintf(drive_list[drive_num], "%c", prev_char);
drive_num++;
continue;
}
if (c < 65 || c > 90)
continue;
prev_char = c;
}
}
printf("drive nums:%d\n", drive_num);
for (int i = 0; i < drive_num; i++)
strcat(drive_list[i], ":\\");
browser->drives_num = drive_num;
browser->drives = (char **)calloc(drive_num + 1, sizeof(char *));
for (int i = 0; i < drive_num; i++)
{
browser->drives[i] = (char *)calloc(strlen(drive_list[i]), sizeof(char));
browser->drives[i] = strdup(drive_list[i]);
}
browser->drives[browser->drives_num] = NULL;
for (int i = 0; i < drive_num; i++)
puts(browser->drives[i]);
fclose(file);
remove("drive.txt");
}
#endif
void file_browser_init(struct file_browser *browser, struct media *media)
{
memset(browser, 0, sizeof(*browser));
browser->media = media;
#ifdef _WIN32
get_drives(browser);
#endif
{
/* load files and sub-directory list */
const char *home = getenv("HOME");
#ifdef _WIN32
if (!home)
home = getenv("USERPROFILE");
#else
if (!home)
home = getpwuid(getuid());
#endif
{
size_t l;
strncpy(browser->home, home, MAX_PATH_LEN);
l = strlen(browser->home);
#ifdef _WIN32
strcpy(browser->home + l, "\\");
#else
strcpy(browser->home + l, "/");
#endif
strcpy(browser->directory, browser->home);
}
{
size_t l;
strcpy(browser->desktop, browser->home);
l = strlen(browser->desktop);
#ifdef _WIN32
strcpy(browser->desktop + l, "Desktop\\");
#else
strcpy(browser->desktop + l, "Desktop/");
#endif
}
browser->files = dir_list(browser->directory, 0, &browser->file_count);
browser->directories = dir_list(browser->directory, 1, &browser->dir_count);
}
}
void file_browser_free(struct file_browser *browser)
{
if (browser->files)
dir_free_list(browser->files, browser->file_count);
if (browser->directories)
dir_free_list(browser->directories, browser->dir_count);
browser->files = NULL;
browser->directories = NULL;
memset(browser, 0, sizeof(*browser));
}
int file_browser_run(struct file_browser *browser,
struct nk_context *ctx,
struct main_tab *main_settings,
struct output_tab *output,
struct debug_tab *debug,
struct hd_homerun_tab *hd_homerun)
{
static int isFileAdded = nk_false;
int ret = 0;
struct media *media = browser->media;
struct nk_rect total_space;
if (nk_popup_begin(ctx, NK_POPUP_STATIC, "File Browser", NK_WINDOW_CLOSABLE | NK_WINDOW_BORDER | NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_MOVABLE,
nk_rect(0, 0, 930, 650)))
{
static float ratio[] = {0.25f, NK_UNDEFINED};
float spacing_x = ctx->style.window.spacing.x;
/* output path directory selector in the menubar */
ctx->style.window.spacing.x = 0;
nk_menubar_begin(ctx);
{
char *d = browser->directory;
char *begin = d + 1;
nk_layout_row_dynamic(ctx, 25, 6);
while (*d++)
{
#ifdef _WIN32
if (*d == '\\')
#else
if (*d == '/')
#endif
{
*d = '\0';
if (nk_button_label(ctx, begin))
{
#ifdef _WIN32
*d++ = '\\';
#else
*d++ = '/';
#endif
*d = '\0';
file_browser_reload_directory_content(browser, browser->directory);
break;
}
#ifdef _WIN32
*d = '\\';
#else
*d = '/';
#endif
begin = d + 1;
}
}
}
nk_menubar_end(ctx);
ctx->style.window.spacing.x = spacing_x;
/* window layout */
total_space = nk_window_get_content_region(ctx);
nk_layout_row(ctx, NK_DYNAMIC, total_space.h, 2, ratio);
nk_group_begin(ctx, "Special", NK_WINDOW_NO_SCROLLBAR);
{
struct nk_image home = media->icons.home;
struct nk_image desktop = media->icons.desktop;
struct nk_image computer = media->icons.computer;
#ifdef _WIN32
struct nk_image drive = media->icons.drives;
#endif
nk_layout_row_dynamic(ctx, 40, 1);
if (nk_button_image_label(ctx, home, "Home", NK_TEXT_CENTERED))
file_browser_reload_directory_content(browser, browser->home);
if (nk_button_image_label(ctx, desktop, "Desktop", NK_TEXT_CENTERED))
file_browser_reload_directory_content(browser, browser->desktop);
#ifdef _WIN32
for (int drive_counter = 0; drive_counter < browser->drives_num; drive_counter++)
{
if (nk_button_image_label(ctx, drive, browser->drives[drive_counter], NK_TEXT_CENTERED))
file_browser_reload_directory_content(browser, browser->drives[drive_counter]);
}
#else
if (nk_button_image_label(ctx, computer, "Computer", NK_TEXT_CENTERED))
file_browser_reload_directory_content(browser, "/");
#endif
nk_group_end(ctx);
}
/* output directory content window */
nk_group_begin(ctx, "Content", 0);
{
int index = -1;
size_t i = 0, j = 0, k = 0;
size_t rows = 0, cols = 0;
size_t count = browser->dir_count + browser->file_count;
cols = 4;
rows = count / cols;
for (i = 0; i <= rows; i += 1)
{
{
size_t n = j + cols;
nk_layout_row_dynamic(ctx, 135, (int)cols);
for (; j < count && j < n; ++j)
{
/* draw one row of icons */
if (j < browser->dir_count)
{
/* draw and execute directory buttons */
if (nk_button_image(ctx, media->icons.directory))
index = (int)j;
}
else
{
/* draw and execute files buttons */
struct nk_image *icon;
size_t fileIndex = ((size_t)j - browser->dir_count);
icon = media_icon_for_file(media, browser->files[fileIndex]);
if (nk_button_image(ctx, *icon))
{
strncpy(browser->file, browser->directory, MAX_PATH_LEN);
n = strlen(browser->file);
strncpy(browser->file + n, browser->files[fileIndex], MAX_PATH_LEN - n);
ret = 1;
if (hd_homerun->is_homerun_browser_active)
{
hd_homerun->location_len = strlen(browser->file);
strncpy(hd_homerun->location, browser->file, hd_homerun->location_len);
isFileAdded = nk_true;
hd_homerun->is_homerun_browser_active = nk_false;
break;
}
if (debug->is_debug_browser_active)
{
debug->elementary_stream_len = strlen(browser->file);
strcpy(debug->elementary_stream, browser->file);
isFileAdded = nk_true;
debug->is_debug_browser_active = nk_false;
break;
}
if (output->is_output_browser_active)
{
output->filename_len = strlen(browser->file);
strcpy(output->filename, browser->file);
isFileAdded = nk_true;
output->is_output_browser_active = nk_false;
break;
}
if (output->is_cap_browser_active)
{
output->cap_dictionary_len = strlen(browser->file);
strcpy(output->cap_dictionary, browser->file);
isFileAdded = nk_true;
output->is_cap_browser_active = nk_false;
break;
}
if (main_settings->is_file_browser_active)
{
if (main_settings->filename_count == 0)
main_settings->filenames = (char **)calloc(2, sizeof(char *));
else
main_settings->filenames = (char **)realloc(main_settings->filenames, (main_settings->filename_count + 2) * sizeof(char *));
main_settings->filenames[main_settings->filename_count] = (char *)calloc((strlen(browser->file) + 5), sizeof(char));
main_settings->filenames[main_settings->filename_count][0] = '\"';
strcat(main_settings->filenames[main_settings->filename_count], browser->file);
strcat(main_settings->filenames[main_settings->filename_count], "\"");
main_settings->filename_count++;
main_settings->filenames[main_settings->filename_count] = NULL;
isFileAdded = nk_true;
main_settings->is_file_browser_active = nk_false;
break;
}
}
}
}
}
{
size_t n = k + cols;
nk_layout_row_dynamic(ctx, 20, (int)cols);
for (; k < count && k < n; k++)
{
/* draw one row of labels */
if (k < browser->dir_count)
{
nk_label(ctx, browser->directories[k], NK_TEXT_CENTERED);
}
else
{
size_t t = k - browser->dir_count;
nk_label(ctx, browser->files[t], NK_TEXT_CENTERED);
}
}
}
}
if (index != -1)
{
size_t n = strlen(browser->directory);
strncpy(browser->directory + n, browser->directories[index], MAX_PATH_LEN - n);
n = strlen(browser->directory);
if (n < MAX_PATH_LEN - 1)
{
#ifdef _WIN32
browser->directory[n] = '\\';
#else
browser->directory[n] = '/';
#endif
browser->directory[n + 1] = '\0';
}
file_browser_reload_directory_content(browser, browser->directory);
}
nk_group_end(ctx);
}
if (isFileAdded)
{
isFileAdded = nk_false;
main_settings->scaleWindowForFileBrowser = nk_false;
nk_popup_close(ctx);
}
nk_popup_end(ctx);
return ret;
}
else
{
main_settings->scaleWindowForFileBrowser = nk_false;
return 0;
}
}

View File

@@ -1,159 +0,0 @@
#ifndef FILE_BROWSER_H
#define FILE_BROWSER_H
#include "ccextractorGUI.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#ifndef STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#endif
#include "tabs.h"
/* ===============================================================
*
* GUI
*
* ===============================================================*/
struct icons {
struct nk_image desktop;
#ifdef _WIN32
struct nk_image drives;
#endif
struct nk_image home;
struct nk_image computer;
struct nk_image directory;
struct nk_image default_file;
struct nk_image text_file;
struct nk_image music_file;
struct nk_image font_file;
struct nk_image img_file;
struct nk_image movie_file;
};
enum file_groups {
FILE_GROUP_DEFAULT,
FILE_GROUP_TEXT,
FILE_GROUP_MUSIC,
FILE_GROUP_FONT,
FILE_GROUP_IMAGE,
FILE_GROUP_MOVIE,
FILE_GROUP_MAX
};
enum file_types {
FILE_DEFAULT,
FILE_TEXT,
FILE_C_SOURCE,
FILE_CPP_SOURCE,
FILE_HEADER,
FILE_CPP_HEADER,
FILE_MP3,
FILE_WAV,
FILE_OGG,
FILE_TTF,
FILE_BMP,
FILE_PNG,
FILE_JPEG,
FILE_PCX,
FILE_TGA,
FILE_GIF,
FILE_MAX
};
struct file_group {
enum file_groups group;
const char *name;
struct nk_image *icon;
};
struct file {
enum file_types type;
const char *suffix;
enum file_groups group;
};
struct media {
int font;
int icon_sheet;
struct icons icons;
struct file_group group[FILE_GROUP_MAX];
struct file files[FILE_MAX];
};
#define MAX_PATH_LEN 512
struct file_browser {
/* path */
char file[MAX_PATH_LEN];
char home[MAX_PATH_LEN];
char desktop[MAX_PATH_LEN];
char directory[MAX_PATH_LEN];
#ifdef _WIN32
char **drives;
int drives_num;
#endif
/* directory content */
char **files;
char **directories;
size_t file_count;
size_t dir_count;
struct media *media;
};
void
die(const char *fmt, ...);
char*
file_load(const char* path, size_t* siz);
char*
str_duplicate(const char *src);
void
dir_free_list(char **list, size_t size);
char**
dir_list(const char *dir, int return_subdirs, size_t *count);
struct file_group
FILE_GROUP(enum file_groups group, const char *name, struct nk_image *icon);
struct file
FILE_DEF(enum file_types type, const char *suffix, enum file_groups group);
struct nk_image*
media_icon_for_file(struct media *media, const char *file);
void
media_init(struct media *media);
void
file_browser_reload_directory_content(struct file_browser *browser, const char *path);
#if _WIN32
void
get_drives(struct file_browser *browser);
#endif
void
file_browser_init(struct file_browser *browser, struct media *media);
void
file_browser_free(struct file_browser *browser);
int
file_browser_run(struct file_browser *browser,
struct nk_context *ctx,
struct main_tab *main_settings,
struct output_tab *output,
struct debug_tab *debug,
struct hd_homerun_tab *hd_homerun);
struct nk_image
icon_load(char icon_data[], int len);
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,352 +0,0 @@
/*
* Nuklear - v1.32.0 - public domain
* no warrenty implied; use at your own risk.
* authored from 2015-2017 by Micha Mettke
*/
/*
* ==============================================================
*
* API
*
* ===============================================================
*/
#ifndef NK_GLFW_GL2_H_
#define NK_GLFW_GL2_H_
#include <GLFW/glfw3.h>
enum nk_glfw_init_state{
NK_GLFW3_DEFAULT = 0,
NK_GLFW3_INSTALL_CALLBACKS
};
NK_API struct nk_context* nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state);
NK_API void nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas);
NK_API void nk_glfw3_font_stash_end(void);
NK_API void nk_glfw3_new_frame(void);
NK_API void nk_glfw3_render(enum nk_anti_aliasing);
NK_API void nk_glfw3_shutdown(void);
NK_API void nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint);
NK_API void nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff);
#endif
/*
* ==============================================================
*
* IMPLEMENTATION
*
* ===============================================================
*/
#ifdef NK_GLFW_GL2_IMPLEMENTATION
#ifndef NK_GLFW_TEXT_MAX
#define NK_GLFW_TEXT_MAX 256
#endif
struct nk_glfw_device {
struct nk_buffer cmds;
struct nk_draw_null_texture null;
GLuint font_tex;
GLint uniform_tex;
GLint uniform_proj;
};
struct nk_glfw_vertex {
float position[2];
float uv[2];
nk_byte col[4];
};
static struct nk_glfw {
GLFWwindow *win;
int width, height;
int display_width, display_height;
struct nk_glfw_device ogl;
struct nk_context ctx;
struct nk_font_atlas atlas;
struct nk_vec2 fb_scale;
unsigned int text[NK_GLFW_TEXT_MAX];
int text_len;
float scroll;
} glfw;
NK_INTERN void
nk_glfw3_device_upload_atlas(const void *image, int width, int height)
{
struct nk_glfw_device *dev = &glfw.ogl;
glGenTextures(1, &dev->font_tex);
glBindTexture(GL_TEXTURE_2D, dev->font_tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, image);
}
NK_API void
nk_glfw3_render(enum nk_anti_aliasing AA)
{
/* setup global state */
struct nk_glfw_device *dev = &glfw.ogl;
glPushAttrib(GL_ENABLE_BIT|GL_COLOR_BUFFER_BIT|GL_TRANSFORM_BIT);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glEnable(GL_SCISSOR_TEST);
glEnable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
/* setup viewport/project */
glViewport(0,0,(GLsizei)glfw.display_width,(GLsizei)glfw.display_height);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0.0f, glfw.width, glfw.height, 0.0f, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
{
GLsizei vs = sizeof(struct nk_glfw_vertex);
size_t vp = offsetof(struct nk_glfw_vertex, position);
size_t vt = offsetof(struct nk_glfw_vertex, uv);
size_t vc = offsetof(struct nk_glfw_vertex, col);
/* convert from command queue into draw list and draw to screen */
const struct nk_draw_command *cmd;
const nk_draw_index *offset = NULL;
struct nk_buffer vbuf, ebuf;
/* fill convert configuration */
struct nk_convert_config config;
static const struct nk_draw_vertex_layout_element vertex_layout[] = {
{NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, position)},
{NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, uv)},
{NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_glfw_vertex, col)},
{NK_VERTEX_LAYOUT_END}
};
NK_MEMSET(&config, 0, sizeof(config));
config.vertex_layout = vertex_layout;
config.vertex_size = sizeof(struct nk_glfw_vertex);
config.vertex_alignment = NK_ALIGNOF(struct nk_glfw_vertex);
config.null = dev->null;
config.circle_segment_count = 22;
config.curve_segment_count = 22;
config.arc_segment_count = 22;
config.global_alpha = 1.0f;
config.shape_AA = AA;
config.line_AA = AA;
/* convert shapes into vertexes */
nk_buffer_init_default(&vbuf);
nk_buffer_init_default(&ebuf);
nk_convert(&glfw.ctx, &dev->cmds, &vbuf, &ebuf, &config);
/* setup vertex buffer pointer */
{const void *vertices = nk_buffer_memory_const(&vbuf);
glVertexPointer(2, GL_FLOAT, vs, (const void*)((const nk_byte*)vertices + vp));
glTexCoordPointer(2, GL_FLOAT, vs, (const void*)((const nk_byte*)vertices + vt));
glColorPointer(4, GL_UNSIGNED_BYTE, vs, (const void*)((const nk_byte*)vertices + vc));}
/* iterate over and execute each draw command */
offset = (const nk_draw_index*)nk_buffer_memory_const(&ebuf);
nk_draw_foreach(cmd, &glfw.ctx, &dev->cmds)
{
if (!cmd->elem_count) continue;
glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
glScissor(
(GLint)(cmd->clip_rect.x * glfw.fb_scale.x),
(GLint)((glfw.height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * glfw.fb_scale.y),
(GLint)(cmd->clip_rect.w * glfw.fb_scale.x),
(GLint)(cmd->clip_rect.h * glfw.fb_scale.y));
glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
offset += cmd->elem_count;
}
nk_clear(&glfw.ctx);
nk_buffer_free(&vbuf);
nk_buffer_free(&ebuf);
}
/* default OpenGL state */
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
}
NK_API void
nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint)
{
(void)win;
if (glfw.text_len < NK_GLFW_TEXT_MAX)
glfw.text[glfw.text_len++] = codepoint;
}
NK_API void
nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff)
{
(void)win; (void)xoff;
glfw.scroll += (float)yoff;
}
NK_INTERN void
nk_glfw3_clipbard_paste(nk_handle usr, struct nk_text_edit *edit)
{
const char *text = glfwGetClipboardString(glfw.win);
if (text) nk_textedit_paste(edit, text, nk_strlen(text));
(void)usr;
}
NK_INTERN void
nk_glfw3_clipbard_copy(nk_handle usr, const char *text, int len)
{
char *str = 0;
(void)usr;
if (!len) return;
str = (char*)malloc((size_t)len+1);
if (!str) return;
memcpy(str, text, (size_t)len);
str[len] = '\0';
glfwSetClipboardString(glfw.win, str);
free(str);
}
NK_API struct nk_context*
nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state init_state)
{
glfw.win = win;
if (init_state == NK_GLFW3_INSTALL_CALLBACKS) {
glfwSetScrollCallback(win, nk_gflw3_scroll_callback);
glfwSetCharCallback(win, nk_glfw3_char_callback);
}
nk_init_default(&glfw.ctx, 0);
glfw.ctx.clip.copy = nk_glfw3_clipbard_copy;
glfw.ctx.clip.paste = nk_glfw3_clipbard_paste;
glfw.ctx.clip.userdata = nk_handle_ptr(0);
nk_buffer_init_default(&glfw.ogl.cmds);
return &glfw.ctx;
}
NK_API void
nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas)
{
nk_font_atlas_init_default(&glfw.atlas);
nk_font_atlas_begin(&glfw.atlas);
*atlas = &glfw.atlas;
}
NK_API void
nk_glfw3_font_stash_end(void)
{
const void *image; int w, h;
image = nk_font_atlas_bake(&glfw.atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
nk_glfw3_device_upload_atlas(image, w, h);
nk_font_atlas_end(&glfw.atlas, nk_handle_id((int)glfw.ogl.font_tex), &glfw.ogl.null);
if (glfw.atlas.default_font)
nk_style_set_font(&glfw.ctx, &glfw.atlas.default_font->handle);
}
NK_API void
nk_glfw3_new_frame(void)
{
int i;
double x, y;
struct nk_context *ctx = &glfw.ctx;
struct GLFWwindow *win = glfw.win;
glfwGetWindowSize(win, &glfw.width, &glfw.height);
glfwGetFramebufferSize(win, &glfw.display_width, &glfw.display_height);
glfw.fb_scale.x = (float)glfw.display_width/(float)glfw.width;
glfw.fb_scale.y = (float)glfw.display_height/(float)glfw.height;
nk_input_begin(ctx);
for (i = 0; i < glfw.text_len; ++i)
nk_input_unicode(ctx, glfw.text[i]);
/* optional grabbing behavior */
if (ctx->input.mouse.grab)
glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
else if (ctx->input.mouse.ungrab)
glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
nk_input_key(ctx, NK_KEY_DEL, glfwGetKey(win, GLFW_KEY_DELETE) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_ENTER, glfwGetKey(win, GLFW_KEY_ENTER) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TAB, glfwGetKey(win, GLFW_KEY_TAB) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_BACKSPACE, glfwGetKey(win, GLFW_KEY_BACKSPACE) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_UP, glfwGetKey(win, GLFW_KEY_UP) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_DOWN, glfwGetKey(win, GLFW_KEY_DOWN) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_SCROLL_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_SCROLL_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_SCROLL_DOWN, glfwGetKey(win, GLFW_KEY_PAGE_DOWN) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_SCROLL_UP, glfwGetKey(win, GLFW_KEY_PAGE_UP) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_SHIFT, glfwGetKey(win, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS||
glfwGetKey(win, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS);
if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS ||
glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS) {
nk_input_key(ctx, NK_KEY_COPY, glfwGetKey(win, GLFW_KEY_C) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_PASTE, glfwGetKey(win, GLFW_KEY_V) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_X) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_UNDO, glfwGetKey(win, GLFW_KEY_Z) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_REDO, glfwGetKey(win, GLFW_KEY_R) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_LINE_START, glfwGetKey(win, GLFW_KEY_B) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_LINE_END, glfwGetKey(win, GLFW_KEY_E) == GLFW_PRESS);
} else {
nk_input_key(ctx, NK_KEY_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_COPY, 0);
nk_input_key(ctx, NK_KEY_PASTE, 0);
nk_input_key(ctx, NK_KEY_CUT, 0);
nk_input_key(ctx, NK_KEY_SHIFT, 0);
}
glfwGetCursorPos(win, &x, &y);
nk_input_motion(ctx, (int)x, (int)y);
if (ctx->input.mouse.grabbed) {
glfwSetCursorPos(glfw.win, ctx->input.mouse.prev.x, ctx->input.mouse.prev.y);
ctx->input.mouse.pos.x = ctx->input.mouse.prev.x;
ctx->input.mouse.pos.y = ctx->input.mouse.prev.y;
}
nk_input_button(ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS);
nk_input_button(ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS);
nk_input_button(ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS);
nk_input_scroll(ctx, glfw.scroll);
nk_input_end(&glfw.ctx);
glfw.text_len = 0;
glfw.scroll = 0;
}
NK_API
void nk_glfw3_shutdown(void)
{
struct nk_glfw_device *dev = &glfw.ogl;
nk_font_atlas_clear(&glfw.atlas);
nk_free(&glfw.ctx);
glDeleteTextures(1, &dev->font_tex);
nk_buffer_free(&dev->cmds);
memset(&glfw, 0, sizeof(glfw));
}
#endif

View File

@@ -1,313 +0,0 @@
#ifndef NK_IMPLEMENTATION
#include "nuklear_lib/nuklear.h"
#include <stdio.h>
#include <string.h>
#endif // !NK_IMPLEMENTATION
#include "tabs.h"
#include "popups.h"
void setup_network_settings(struct network_popup *network_settings)
{
network_settings->show_network_settings = nk_false;
network_settings->save_network_settings = nk_false;
strcpy(network_settings->udp_ipv4, "None");
network_settings->udp_ipv4_len = strlen(network_settings->udp_ipv4);
strcpy(network_settings->tcp_pass, "None");
network_settings->tcp_pass_len = strlen(network_settings->tcp_pass);
strcpy(network_settings->tcp_desc, "None");
network_settings->tcp_desc_len = strlen(network_settings->tcp_desc);
strcpy(network_settings->send_port, "None");
network_settings->send_port_len = strlen(network_settings->send_port);
strcpy(network_settings->send_host, "None");
network_settings->send_host_len = strlen(network_settings->send_host);
}
void draw_network_popup(struct nk_context *ctx, struct network_popup *network_settings)
{
const float save_ok_ratio[] = {0.8f, 0.1f, 0.1f};
const float udp_tcp_ratio[] = {0.45f, 0.1f, 0.45f};
static char udp_ipv4_buffer[30];
static int udp_ipv4_len[30];
static char tcp_pass_buf[30];
static int tcp_pass_len[30];
static char tcp_desc_buf[30];
static int tcp_desc_len[30];
static char send_port_buf[30];
static int send_port_len[30];
static char send_host_buf[30];
static int send_host_len[30];
const char network_attr[][30] = {"-udp port:", "-udp [host:]port:", "-sendto host[:port]:", "-tcp port:", "-tcppassword password:", "-tcpdesc description:"};
static struct nk_rect s = {20, 30, 480, 500};
if (nk_popup_begin(ctx, NK_POPUP_STATIC, "Network Settings", NK_WINDOW_CLOSABLE | NK_WINDOW_NO_SCROLLBAR, s))
{
nk_layout_row_dynamic(ctx, 220, 1);
if (nk_group_begin(ctx, "Receive", NK_WINDOW_TITLE))
{
nk_layout_row(ctx, NK_DYNAMIC, 21, 3, udp_tcp_ratio);
nk_spacing(ctx, 1);
nk_label(ctx, "UDP:", NK_TEXT_CENTERED);
nk_layout_row_static(ctx, 20, 200, 2);
nk_label(ctx, "Hostname/IPv4 Address:", NK_TEXT_LEFT);
nk_edit_string(ctx, NK_EDIT_SIMPLE, network_settings->udp_ipv4, &network_settings->udp_ipv4_len, 50, nk_filter_default);
nk_layout_row(ctx, NK_DYNAMIC, 21, 3, udp_tcp_ratio);
nk_spacing(ctx, 1);
nk_label(ctx, "TCP:", NK_TEXT_CENTERED);
nk_layout_row_static(ctx, 20, 200, 2);
nk_label(ctx, "Password:", NK_TEXT_LEFT);
nk_edit_string(ctx, NK_EDIT_SIMPLE, network_settings->tcp_pass, &network_settings->tcp_pass_len, 25, nk_filter_default);
nk_layout_row_static(ctx, 20, 200, 2);
nk_label(ctx, "Description:", NK_TEXT_LEFT);
nk_edit_string(ctx, NK_EDIT_SIMPLE, network_settings->tcp_desc, &network_settings->tcp_desc_len, 25, nk_filter_default);
nk_group_end(ctx);
}
nk_layout_row_dynamic(ctx, 200, 1);
if (nk_group_begin(ctx, "Send", NK_WINDOW_TITLE))
{
nk_layout_row(ctx, NK_DYNAMIC, 21, 3, udp_tcp_ratio);
nk_spacing(ctx, 1);
nk_label(ctx, "Send to:", NK_TEXT_CENTERED);
nk_layout_row_static(ctx, 20, 200, 2);
nk_label(ctx, "Port:", NK_TEXT_LEFT);
nk_edit_string(ctx, NK_EDIT_SIMPLE, network_settings->send_port, &network_settings->send_port_len, 25, nk_filter_default);
nk_layout_row_static(ctx, 20, 200, 2);
nk_label(ctx, "Host:", NK_TEXT_LEFT);
nk_edit_string(ctx, NK_EDIT_SIMPLE, network_settings->send_host, &network_settings->send_host_len, 25, nk_filter_default);
nk_group_end(ctx);
}
/*nk_layout_row_static(ctx, 20, 200, 2);
nk_label(ctx, network_attr[5], NK_TEXT_LEFT);
nk_edit_string(ctx, NK_EDIT_SIMPLE, text_buffer[5], &text_len[5], 50, nk_filter_default);*/
//OK Button
nk_layout_row(ctx, NK_DYNAMIC, 27, 3, save_ok_ratio);
nk_spacing(ctx, 1);
if (nk_button_label(ctx, "Save"))
{
network_settings->save_network_settings = nk_true;
network_settings->show_network_settings = nk_false;
nk_popup_close(ctx);
}
if (nk_button_label(ctx, "OK"))
{
network_settings->save_network_settings = nk_false;
network_settings->show_network_settings = nk_false;
nk_popup_close(ctx);
}
nk_popup_end(ctx);
}
else
network_settings->show_network_settings = nk_false;
}
void draw_getting_started_popup(struct nk_context *ctx, int *show_getting_started)
{
static struct nk_rect s = {20, 30, 480, 500};
if (nk_popup_begin(ctx, NK_POPUP_STATIC, "Getting Started", NK_WINDOW_CLOSABLE, s))
{
nk_layout_row_dynamic(ctx, 80, 1);
nk_label_wrap(ctx, "Getting Started information about CCX will come here! This popup will be populated at the end.");
nk_popup_end(ctx);
}
else
*show_getting_started = nk_false;
}
void draw_about_ccx_popup(struct nk_context *ctx, int *show_about_ccx, struct nk_user_font *droid_big, struct nk_user_font *droid_head)
{
const float ccx_ratio[] = {0.3f, 0.4f, 0.3f};
const float ok_ratio[] = {0.9f, 0.1f};
static struct nk_rect s = {20, 30, 480, 500};
if (nk_popup_begin(ctx, NK_POPUP_STATIC, "About CCExtractor", NK_WINDOW_CLOSABLE | NK_WINDOW_NO_SCROLLBAR, s))
{
nk_style_push_font(ctx, droid_big);
nk_layout_row(ctx, NK_DYNAMIC, 30, 3, ccx_ratio);
nk_spacing(ctx, 1);
nk_label_wrap(ctx, "About CCExtractor" /*, NK_TEXT_LEFT*/);
nk_style_pop_font(ctx);
nk_layout_row_dynamic(ctx, 390, 1);
if (nk_group_begin(ctx, "About CCExtractor", NK_WINDOW_BACKGROUND))
{
nk_style_push_font(ctx, droid_head);
nk_layout_row_dynamic(ctx, 23, 1);
nk_label_wrap(ctx, "What's CCExtractor?");
nk_style_pop_font(ctx);
nk_layout_row_dynamic(ctx, 65, 1);
nk_label_wrap(ctx, "A tool that analyzes video files and produces independent subtitle files from the closed captions data. CCExtractor is portable, small, and very fast. It works in Linux, Windows, and OSX.");
nk_style_push_font(ctx, droid_head);
nk_layout_row_dynamic(ctx, 23, 1);
nk_label_wrap(ctx, "What kind of closed captions does CCExtractor support?");
nk_style_pop_font(ctx);
nk_layout_row_dynamic(ctx, 47, 1);
nk_label_wrap(ctx, "American TV captions (CEA-608 is well supported, and CEA-708 is starting to look good) and Teletext based European subtitles.");
nk_style_push_font(ctx, droid_head);
nk_layout_row_dynamic(ctx, 23, 1);
nk_label_wrap(ctx, "How easy is it to use CCExtractor?");
nk_style_pop_font(ctx);
nk_layout_row_dynamic(ctx, 30, 1);
nk_label_wrap(ctx, "Very. Just tell it what file to process and it does everything for you.");
nk_style_push_font(ctx, droid_head);
nk_layout_row_dynamic(ctx, 23, 1);
nk_label_wrap(ctx, "CCExtractor integration with other tools");
nk_style_pop_font(ctx);
nk_layout_row_dynamic(ctx, 147, 1);
nk_label_wrap(ctx, "It is possible to integrate CCExtractor in a larger process. A couple of tools already call CCExtractor as part their video process - this way they get subtitle support for free. Starting in 0.52, CCExtractor is very front - end friendly.Front - ends can easily get real - time status information.The GUI source code is provided and can be used for reference. Any tool, commercial or not, is specifically allowed to use CCExtractor for any use the authors seem fit. So if your favourite video tools still lacks captioning tool, feel free to send the authors here.");
nk_style_push_font(ctx, droid_head);
nk_layout_row_dynamic(ctx, 50, 1);
nk_label_wrap(ctx, "What's the point of generating separate files for subtitles, if they are already in the source file?");
nk_style_pop_font(ctx);
nk_layout_row_dynamic(ctx, 367, 1);
nk_label_wrap(ctx, "There are several reasons to have subtitles separated from the video file, including: - Closed captions never survive MPEG processing. If you take a MPEG file and encode it to any format (such as divx), your result file will not have closed captions. This means that if you want to keep the subtitles, you need to keep the original file. This is hardly practical if you are archiving HDTV shows for example. - Subtitles files are small - so small (around 250 Kb for a movie) that you can quickly download them, or email them, etc, in case you have a recording without subtitles. - Subtitles files are indexable: You can have a database with all your subtitles if you want (there are many available), so you can search the dialogs. - Subtitles files are a de-facto standard: Almost every player can use them. In fact, many setbox players accept subtitles files in .srt format - so you can have subtitles in your divx movies and not just in your original DVDs. - Closed captions are stored in many different formats by capture cards. Upgrading to a new card, if it comes with a new player, may mean that you can't use your previously recorded closed captions, even if the audio/video are fine. - Closed captions require a closed caption decoder. All US TV have one (it's a legal requirement), but no European TV does, since there are not closed captions in Europe (teletext is used instead). Basically this means that if you buy a DVD in the US which has closed captions but no DVD subtitles, you are out of luck. This is a problem with many (most) old TV shows DVDs, which only come with closed captions. DVD producers don't bother doing DVD subs, since it's another way to segment the market, same as with DVD regions. ");
nk_style_push_font(ctx, droid_head);
nk_layout_row_dynamic(ctx, 23, 1);
nk_label_wrap(ctx, "How I do use subtitles once they are in a separate file?");
nk_style_pop_font(ctx);
nk_layout_row_dynamic(ctx, 80, 1);
nk_label_wrap(ctx, "CCExtractor generates files in the two most common formats: .srt (SubRip) and .smi (which is a Microsoft standard). Most players support at least .srt natively. You just need to name the .srt file as the file you want to play it with, for example sample.avi and sample.srt.");
nk_style_push_font(ctx, droid_head);
nk_layout_row_dynamic(ctx, 23, 1);
nk_label_wrap(ctx, "What kind of files can I extract closed captions from?");
nk_style_pop_font(ctx);
nk_layout_row_dynamic(ctx, 20, 1);
nk_label_wrap(ctx, "CCExtractor currently handles:");
nk_layout_row_dynamic(ctx, 20, 1);
nk_label_wrap(ctx, "- DVDs.");
nk_layout_row_dynamic(ctx, 20, 1);
nk_label_wrap(ctx, "- Most HDTV captures(where you save the Transport Stream).");
nk_layout_row_dynamic(ctx, 52, 1);
nk_label_wrap(ctx, "- Captures where captions are recorded in bttv format.The number of cards that use this card is huge.My test samples came from a Hauppage PVR - 250. You can check the complete list here:");
nk_layout_row_dynamic(ctx, 40, 1);
nk_label_colored_wrap(ctx, "http://linuxtv.org/hg/v4l-dvb/file/tip/linux/Documentation/video4linux/CARDLIST.bttv", nk_rgb(61, 117, 206));
nk_layout_row_dynamic(ctx, 20, 1);
nk_label_wrap(ctx, "- DVR - MS(microsoft digital video recording).");
nk_layout_row_dynamic(ctx, 20, 1);
nk_label_wrap(ctx, "- Tivo files");
nk_layout_row_dynamic(ctx, 20, 1);
nk_label_wrap(ctx, "- ReplayTV files");
nk_layout_row_dynamic(ctx, 20, 1);
nk_label_wrap(ctx, "- Dish Network files");
nk_layout_row_dynamic(ctx, 80, 1);
nk_label_wrap(ctx, "Usually, if you record a TV show with your capture card and CCExtractor produces the expected result, it will work for your all recordings.If it doesn't, which means that your card uses a format CCExtractor can't handle, please contact me and we'll try to make it work.");
nk_style_push_font(ctx, droid_head);
nk_layout_row_dynamic(ctx, 23, 1);
nk_label_wrap(ctx, "Can I edit the subtitles? ");
nk_style_pop_font(ctx);
nk_layout_row_dynamic(ctx, 43, 1);
nk_label_wrap(ctx, ".srt files are just text files, with time information (when subtitles are supposed to be shown and for how long) and some basic formatting (use italics, bold, etc). So you can edit them with any text editor. If you need to do serious editing (such as adjusting timing), you can use subtitle editing tools - there are many available.");
nk_style_push_font(ctx, droid_head);
nk_layout_row_dynamic(ctx, 23, 1);
nk_label_wrap(ctx, "Can CCExtractor generate other subtitles formats?");
nk_style_pop_font(ctx);
nk_layout_row_dynamic(ctx, 23, 1);
nk_label_wrap(ctx, "At this time, CCExtractor can generate .srt, .smi and raw and bin files.");
nk_style_push_font(ctx, droid_head);
nk_layout_row_dynamic(ctx, 23, 1);
nk_label_wrap(ctx, "How I can contact the author?");
nk_style_pop_font(ctx);
nk_layout_row_dynamic(ctx, 23, 1);
nk_label_wrap(ctx, "Send me an email: carlos@ccextractor.org");
nk_group_end(ctx);
}
nk_layout_row(ctx, NK_DYNAMIC, 27, 2, ok_ratio);
nk_spacing(ctx, 1);
if (nk_button_label(ctx, "OK"))
{
*show_about_ccx = nk_false;
nk_popup_close(ctx);
}
nk_popup_end(ctx);
}
else
*show_about_ccx = nk_false;
}
void draw_progress_details_popup(struct nk_context *ctx, int *show_progress_details, struct main_tab *main_settings)
{
static struct nk_rect s = {20, 30, 480, 500};
if (nk_popup_begin(ctx, NK_POPUP_STATIC, "Progress Details of Extraction", NK_WINDOW_CLOSABLE, s))
{
nk_layout_row_dynamic(ctx, 20, 1);
for (int i = 0; i < main_settings->activity_string_count; i++)
nk_label_wrap(ctx, main_settings->activity_string[i]);
nk_popup_end(ctx);
}
else
*show_progress_details = nk_false;
}
void draw_color_popup(struct nk_context *ctx, struct output_tab *output)
{
static struct nk_rect s = {250, 250, 200, 230};
if (nk_popup_begin(ctx, NK_POPUP_STATIC, "Color Picker", NK_WINDOW_TITLE | NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_BORDER, s))
{
nk_layout_row_dynamic(ctx, 160, 1);
output->color_rgb = nk_color_picker(ctx, output->color_rgb, NK_RGBA);
nk_layout_row_dynamic(ctx, 25, 3);
nk_spacing(ctx, 1);
if (nk_button_label(ctx, "OK"))
{
show_color_from_picker = nk_true;
output->color_popup = nk_false;
nk_popup_close(ctx);
}
nk_spacing(ctx, 1);
nk_popup_end(ctx);
}
else
output->color_popup = nk_false;
}
void draw_thread_popup(struct nk_context *ctx, int *show_thread_popup)
{
static struct nk_rect s = {100, 100, 300, 175};
static const float ratio[] = {0.85f, 0.15f};
if (nk_popup_begin(ctx, NK_POPUP_STATIC, "File Read Error",
NK_WINDOW_TITLE | NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_BORDER, s))
{
nk_layout_row_dynamic(ctx, 25, 1);
nk_label(ctx, "Cannot read file.", NK_TEXT_CENTERED);
nk_layout_row_dynamic(ctx, 60, 1);
nk_label_wrap(ctx, "Make sure the directory isn't write protected OR you are running the program with write permissions.");
nk_layout_row(ctx, NK_DYNAMIC, 25, 2, ratio);
nk_spacing(ctx, 1);
if (nk_button_label(ctx, "OK"))
{
*show_thread_popup = nk_false;
nk_popup_close(ctx);
}
nk_popup_end(ctx);
}
else
*show_thread_popup = nk_false;
}

View File

@@ -1,31 +0,0 @@
#ifndef POPUPS_H
#define POPUPS_H
#include "tabs.h"
struct network_popup
{
int show_network_settings;
int save_network_settings;
char udp_ipv4[30];
int udp_ipv4_len;
char tcp_pass[30];
int tcp_pass_len;
char tcp_desc[30];
int tcp_desc_len;
char send_port[30];
int send_port_len;
char send_host[30];
int send_host_len;
};
void draw_network_popup(struct nk_context *ctx, struct network_popup *network_settings);
void draw_getting_started_popup(struct nk_context *ctx, int *show_getting_started);
void draw_about_ccx_popup(struct nk_context *ctx, int *show_about_ccx, struct nk_user_font *droid_big, struct nk_user_font *droid_head);
void draw_progress_details_popup(struct nk_context *ctx, int *show_progress_details, struct main_tab *main_settings);
void draw_color_popup(struct nk_context *ctx, struct output_tab *output);
void draw_thread_popup(struct nk_context *ctx, int *show_thread_popup);
void setup_network_settings(struct network_popup *network_settings);
#endif //!POPUPS_H

View File

@@ -1,19 +0,0 @@
#ifndef NK_IMPLEMENTATION
#include "nuklear_lib/nuklear.h"
#endif // !NK_IMPLEMENTATION
#include <stdio.h>
#include "preview.h"
int preview(struct nk_context *ctx, int x, int y, int width, int height, struct main_tab *main_settings)
{
static int i;
if (nk_begin(ctx, "Preview", nk_rect(x, y, width, height), NK_WINDOW_TITLE | NK_WINDOW_BACKGROUND))
{
nk_layout_row_dynamic(ctx, 20, 1);
for (i = 0; i < main_settings->preview_string_count; i++)
nk_label_wrap(ctx, main_settings->preview_string[i]);
}
nk_end(ctx);
return !nk_window_is_closed(ctx, "Preview");
}

View File

@@ -1,8 +0,0 @@
#ifndef PREVIEW_H
#define PREVIEW_H
#include "ccextractorGUI.h"
int preview(struct nk_context *ctx, int x, int y, int width, int height, struct main_tab *main_settings);
#endif //!PREVIEW_H

View File

@@ -1,561 +0,0 @@
#include "save_load_data.h"
#include "ccextractorGUI.h"
#include "tabs.h"
#include "popups.h"
void load_data(FILE *file,
struct main_tab *main_settings,
struct input_tab *input,
struct advanced_input_tab *advanced_input,
struct output_tab *output,
struct decoders_tab *decoders,
struct credits_tab *credits,
struct debug_tab *debug,
struct hd_homerun_tab *hd_homerun,
struct burned_subs_tab *burned_subs,
struct network_popup *network_settings)
{
int null_int, r, g, b;
char null_char[260];
//Read main_tab data
fscanf(file, "port_or_files:%d\n", &main_settings->port_or_files);
fscanf(file, "port_num_len:%d\n", &main_settings->port_num_len);
if (main_settings->port_num_len > 0)
fscanf(file, "port_num:%[^\n]\n", main_settings->port_num);
else
fscanf(file, "%[^\n]\n", null_char);
fscanf(file, "is_check_common_extension:%d\n", &main_settings->is_check_common_extension);
fscanf(file, "port_select:%d\n", &main_settings->port_select);
//Read input_tab data
fscanf(file, "type_select:%d\n", &input->type_select);
fscanf(file, "is_split:%d\n", &input->is_split);
fscanf(file, "is_live_stream:%d\n", &input->is_live_stream);
fscanf(file, "wait_data_sec_len:%d\n", &input->wait_data_sec_len);
if (input->wait_data_sec_len > 0)
fscanf(file, "wait_data_sec:%[^\n]\n", input->wait_data_sec);
else
fscanf(file, "%[^\n]\n", null_char);
fscanf(file, "is_process_from:%d\n", &input->is_process_from);
fscanf(file, "is_process_until:%d\n", &input->is_process_until);
fscanf(file, "from_time_buffer:%[^\n]\n", input->from_time_buffer);
fscanf(file, "until_time_buffer:%[^\n]\n", input->until_time_buffer);
fscanf(file, "elementary_stream:%d\n", &input->elementary_stream);
fscanf(file, "is_assume_mpeg:%d\n", &input->is_assume_mpeg);
fscanf(file, "stream_type_len:%d\n", &input->stream_type_len);
if (input->stream_type_len > 0)
fscanf(file, "stream_type:%[^\n]\n", input->stream_type);
else
fscanf(file, "%[^\n]\n", null_char);
fscanf(file, "stream_pid_len:%d\n", &input->stream_pid_len);
if (input->stream_pid_len > 0)
fscanf(file, "stream_pid:%[^\n]\n", input->stream_pid);
else
fscanf(file, "%[^\n]\n", null_char);
fscanf(file, "mpeg_type_len:%d\n", &input->mpeg_type_len);
if (input->mpeg_type_len > 0)
fscanf(file, "mpeg_type:%[^\n]\n", input->mpeg_type);
else
fscanf(file, "%[^\n]\n", null_char);
fscanf(file, "teletext_decoder:%d\n", &input->teletext_decoder);
fscanf(file, "is_process_teletext_page:%d\n", &input->is_process_teletext_page);
fscanf(file, "teletext_page_number_len:%d\n", &input->teletext_page_numer_len);
if (input->teletext_page_numer_len)
fscanf(file, "teletext_page_number:%[^\n]\n", input->teletext_page_number);
else
fscanf(file, "%[^\n]\n", null_char);
fscanf(file, "is_limit:%d\n", &input->is_limit);
fscanf(file, "screenful_limit_buffer:%[^\n]\n", input->screenful_limit_buffer);
fscanf(file, "clock_input:%d\n", &input->clock_input);
//Read advanced_input_tab data
fscanf(file, "is_multiple_program:%d\n", &advanced_input->is_multiple_program);
fscanf(file, "multiple_program:%d\n", &advanced_input->multiple_program);
fscanf(file, "prog_number_len:%d\n", &advanced_input->prog_number_len);
if (advanced_input->prog_number_len)
fscanf(file, "prog_number:%[^\n]\n", advanced_input->prog_number);
else
fscanf(file, "%[^\n]\n", null_char);
fscanf(file, "set_myth:%d\n", &advanced_input->set_myth);
fscanf(file, "is_mpeg_90090:%d\n", &advanced_input->is_mpeg_90090);
fscanf(file, "is_padding_0000:%d\n", &advanced_input->is_padding_0000);
fscanf(file, "is_order_ccinfo:%d\n", &advanced_input->is_order_ccinfo);
fscanf(file, "is_win_bug:%d\n", &advanced_input->is_win_bug);
fscanf(file, "is_hauppage_file:%d\n", &advanced_input->is_hauppage_file);
fscanf(file, "is_process_mp4:%d\n", &advanced_input->is_process_mp4);
fscanf(file, "is_ignore_broadcast:%d\n", &advanced_input->is_ignore_broadcast);
//Read output_tab data
fscanf(file, "type_select:%d\n", &output->type_select);
fscanf(file, "is_filename:%d\n", &output->is_filename);
fscanf(file, "filename_len:%d\n", &output->filename_len);
if (output->filename_len > 0)
fscanf(file, "filename:%[^\n]\n", output->filename);
else
fscanf(file, "%[^\n]\n", null_char);
fscanf(file, "is_delay:%d\n", &output->is_delay);
fscanf(file, "delay_sec_buffer:%[^\n]\n", output->delay_sec_buffer);
fscanf(file, "is_export_xds:%d\n", &output->is_export_xds);
fscanf(file, "encoding:%d\n", &output->encoding);
fscanf(file, "is_bom:%d\n", &output->is_bom);
fscanf(file, "is_cap_standard:%d\n", &output->is_cap_standard);
fscanf(file, "is_cap_file:%d\n", &output->is_cap_file);
fscanf(file, "cap_dictionary_len:%d\n", &output->cap_dictionary_len);
if (output->cap_dictionary_len > 0)
fscanf(file, "cap_dictionary:%[^\n]\n", output->cap_dictionary);
else
fscanf(file, "%[^\n]\n", null_char);
fscanf(file, "line_ending:%d\n", &output->line_ending);
fscanf(file, "is_center:%d\n", &output->is_center);
fscanf(file, "is_dash:%d\n", &output->is_dash);
fscanf(file, "no_typesetting:%d\n", &output->no_typesetting);
fscanf(file, "font_color:%d\n", &output->font_color);
fscanf(file, "color_hex:%[^\n]\n", output->color_hex);
fscanf(file, "color_rgb_r:%d\n", &r);
fscanf(file, "color_rgb_g:%d\n", &g);
fscanf(file, "color_rgb_b:%d\n", &b);
output->color_rgb.r = (nk_byte)r;
output->color_rgb.g = (nk_byte)g;
output->color_rgb.b = (nk_byte)b;
fscanf(file, "onetime_or_realtime:%d\n", &output->onetime_or_realtime);
fscanf(file, "roll_limit_select:%d\n", &output->roll_limit_select);
//Read decoders_tab data
fscanf(file, "is_field1:%d\n", &decoders->is_field1);
fscanf(file, "is_field2:%d\n", &decoders->is_field2);
fscanf(file, "channel:%d\n", &decoders->channel);
fscanf(file, "is_708:%d\n", &decoders->is_708);
fscanf(file, "services_len:%d\n", &decoders->services_len);
if (decoders->services_len > 0)
fscanf(file, "services:%[^\n]\n", decoders->services);
else
fscanf(file, "%[^\n]\n", null_char);
fscanf(file, "teletext_dvb:%d\n", &decoders->teletext_dvb);
fscanf(file, "min_distance_len:%d\n", &decoders->min_distance_len);
if (decoders->min_distance_len > 0)
fscanf(file, "min_distance:%[^\n]\n", decoders->min_distance);
else
fscanf(file, "%[^\n]\n", null_char);
fscanf(file, "max_distance_len:%d\n", &decoders->max_distance_len);
if (decoders->max_distance_len > 0)
fscanf(file, "max_distance:%[^\n]\n", decoders->max_distance);
else
fscanf(file, "%[^\n]\n", null_char);
//Read credits tab data
fscanf(file, "is_start_text:%d\n", &credits->is_start_text);
fscanf(file, "is_before:%d\n", &credits->is_before);
fscanf(file, "is_after:%d\n", &credits->is_after);
fscanf(file, "before_time_buffer:%[^\n]\n", credits->before_time_buffer);
fscanf(file, "after_time_buffer:%[^\n]\n", credits->after_time_buffer);
fscanf(file, "start_atmost_sec_len:%d\n", &credits->start_atmost_sec_len);
if (credits->start_atmost_sec_len > 0)
fscanf(file, "start_atmost_sec:%[^\n]\n", credits->start_atmost_sec);
else
fscanf(file, "%[^\n]\n", null_char);
fscanf(file, "start_atleast_sec_len:%d\n", &credits->start_atleast_sec_len);
if (credits->start_atleast_sec_len > 0)
fscanf(file, "start_atleast_sec:%[^\n]\n", credits->start_atleast_sec);
else
fscanf(file, "%[^\n]\n", null_char);
fscanf(file, "is_end_text:%d\n", &credits->is_end_text);
fscanf(file, "end_atmost_sec_len:%d\n", &credits->end_atmost_sec_len);
if (credits->end_atmost_sec_len > 0)
fscanf(file, "end_atmost_sec:%[^\n]\n", credits->end_atmost_sec);
else
fscanf(file, "%[^\n]\n", null_char);
fscanf(file, "end_atleast_sec_len:%d\n", &credits->end_atleast_sec_len);
if (credits->end_atleast_sec_len > 0)
fscanf(file, "end_atleast_sec:%[^\n]\n", credits->end_atleast_sec);
else
fscanf(file, "%[^\n]\n", null_char);
fscanf(file, "start_text_len:%d\n", &credits->start_text_len);
fscanf(file, "end_text_len:%d\n", &credits->end_text_len);
read_credits(file, credits);
//Read debug tab data
fscanf(file, "is_elementary_stream:%d\n", &debug->is_elementary_stream);
fscanf(file, "elementary_stream_len:%d\n", &debug->elementary_stream_len);
if (debug->elementary_stream_len > 0)
fscanf(file, "elementary_stream:%[^\n]\n", debug->elementary_stream);
else
fscanf(file, "%[^\n]\n", null_char);
fscanf(file, "is_dump_packets:%d\n", &debug->is_dump_packets);
fscanf(file, "is_debug_608:%d\n", &debug->is_debug_608);
fscanf(file, "is_debug_708:%d\n", &debug->is_debug_708);
fscanf(file, "is_stamp_output:%d\n", &debug->is_stamp_output);
fscanf(file, "is_debug_analysed_vid:%d\n", &debug->is_debug_analysed_vid);
fscanf(file, "is_raw_608_708:%d\n", &debug->is_raw_608_708);
fscanf(file, "is_debug_parsed:%d\n", &debug->is_debug_parsed);
fscanf(file, "is_disable_sync:%d\n", &debug->is_disable_sync);
fscanf(file, "is_no_padding:%d\n", &debug->is_no_padding);
fscanf(file, "is_debug_xds:%d\n", &debug->is_debug_xds);
fscanf(file, "is_output_pat:%d\n", &debug->is_output_pat);
fscanf(file, "is_output_pmt:%d\n", &debug->is_output_pmt);
fscanf(file, "is_scan_ccdata:%d\n", &debug->is_scan_ccdata);
fscanf(file, "is_output_levenshtein:%d\n", &debug->is_output_levenshtein);
//Read HD Homerun Tab data
fscanf(file, "location_len:%d\n", &hd_homerun->location_len);
if (hd_homerun->location_len > 0)
fscanf(file, "location:%[^\n]\n", hd_homerun->location);
else
fscanf(file, "%[^\n]\n", null_char);
fscanf(file, "tuner_len:%d\n", &hd_homerun->tuner_len);
if (hd_homerun->tuner_len > 0)
fscanf(file, "tuner:%[^\n]\n", hd_homerun->tuner);
else
fscanf(file, "%[^\n]\n", null_char);
fscanf(file, "channel_len:%d\n", &hd_homerun->channel_len);
if (hd_homerun->channel_len > 0)
fscanf(file, "channel:%[^\n]\n", hd_homerun->channel);
else
fscanf(file, "%[^\n]\n", null_char);
fscanf(file, "program_len:%d\n", &hd_homerun->program_len);
if (hd_homerun->program_len > 0)
fscanf(file, "program:%[^\n]\n", hd_homerun->program);
else
fscanf(file, "%[^\n]\n", null_char);
fscanf(file, "ipv4_address_len:%d\n", &hd_homerun->ipv4_address_len);
if (hd_homerun->ipv4_address_len > 0)
fscanf(file, "ipv4_address:%[^\n]\n", hd_homerun->ipv4_address);
else
fscanf(file, "%[^\n]\n", null_char);
fscanf(file, "port_number_len:%d\n", &hd_homerun->port_number_len);
if (hd_homerun->port_number_len > 0)
fscanf(file, "port_number:%[^\n]\n", hd_homerun->port_number);
else
fscanf(file, "%[^\n]\n", null_char);
//Read Burned Subs tab data
fscanf(file, "is_burnded_subs:%d\n", &burned_subs->is_burned_subs);
fscanf(file, "color_type:%d\n", &burned_subs->color_type);
fscanf(file, "sub_color_select:%d\n", &burned_subs->subs_color_select);
fscanf(file, "custom_hue_len:%d\n", &burned_subs->custom_hue_len);
if (burned_subs->custom_hue_len > 0)
fscanf(file, "custom_hue:%[^\n]\n", burned_subs->custom_hue);
else
fscanf(file, "%[^\n]\n", null_char);
fscanf(file, "ocr_mode:%d\n", &burned_subs->ocr_mode);
fscanf(file, "min_duration_len:%d\n", &burned_subs->min_duration_len);
if (burned_subs->min_duration_len > 0)
fscanf(file, "min_duration:%[^\n]\n", burned_subs->min_duration);
else
fscanf(file, "%[^\n]\n", null_char);
fscanf(file, "luminance_threshold:%d\n", &burned_subs->luminance_threshold);
fscanf(file, "confidence_threshold:%d\n", &burned_subs->confidence_threshold);
fscanf(file, "is_italic:%d\n", &burned_subs->is_italic);
//Read Network Settings data
fscanf(file, "udp_ipv4_len:%d\n", &network_settings->udp_ipv4_len);
if (network_settings->udp_ipv4_len > 0)
fscanf(file, "udp_ipv4:%[^\n]\n", network_settings->udp_ipv4);
else
fscanf(file, "udp_ipv4:%[^\n]\n", null_char);
fscanf(file, "tcp_pass_len:%d\n", &network_settings->tcp_pass_len);
if (network_settings->tcp_pass_len > 0)
fscanf(file, "tcp_pass:%[^\n]\n", network_settings->tcp_pass);
else
fscanf(file, "tcp_pass:%[^\n]\n", null_char);
fscanf(file, "tcp_desc_len:%d\n", &network_settings->tcp_desc_len);
if (network_settings->tcp_desc_len > 0)
fscanf(file, "tcp_desc:%[^\n]\n", network_settings->tcp_desc);
else
fscanf(file, "tcp_desc:%[^\n]\n", null_char);
fscanf(file, "send_port_len:%d\n", &network_settings->send_port_len);
if (network_settings->send_port_len > 0)
fscanf(file, "send_port:%[^\n]\n", network_settings->send_port);
else
fscanf(file, "send_port:%[^\n]\n", null_char);
fscanf(file, "send_host_len:%d\n", &network_settings->send_host_len);
if (network_settings->send_host_len > 0)
fscanf(file, "send_host:%[^\n]\n", network_settings->send_host);
fscanf(file, "send_host:%[^\n]\n", null_char);
}
void save_data(FILE *file,
struct main_tab *main_settings,
struct input_tab *input,
struct advanced_input_tab *advanced_input,
struct output_tab *output,
struct decoders_tab *decoders,
struct credits_tab *credits,
struct debug_tab *debug,
struct hd_homerun_tab *hd_homerun,
struct burned_subs_tab *burned_subs,
struct network_popup *network_settings)
{
//Write main_tab data
fprintf(file, "port_or_files:%d\n", main_settings->port_or_files);
fprintf(file, "port_num_len:%d\n", main_settings->port_num_len);
fprintf(file, "port_num:%s\n", main_settings->port_num);
fprintf(file, "is_check_common_extension:%d\n", main_settings->is_check_common_extension);
fprintf(file, "port_select:%d\n", main_settings->port_select);
//Write input_tab data
fprintf(file, "type_select:%d\n", input->type_select);
fprintf(file, "is_split:%d\n", input->is_split);
fprintf(file, "is_live_stream:%d\n", input->is_live_stream);
fprintf(file, "wait_data_sec_len:%d\n", input->wait_data_sec_len);
fprintf(file, "wait_data_sec:%s\n", input->wait_data_sec);
fprintf(file, "is_process_from:%d\n", input->is_process_from);
fprintf(file, "is_process_until:%d\n", input->is_process_until);
fprintf(file, "from_time_buffer:%s\n", input->from_time_buffer);
fprintf(file, "until_time_buffer:%s\n", input->until_time_buffer);
fprintf(file, "elementary_stream:%d\n", input->elementary_stream);
fprintf(file, "is_assume_mpeg:%d\n", input->is_assume_mpeg);
fprintf(file, "stream_type_len:%d\n", input->stream_type_len);
fprintf(file, "stream_type:%s\n", input->stream_type);
fprintf(file, "stream_pid_len:%d\n", input->stream_pid_len);
fprintf(file, "stream_pid:%s\n", input->stream_pid);
fprintf(file, "mpeg_type_len:%d\n", input->mpeg_type_len);
fprintf(file, "mpeg_type:%s\n", input->mpeg_type);
fprintf(file, "teletext_decoder:%d\n", input->teletext_decoder);
fprintf(file, "is_process_teletext_page:%d\n", input->is_process_teletext_page);
fprintf(file, "teletext_page_number_len:%d\n", input->teletext_page_numer_len);
fprintf(file, "teletext_page_number:%s\n", input->teletext_page_number);
fprintf(file, "is_limit:%d\n", input->is_limit);
fprintf(file, "screenful_limit_buffer:%s\n", input->screenful_limit_buffer);
fprintf(file, "clock_input:%d\n", input->clock_input);
//Write advanced_input_tab data
fprintf(file, "is_multiple_program:%d\n", advanced_input->is_multiple_program);
fprintf(file, "multiple_program:%d\n", advanced_input->multiple_program);
fprintf(file, "prog_number_len:%d\n", advanced_input->prog_number_len);
fprintf(file, "prog_number:%s\n", advanced_input->prog_number);
fprintf(file, "set_myth:%d\n", advanced_input->set_myth);
fprintf(file, "is_mpeg_90090:%d\n", advanced_input->is_mpeg_90090);
fprintf(file, "is_padding_0000:%d\n", advanced_input->is_padding_0000);
fprintf(file, "is_order_ccinfo:%d\n", advanced_input->is_order_ccinfo);
fprintf(file, "is_win_bug:%d\n", advanced_input->is_win_bug);
fprintf(file, "is_hauppage_file:%d\n", advanced_input->is_hauppage_file);
fprintf(file, "is_process_mp4:%d\n", advanced_input->is_process_mp4);
fprintf(file, "is_ignore_broadcast:%d\n", advanced_input->is_ignore_broadcast);
//Write output_tab data
fprintf(file, "type_select:%d\n", output->type_select);
fprintf(file, "is_filename:%d\n", output->is_filename);
fprintf(file, "filename_len:%d\n", output->filename_len);
fprintf(file, "filename:%s\n", output->filename);
fprintf(file, "is_delay:%d\n", output->is_delay);
fprintf(file, "delay_sec_buffer:%s\n", output->delay_sec_buffer);
fprintf(file, "is_export_xds:%d\n", output->is_export_xds);
fprintf(file, "encoding:%d\n", output->encoding);
fprintf(file, "is_bom:%d\n", output->is_bom);
fprintf(file, "is_cap_standard:%d\n", output->is_cap_standard);
fprintf(file, "is_cap_file:%d\n", output->is_cap_file);
fprintf(file, "cap_dictionary_len:%d\n", output->cap_dictionary_len);
fprintf(file, "cap_dictionary:%s\n", output->cap_dictionary);
fprintf(file, "line_ending:%d\n", output->line_ending);
fprintf(file, "is_center:%d\n", output->is_center);
fprintf(file, "is_dash:%d\n", output->is_dash);
fprintf(file, "no_typesetting:%d\n", output->no_typesetting);
fprintf(file, "font_color:%d\n", output->font_color);
fprintf(file, "color_hex:%s\n", output->color_hex);
fprintf(file, "color_rgb_r:%d\n", output->color_rgb.r);
fprintf(file, "color_rgb_g:%d\n", output->color_rgb.g);
fprintf(file, "color_rgb_b:%d\n", output->color_rgb.b);
fprintf(file, "onetime_or_realtime:%d\n", output->onetime_or_realtime);
fprintf(file, "roll_limit_select:%d\n", output->roll_limit_select);
//Write decoders_tab data
fprintf(file, "is_field1:%d\n", decoders->is_field1);
fprintf(file, "is_field2:%d\n", decoders->is_field2);
fprintf(file, "channel:%d\n", decoders->channel);
fprintf(file, "is_708:%d\n", decoders->is_708);
fprintf(file, "services_len:%d\n", decoders->services_len);
fprintf(file, "services:%s\n", decoders->services);
fprintf(file, "teletext_dvb:%d\n", decoders->teletext_dvb);
fprintf(file, "min_distance_len:%d\n", decoders->min_distance_len);
fprintf(file, "min_distance:%s\n", decoders->min_distance);
fprintf(file, "max_distance_len:%d\n", decoders->max_distance_len);
fprintf(file, "max_distance:%s\n", decoders->max_distance);
//Write credits tab data
fprintf(file, "is_start_text:%d\n", credits->is_start_text);
fprintf(file, "is_before:%d\n", credits->is_before);
fprintf(file, "is_after:%d\n", credits->is_after);
fprintf(file, "before_time_buffer:%s\n", credits->before_time_buffer);
fprintf(file, "after_time_buffer:%s\n", credits->after_time_buffer);
fprintf(file, "start_atmost_sec_len:%d\n", credits->start_atmost_sec_len);
fprintf(file, "start_atmost_sec:%s\n", credits->start_atmost_sec);
fprintf(file, "start_atleast_sec_len:%d\n", credits->start_atleast_sec_len);
fprintf(file, "start_atleast_sec:%s\n", credits->start_atleast_sec);
fprintf(file, "is_end_text:%d\n", credits->is_end_text);
fprintf(file, "end_atmost_sec_len:%d\n", credits->end_atmost_sec_len);
fprintf(file, "end_atmost_sec:%s\n", credits->end_atmost_sec);
fprintf(file, "end_atleast_sec_len:%d\n", credits->end_atleast_sec_len);
fprintf(file, "end_atleast_sec:%s\n", credits->end_atleast_sec);
fprintf(file, "start_text_len:%d\n", credits->start_text_len);
fprintf(file, "end_text_len:%d\n", credits->end_text_len);
write_credits(file, credits);
//Write debug tab data
fprintf(file, "is_elementary_stream:%d\n", debug->is_elementary_stream);
fprintf(file, "elementary_stream_len:%d\n", debug->elementary_stream_len);
fprintf(file, "elementary_stream:%s\n", debug->elementary_stream);
fprintf(file, "is_dump_packets:%d\n", debug->is_dump_packets);
fprintf(file, "is_debug_608:%d\n", debug->is_debug_608);
fprintf(file, "is_debug_708:%d\n", debug->is_debug_708);
fprintf(file, "is_stamp_output:%d\n", debug->is_stamp_output);
fprintf(file, "is_debug_analysed_vid:%d\n", debug->is_debug_analysed_vid);
fprintf(file, "is_raw_608_708:%d\n", debug->is_raw_608_708);
fprintf(file, "is_debug_parsed:%d\n", debug->is_debug_parsed);
fprintf(file, "is_disable_sync:%d\n", debug->is_disable_sync);
fprintf(file, "is_no_padding:%d\n", debug->is_no_padding);
fprintf(file, "is_debug_xds:%d\n", debug->is_debug_xds);
fprintf(file, "is_output_pat:%d\n", debug->is_output_pat);
fprintf(file, "is_output_pmt:%d\n", debug->is_output_pmt);
fprintf(file, "is_scan_ccdata:%d\n", debug->is_scan_ccdata);
fprintf(file, "is_output_levenshtein:%d\n", debug->is_output_levenshtein);
//Write HD Homerun Tab data
fprintf(file, "location_len:%d\n", hd_homerun->location_len);
fprintf(file, "location:%s\n", hd_homerun->location);
fprintf(file, "tuner_len:%d\n", hd_homerun->tuner_len);
fprintf(file, "tuner:%s\n", hd_homerun->tuner);
fprintf(file, "channel_len:%d\n", hd_homerun->channel_len);
fprintf(file, "channel:%s\n", hd_homerun->channel);
fprintf(file, "program_len:%d\n", hd_homerun->program_len);
fprintf(file, "program:%s\n", hd_homerun->program);
fprintf(file, "ipv4_address_len:%d\n", hd_homerun->ipv4_address_len);
fprintf(file, "ipv4_address:%s\n", hd_homerun->ipv4_address);
fprintf(file, "port_number_len:%d\n", hd_homerun->port_number_len);
fprintf(file, "port_number:%s\n", hd_homerun->port_number);
//Write Burned Subs tab data
fprintf(file, "is_burnded_subs:%d\n", burned_subs->is_burned_subs);
fprintf(file, "color_type:%d\n", burned_subs->color_type);
fprintf(file, "sub_color_select:%d\n", burned_subs->subs_color_select);
fprintf(file, "custom_hue_len:%d\n", burned_subs->custom_hue_len);
fprintf(file, "custom_hue:%s\n", burned_subs->custom_hue);
fprintf(file, "ocr_mode:%d\n", burned_subs->ocr_mode);
fprintf(file, "min_duration_len:%d\n", burned_subs->min_duration_len);
fprintf(file, "min_duration:%s\n", burned_subs->min_duration);
fprintf(file, "luminance_threshold:%d\n", burned_subs->luminance_threshold);
fprintf(file, "confidence_threshold:%d\n", burned_subs->confidence_threshold);
fprintf(file, "is_italic:%d\n", burned_subs->is_italic);
//Write Network Settings popup data
if (network_settings->save_network_settings)
{
fprintf(file, "udp_ipv4_len:%d\n", network_settings->udp_ipv4_len);
fprintf(file, "udp_ipv4:%s\n", network_settings->udp_ipv4);
fprintf(file, "tcp_pass_len:%d\n", network_settings->tcp_pass_len);
fprintf(file, "tcp_pass:%s\n", network_settings->tcp_pass);
fprintf(file, "tcp_desc_len:%d\n", network_settings->tcp_desc_len);
fprintf(file, "tcp_desc:%s\n", network_settings->tcp_desc);
fprintf(file, "send_port_len:%d\n", network_settings->send_port_len);
fprintf(file, "send_port:%s\n", network_settings->send_port);
fprintf(file, "send_host_len:%d\n", network_settings->send_host_len);
fprintf(file, "send_host:%s\n", network_settings->send_host);
}
}
void write_credits(FILE *file, struct credits_tab *credits)
{
//Number of newlines in end_text
static int newlines_end;
//Number of newlines in start_text
static int newlines_start;
int newline_char = 10; // '\n' is 10 in ascii encoding
for (int i = 0; i < credits->start_text_len; i++)
{
if (credits->start_text[i] == newline_char)
newlines_start++;
}
for (int i = 0; i < credits->end_text_len; i++)
{
if (credits->end_text[i] == newline_char)
newlines_end++;
}
fprintf(file, "start_text:%d\n", newlines_start);
if (credits->start_text_len > 0)
fprintf(file, "%s\n", credits->start_text);
fprintf(file, "end_text:%d\n", newlines_end);
if (credits->end_text_len > 0)
fprintf(file, "%s\n", credits->end_text);
}
void read_credits(FILE *file, struct credits_tab *credits)
{
//Number of newlines in end_text
static int newlines_end;
//Number of newlines in start_text
static int newlines_start;
static char buffer[1000], null_char[260];
if (credits->start_text_len == 0)
fscanf(file, "%[^\n]\n", null_char);
else
{
fscanf(file, "start_text:%d\n", &newlines_start);
for (int i = 0; i != newlines_start + 1; i++)
{
static char line[200];
fscanf(file, "%[^\n]\n", line);
if (!(i == newlines_start))
strcat(line, "\n");
if (strlen(buffer) > 0)
strcat(buffer, line);
else
strcpy(buffer, line);
}
memset(credits->start_text, 0, sizeof(credits->start_text));
strcpy(credits->start_text, buffer);
memset(buffer, 0, sizeof(buffer));
}
if (credits->end_text_len == 0)
fscanf(file, "%[^\n]\n", null_char);
else
{
fscanf(file, "end_text:%d\n", &newlines_end);
for (int i = 0; i != newlines_end + 1; i++)
{
static char line[200];
fscanf(file, "%[^\n]\n", line);
if (!(i == newlines_end))
strcat(line, "\n");
if (strlen(buffer) > 0)
strcat(buffer, line);
else
strcpy(buffer, line);
}
memset(credits->end_text, 0, sizeof(credits->end_text));
strcpy(credits->end_text, buffer);
}
}

View File

@@ -1,40 +0,0 @@
#ifndef SAVE_LOAD_DATA_H
#define SAVE_LOAD_DATA_H
#include "ccextractorGUI.h"
#include "tabs.h"
#include "popups.h"
#include <stdio.h>
void load_data(FILE *file,
struct main_tab* main_settings,
struct input_tab* input,
struct advanced_input_tab* advanced_input,
struct output_tab* output,
struct decoders_tab* decoders,
struct credits_tab* credits,
struct debug_tab* debug,
struct hd_homerun_tab* hd_homerun,
struct burned_subs_tab* burned_subs,
struct network_popup* network_settings);
void save_data(FILE *file,
struct main_tab* main_settings,
struct input_tab* input,
struct advanced_input_tab* advanced_input,
struct output_tab* output,
struct decoders_tab* decoders,
struct credits_tab* credits,
struct debug_tab* debug,
struct hd_homerun_tab* hd_homerun,
struct burned_subs_tab* burned_subs,
struct network_popup* network_settings);
void write_credits(FILE* file, struct credits_tab* credits);
void read_credits(FILE* file, struct credits_tab* credits);
//Number of newlines in end_text
static int newlines_end;
//Number of newlines in start_text
static int newlines_start;
#endif //!SAVE_LOAD_DATA_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,241 +0,0 @@
#ifndef TABS_H
#define TABS_H
#include "ccextractorGUI.h"
/*Global variable for output tab*/
int show_color_from_picker;
/*Data containers for other functions*/
struct output_tab
{
//General
char **type;
int type_select;
int is_filename;
char filename[260];
int filename_len;
int is_output_browser_active;
int is_delay;
char delay_sec_buffer[4];
int is_export_xds;
//Encoding
enum { LATIN, UNIC, UTF } encoding;
int is_bom;
//Capitalization
int is_cap_browser_active;
int is_cap_standard;
int is_cap_file;
char cap_dictionary[260];
int cap_dictionary_len;
//Line Endings
enum { CRLF, LF } line_ending;
//Colors and Styles
int is_center;
int is_dash;
int no_typesetting;
enum { NO_COLOR, DEFAULT_COLOR } font_color;
int color_popup;
char color_hex[7];
struct nk_color color_rgb;
//Roll-up Captions
enum {ONETIME, REALTIME} onetime_or_realtime;
char **roll_limit;
int roll_limit_select;
};
struct time {
int hours, minutes, seconds;
};
struct input_tab {
//General
char **type;
int type_select;
int is_split;
int is_live_stream;
char wait_data_sec[4];
int wait_data_sec_len;
//Timing
int is_process_from;
int is_process_until;
char from_time_buffer[10];
char until_time_buffer[10];
//Elementary Stream
enum {AUTO_DETECT,STREAM_TYPE,STREAM_PID} elementary_stream;
int is_assume_mpeg;
char stream_type[10];
int stream_type_len;
char stream_pid[10];
int stream_pid_len;
char mpeg_type[10];
int mpeg_type_len;
//Teletext
enum { AUTO_DECODE, FORCE, DISABLE } teletext_decoder;
int is_process_teletext_page;
char teletext_page_number[6];
int teletext_page_numer_len;
//Screenfuls limit
enum { NO_LIMIT, LIMITED } is_limit;
char screenful_limit_buffer[4];
//Clock
enum { AUTO, GOP, PTS } clock_input;
};
struct advanced_input_tab{
//Multiple Programs
int is_multiple_program;
enum { FIRST_PROG, PROG_NUM } multiple_program;
char prog_number[6];
int prog_number_len;
//Myth TV
enum { AUTO_MYTH, FORCE_MYTH, DISABLE_MYTH } set_myth;
//Miscellaneous
int is_mpeg_90090;
int is_padding_0000;
int is_order_ccinfo;
int is_win_bug;
int is_hauppage_file;
int is_process_mp4;
int is_ignore_broadcast;
};
struct debug_tab{
int is_elementary_stream;
char elementary_stream[260];
int elementary_stream_len;
int is_dump_packets;
int is_debug_608;
int is_debug_708;
int is_stamp_output;
int is_debug_analysed_vid;
int is_raw_608_708;
int is_debug_parsed;
int is_disable_sync;
int is_no_padding;
int is_debug_xds;
int is_output_pat;
int is_output_pmt;
int is_scan_ccdata;
int is_output_levenshtein;
//File browser trigger
int is_debug_browser_active;
};
struct burned_subs_tab{
int is_burned_subs;
enum {PRESET, CUSTOM} color_type;
char** subs_color;
int subs_color_select;
char custom_hue[4];
int custom_hue_len;
enum {FRAME_WISE, WORD_WISE, LETTER_WISE} ocr_mode;
char min_duration[4];
int min_duration_len;
int luminance_threshold;
int confidence_threshold;
int is_italic;
};
struct decoders_tab{
//608 DECODER
int is_field1;
int is_field2;
enum { CHANNEL_1, CHANNEL_2 } channel;
//708 DECODER
int is_708;
char services[15];
int services_len;
//Teletext or DVB
enum { TELETEXT, DVB } teletext_dvb;
//Teletext line Duplication
char min_distance[4];
int min_distance_len;
char max_distance[4];
int max_distance_len;
};
struct credits_tab{
//START CREDITS
int is_start_text;
char start_text[1000];
int start_text_len;
int is_before;
int is_after;
char before_time_buffer[10];
char after_time_buffer[10];
char start_atmost_sec[4];
int start_atmost_sec_len;
char start_atleast_sec[4];
int start_atleast_sec_len;
//END CREDITS
int is_end_text;
char end_text[1000];
int end_text_len;
char end_atmost_sec[4];
int end_atmost_sec_len;
char end_atleast_sec[4];
int end_atleast_sec_len;
};
struct hd_homerun_tab{
char location[260];
int location_len;
int device_select[50];
int device_num;
char **devices;
int is_homerun_browser_active;
char tuner[2];
int tuner_len;
char channel[5];
int channel_len;
char program[10];
int program_len;
char ipv4_address[16];
int ipv4_address_len;
char port_number[8];
int port_number_len;
int selected;
int threadPopup;
};
/*Tab Functions*/
void setup_output_tab(struct output_tab *output);
void setup_decoders_tab(struct decoders_tab *decoders);
void setup_credits_tab(struct credits_tab *credits);
void setup_input_tab(struct input_tab *input);
void setup_advanced_input_tab(struct advanced_input_tab *advaned_input);
void setup_debug_tab(struct debug_tab *debug);
void setup_hd_homerun_tab(struct hd_homerun_tab *hd_homerun);
void setup_burned_subs_tab(struct burned_subs_tab *burned_subs);
void draw_input_tab(struct nk_context *ctx, int *tab_screen_height, struct input_tab *input,
struct decoders_tab *decoders);
void draw_advanced_input_tab(struct nk_context *ctx, int *tab_screen_height,
struct advanced_input_tab *advaned_input);
void draw_output_tab(struct nk_context *ctx, int *tab_screen_height, struct output_tab *output,
struct main_tab *main_settings);
void draw_decoders_tab(struct nk_context *ctx, int *tab_screen_height, struct decoders_tab *decoders);
void draw_credits_tab(struct nk_context *ctx, int *tab_screen_height, struct credits_tab *credits);
void draw_debug_tab(struct nk_context *ctx, int *tab_screen_height,
struct main_tab *main_settings,
struct output_tab *output,
struct debug_tab *debug);
void draw_hd_homerun_tab(struct nk_context *ctx, int *tab_screen_height,
struct hd_homerun_tab *hd_homerun,
struct main_tab *main_settings);
void draw_burned_subs_tab(struct nk_context *ctx, int *tab_screen_height, struct burned_subs_tab *burned_subs);
#endif //!TABS_H

View File

@@ -1,16 +0,0 @@
#ifndef NK_IMPLEMENTATION
#include "nuklear_lib/nuklear.h"
#endif // !NK_IMPLEMENTATION
static int
terminal(struct nk_context *ctx, int x, int y, int width, int height, char *command)
{
if (nk_begin(ctx, "Terminal", nk_rect(x, y, width, height),
NK_WINDOW_TITLE | NK_WINDOW_BACKGROUND))
{
nk_layout_row_dynamic(ctx, 60, 1);
nk_label_wrap(ctx, command);
}
nk_end(ctx);
return !nk_window_is_closed(ctx, "Terminal");
}

View File

@@ -1,951 +0,0 @@
/*
* Dirent interface for Microsoft Visual Studio
* Version 1.21
*
* Copyright (C) 2006-2012 Toni Ronkko
* This file is part of dirent. Dirent may be freely distributed
* under the MIT license. For all details and documentation, see
* https://github.com/tronkko/dirent
*/
#ifndef DIRENT_H
#define DIRENT_H
/*
* Include windows.h without Windows Sockets 1.1 to prevent conflicts with
* Windows Sockets 2.0.
*/
#ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <stdio.h>
#include <stdarg.h>
#include <wchar.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
/* Indicates that d_type field is available in dirent structure */
#define _DIRENT_HAVE_D_TYPE
/* Indicates that d_namlen field is available in dirent structure */
#define _DIRENT_HAVE_D_NAMLEN
/* Entries missing from MSVC 6.0 */
#if !defined(FILE_ATTRIBUTE_DEVICE)
# define FILE_ATTRIBUTE_DEVICE 0x40
#endif
/* File type and permission flags for stat(), general mask */
#if !defined(S_IFMT)
# define S_IFMT _S_IFMT
#endif
/* Directory bit */
#if !defined(S_IFDIR)
# define S_IFDIR _S_IFDIR
#endif
/* Character device bit */
#if !defined(S_IFCHR)
# define S_IFCHR _S_IFCHR
#endif
/* Pipe bit */
#if !defined(S_IFFIFO)
# define S_IFFIFO _S_IFFIFO
#endif
/* Regular file bit */
#if !defined(S_IFREG)
# define S_IFREG _S_IFREG
#endif
/* Read permission */
#if !defined(S_IREAD)
# define S_IREAD _S_IREAD
#endif
/* Write permission */
#if !defined(S_IWRITE)
# define S_IWRITE _S_IWRITE
#endif
/* Execute permission */
#if !defined(S_IEXEC)
# define S_IEXEC _S_IEXEC
#endif
/* Pipe */
#if !defined(S_IFIFO)
# define S_IFIFO _S_IFIFO
#endif
/* Block device */
#if !defined(S_IFBLK)
# define S_IFBLK 0
#endif
/* Link */
#if !defined(S_IFLNK)
# define S_IFLNK 0
#endif
/* Socket */
#if !defined(S_IFSOCK)
# define S_IFSOCK 0
#endif
/* Read user permission */
#if !defined(S_IRUSR)
# define S_IRUSR S_IREAD
#endif
/* Write user permission */
#if !defined(S_IWUSR)
# define S_IWUSR S_IWRITE
#endif
/* Execute user permission */
#if !defined(S_IXUSR)
# define S_IXUSR 0
#endif
/* Read group permission */
#if !defined(S_IRGRP)
# define S_IRGRP 0
#endif
/* Write group permission */
#if !defined(S_IWGRP)
# define S_IWGRP 0
#endif
/* Execute group permission */
#if !defined(S_IXGRP)
# define S_IXGRP 0
#endif
/* Read others permission */
#if !defined(S_IROTH)
# define S_IROTH 0
#endif
/* Write others permission */
#if !defined(S_IWOTH)
# define S_IWOTH 0
#endif
/* Execute others permission */
#if !defined(S_IXOTH)
# define S_IXOTH 0
#endif
/* Maximum length of file name */
#if !defined(PATH_MAX)
# define PATH_MAX MAX_PATH
#endif
#if !defined(FILENAME_MAX)
# define FILENAME_MAX MAX_PATH
#endif
#if !defined(NAME_MAX)
# define NAME_MAX FILENAME_MAX
#endif
/* File type flags for d_type */
#define DT_UNKNOWN 0
#define DT_REG S_IFREG
#define DT_DIR S_IFDIR
#define DT_FIFO S_IFIFO
#define DT_SOCK S_IFSOCK
#define DT_CHR S_IFCHR
#define DT_BLK S_IFBLK
#define DT_LNK S_IFLNK
/* Macros for converting between st_mode and d_type */
#define IFTODT(mode) ((mode) & S_IFMT)
#define DTTOIF(type) (type)
/*
* File type macros. Note that block devices, sockets and links cannot be
* distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
* only defined for compatibility. These macros should always return false
* on Windows.
*/
#if !defined(S_ISFIFO)
# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
#endif
#if !defined(S_ISDIR)
# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#endif
#if !defined(S_ISREG)
# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
#endif
#if !defined(S_ISLNK)
# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
#endif
#if !defined(S_ISSOCK)
# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
#endif
#if !defined(S_ISCHR)
# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
#endif
#if !defined(S_ISBLK)
# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
#endif
/* Return the exact length of d_namlen without zero terminator */
#define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
/* Return number of bytes needed to store d_namlen */
#define _D_ALLOC_NAMLEN(p) (PATH_MAX)
#ifdef __cplusplus
extern "C" {
#endif
/* Wide-character version */
struct _wdirent {
/* Always zero */
long d_ino;
/* Structure size */
unsigned short d_reclen;
/* Length of name without \0 */
size_t d_namlen;
/* File type */
int d_type;
/* File name */
wchar_t d_name[PATH_MAX];
};
typedef struct _wdirent _wdirent;
struct _WDIR {
/* Current directory entry */
struct _wdirent ent;
/* Private file data */
WIN32_FIND_DATAW data;
/* True if data is valid */
int cached;
/* Win32 search handle */
HANDLE handle;
/* Initial directory name */
wchar_t *patt;
};
typedef struct _WDIR _WDIR;
static _WDIR *_wopendir(const wchar_t *dirname);
static struct _wdirent *_wreaddir(_WDIR *dirp);
static int _wclosedir(_WDIR *dirp);
static void _wrewinddir(_WDIR* dirp);
/* For compatibility with Symbian */
#define wdirent _wdirent
#define WDIR _WDIR
#define wopendir _wopendir
#define wreaddir _wreaddir
#define wclosedir _wclosedir
#define wrewinddir _wrewinddir
/* Multi-byte character versions */
struct dirent {
/* Always zero */
long d_ino;
/* Structure size */
unsigned short d_reclen;
/* Length of name without \0 */
size_t d_namlen;
/* File type */
int d_type;
/* File name */
char d_name[PATH_MAX];
};
typedef struct dirent dirent;
struct DIR {
struct dirent ent;
struct _WDIR *wdirp;
};
typedef struct DIR DIR;
static DIR *opendir(const char *dirname);
static struct dirent *readdir(DIR *dirp);
static int closedir(DIR *dirp);
static void rewinddir(DIR* dirp);
/* Internal utility functions */
static WIN32_FIND_DATAW *dirent_first(_WDIR *dirp);
static WIN32_FIND_DATAW *dirent_next(_WDIR *dirp);
static int dirent_mbstowcs_s(
size_t *pReturnValue,
wchar_t *wcstr,
size_t sizeInWords,
const char *mbstr,
size_t count);
static int dirent_wcstombs_s(
size_t *pReturnValue,
char *mbstr,
size_t sizeInBytes,
const wchar_t *wcstr,
size_t count);
static void dirent_set_errno(int error);
/*
* Open directory stream DIRNAME for read and return a pointer to the
* internal working area that is used to retrieve individual directory
* entries.
*/
static _WDIR*
_wopendir(
const wchar_t *dirname)
{
_WDIR *dirp = NULL;
int error;
/* Must have directory name */
if (dirname == NULL || dirname[0] == '\0') {
dirent_set_errno(ENOENT);
return NULL;
}
/* Allocate new _WDIR structure */
dirp = (_WDIR*)malloc(sizeof(struct _WDIR));
if (dirp != NULL) {
DWORD n;
/* Reset _WDIR structure */
dirp->handle = INVALID_HANDLE_VALUE;
dirp->patt = NULL;
dirp->cached = 0;
/* Compute the length of full path plus zero terminator
*
* Note that on WinRT there's no way to convert relative paths
* into absolute paths, so just assume its an absolute path.
*/
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
n = wcslen(dirname);
# else
n = GetFullPathNameW(dirname, 0, NULL, NULL);
# endif
/* Allocate room for absolute directory name and search pattern */
dirp->patt = (wchar_t*)malloc(sizeof(wchar_t) * n + 16);
if (dirp->patt) {
/*
* Convert relative directory name to an absolute one. This
* allows rewinddir() to function correctly even when current
* working directory is changed between opendir() and rewinddir().
*
* Note that on WinRT there's no way to convert relative paths
* into absolute paths, so just assume its an absolute path.
*/
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
wcsncpy_s(dirp->patt, n + 1, dirname, n);
# else
n = GetFullPathNameW(dirname, n, dirp->patt, NULL);
# endif
if (n > 0) {
wchar_t *p;
/* Append search pattern \* to the directory name */
p = dirp->patt + n;
if (dirp->patt < p) {
switch (p[-1]) {
case '\\':
case '/':
case ':':
/* Directory ends in path separator, e.g. c:\temp\ */
/*NOP*/;
break;
default:
/* Directory name doesn't end in path separator */
*p++ = '\\';
}
}
*p++ = '*';
*p = '\0';
/* Open directory stream and retrieve the first entry */
if (dirent_first(dirp)) {
/* Directory stream opened successfully */
error = 0;
}
else {
/* Cannot retrieve first entry */
error = 1;
dirent_set_errno(ENOENT);
}
}
else {
/* Cannot retrieve full path name */
dirent_set_errno(ENOENT);
error = 1;
}
}
else {
/* Cannot allocate memory for search pattern */
error = 1;
}
}
else {
/* Cannot allocate _WDIR structure */
error = 1;
}
/* Clean up in case of error */
if (error && dirp) {
_wclosedir(dirp);
dirp = NULL;
}
return dirp;
}
/*
* Read next directory entry. The directory entry is returned in dirent
* structure in the d_name field. Individual directory entries returned by
* this function include regular files, sub-directories, pseudo-directories
* "." and ".." as well as volume labels, hidden files and system files.
*/
static struct _wdirent*
_wreaddir(
_WDIR *dirp)
{
WIN32_FIND_DATAW *datap;
struct _wdirent *entp;
/* Read next directory entry */
datap = dirent_next(dirp);
if (datap) {
size_t n;
DWORD attr;
/* Pointer to directory entry to return */
entp = &dirp->ent;
/*
* Copy file name as wide-character string. If the file name is too
* long to fit in to the destination buffer, then truncate file name
* to PATH_MAX characters and zero-terminate the buffer.
*/
n = 0;
while (n + 1 < PATH_MAX && datap->cFileName[n] != 0) {
entp->d_name[n] = datap->cFileName[n];
n++;
}
dirp->ent.d_name[n] = 0;
/* Length of file name excluding zero terminator */
entp->d_namlen = n;
/* File type */
attr = datap->dwFileAttributes;
if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
entp->d_type = DT_CHR;
}
else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
entp->d_type = DT_DIR;
}
else {
entp->d_type = DT_REG;
}
/* Reset dummy fields */
entp->d_ino = 0;
entp->d_reclen = sizeof(struct _wdirent);
}
else {
/* Last directory entry read */
entp = NULL;
}
return entp;
}
/*
* Close directory stream opened by opendir() function. This invalidates the
* DIR structure as well as any directory entry read previously by
* _wreaddir().
*/
static int
_wclosedir(
_WDIR *dirp)
{
int ok;
if (dirp) {
/* Release search handle */
if (dirp->handle != INVALID_HANDLE_VALUE) {
FindClose(dirp->handle);
dirp->handle = INVALID_HANDLE_VALUE;
}
/* Release search pattern */
if (dirp->patt) {
free(dirp->patt);
dirp->patt = NULL;
}
/* Release directory structure */
free(dirp);
ok = /*success*/0;
}
else {
/* Invalid directory stream */
dirent_set_errno(EBADF);
ok = /*failure*/-1;
}
return ok;
}
/*
* Rewind directory stream such that _wreaddir() returns the very first
* file name again.
*/
static void
_wrewinddir(
_WDIR* dirp)
{
if (dirp) {
/* Release existing search handle */
if (dirp->handle != INVALID_HANDLE_VALUE) {
FindClose(dirp->handle);
}
/* Open new search handle */
dirent_first(dirp);
}
}
/* Get first directory entry (internal) */
static WIN32_FIND_DATAW*
dirent_first(
_WDIR *dirp)
{
WIN32_FIND_DATAW *datap;
/* Open directory and retrieve the first entry */
dirp->handle = FindFirstFileExW(
dirp->patt, FindExInfoStandard, &dirp->data,
FindExSearchNameMatch, NULL, 0);
if (dirp->handle != INVALID_HANDLE_VALUE) {
/* a directory entry is now waiting in memory */
datap = &dirp->data;
dirp->cached = 1;
}
else {
/* Failed to re-open directory: no directory entry in memory */
dirp->cached = 0;
datap = NULL;
}
return datap;
}
/* Get next directory entry (internal) */
static WIN32_FIND_DATAW*
dirent_next(
_WDIR *dirp)
{
WIN32_FIND_DATAW *p;
/* Get next directory entry */
if (dirp->cached != 0) {
/* A valid directory entry already in memory */
p = &dirp->data;
dirp->cached = 0;
}
else if (dirp->handle != INVALID_HANDLE_VALUE) {
/* Get the next directory entry from stream */
if (FindNextFileW(dirp->handle, &dirp->data) != FALSE) {
/* Got a file */
p = &dirp->data;
}
else {
/* The very last entry has been processed or an error occurred */
FindClose(dirp->handle);
dirp->handle = INVALID_HANDLE_VALUE;
p = NULL;
}
}
else {
/* End of directory stream reached */
p = NULL;
}
return p;
}
/*
* Open directory stream using plain old C-string.
*/
static DIR*
opendir(
const char *dirname)
{
struct DIR *dirp;
int error;
/* Must have directory name */
if (dirname == NULL || dirname[0] == '\0') {
dirent_set_errno(ENOENT);
return NULL;
}
/* Allocate memory for DIR structure */
dirp = (DIR*)malloc(sizeof(struct DIR));
if (dirp) {
wchar_t wname[PATH_MAX];
size_t n;
/* Convert directory name to wide-character string */
error = dirent_mbstowcs_s(&n, wname, PATH_MAX, dirname, PATH_MAX);
if (!error) {
/* Open directory stream using wide-character name */
dirp->wdirp = _wopendir(wname);
if (dirp->wdirp) {
/* Directory stream opened */
error = 0;
}
else {
/* Failed to open directory stream */
error = 1;
}
}
else {
/*
* Cannot convert file name to wide-character string. This
* occurs if the string contains invalid multi-byte sequences or
* the output buffer is too small to contain the resulting
* string.
*/
error = 1;
}
}
else {
/* Cannot allocate DIR structure */
error = 1;
}
/* Clean up in case of error */
if (error && dirp) {
free(dirp);
dirp = NULL;
}
return dirp;
}
/*
* Read next directory entry.
*
* When working with text consoles, please note that file names returned by
* readdir() are represented in the default ANSI code page while any output to
* console is typically formatted on another code page. Thus, non-ASCII
* characters in file names will not usually display correctly on console. The
* problem can be fixed in two ways: (1) change the character set of console
* to 1252 using chcp utility and use Lucida Console font, or (2) use
* _cprintf function when writing to console. The _cprinf() will re-encode
* ANSI strings to the console code page so many non-ASCII characters will
* display correctly.
*/
static struct dirent*
readdir(
DIR *dirp)
{
WIN32_FIND_DATAW *datap;
struct dirent *entp;
/* Read next directory entry */
datap = dirent_next(dirp->wdirp);
if (datap) {
size_t n;
int error;
/* Attempt to convert file name to multi-byte string */
error = dirent_wcstombs_s(
&n, dirp->ent.d_name, PATH_MAX, datap->cFileName, PATH_MAX);
/*
* If the file name cannot be represented by a multi-byte string,
* then attempt to use old 8+3 file name. This allows traditional
* Unix-code to access some file names despite of unicode
* characters, although file names may seem unfamiliar to the user.
*
* Be ware that the code below cannot come up with a short file
* name unless the file system provides one. At least
* VirtualBox shared folders fail to do this.
*/
if (error && datap->cAlternateFileName[0] != '\0') {
error = dirent_wcstombs_s(
&n, dirp->ent.d_name, PATH_MAX,
datap->cAlternateFileName, PATH_MAX);
}
if (!error) {
DWORD attr;
/* Initialize directory entry for return */
entp = &dirp->ent;
/* Length of file name excluding zero terminator */
entp->d_namlen = n - 1;
/* File attributes */
attr = datap->dwFileAttributes;
if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
entp->d_type = DT_CHR;
}
else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
entp->d_type = DT_DIR;
}
else {
entp->d_type = DT_REG;
}
/* Reset dummy fields */
entp->d_ino = 0;
entp->d_reclen = sizeof(struct dirent);
}
else {
/*
* Cannot convert file name to multi-byte string so construct
* an errornous directory entry and return that. Note that
* we cannot return NULL as that would stop the processing
* of directory entries completely.
*/
entp = &dirp->ent;
entp->d_name[0] = '?';
entp->d_name[1] = '\0';
entp->d_namlen = 1;
entp->d_type = DT_UNKNOWN;
entp->d_ino = 0;
entp->d_reclen = 0;
}
}
else {
/* No more directory entries */
entp = NULL;
}
return entp;
}
/*
* Close directory stream.
*/
static int
closedir(
DIR *dirp)
{
int ok;
if (dirp) {
/* Close wide-character directory stream */
ok = _wclosedir(dirp->wdirp);
dirp->wdirp = NULL;
/* Release multi-byte character version */
free(dirp);
}
else {
/* Invalid directory stream */
dirent_set_errno(EBADF);
ok = /*failure*/-1;
}
return ok;
}
/*
* Rewind directory stream to beginning.
*/
static void
rewinddir(
DIR* dirp)
{
/* Rewind wide-character string directory stream */
_wrewinddir(dirp->wdirp);
}
/* Convert multi-byte string to wide character string */
static int
dirent_mbstowcs_s(
size_t *pReturnValue,
wchar_t *wcstr,
size_t sizeInWords,
const char *mbstr,
size_t count)
{
int error;
#if defined(_MSC_VER) && _MSC_VER >= 1400
/* Microsoft Visual Studio 2005 or later */
error = mbstowcs_s(pReturnValue, wcstr, sizeInWords, mbstr, count);
#else
/* Older Visual Studio or non-Microsoft compiler */
size_t n;
/* Convert to wide-character string (or count characters) */
n = mbstowcs(wcstr, mbstr, sizeInWords);
if (!wcstr || n < count) {
/* Zero-terminate output buffer */
if (wcstr && sizeInWords) {
if (n >= sizeInWords) {
n = sizeInWords - 1;
}
wcstr[n] = 0;
}
/* Length of resulting multi-byte string WITH zero terminator */
if (pReturnValue) {
*pReturnValue = n + 1;
}
/* Success */
error = 0;
}
else {
/* Could not convert string */
error = 1;
}
#endif
return error;
}
/* Convert wide-character string to multi-byte string */
static int
dirent_wcstombs_s(
size_t *pReturnValue,
char *mbstr,
size_t sizeInBytes, /* max size of mbstr */
const wchar_t *wcstr,
size_t count)
{
int error;
#if defined(_MSC_VER) && _MSC_VER >= 1400
/* Microsoft Visual Studio 2005 or later */
error = wcstombs_s(pReturnValue, mbstr, sizeInBytes, wcstr, count);
#else
/* Older Visual Studio or non-Microsoft compiler */
size_t n;
/* Convert to multi-byte string (or count the number of bytes needed) */
n = wcstombs(mbstr, wcstr, sizeInBytes);
if (!mbstr || n < count) {
/* Zero-terminate output buffer */
if (mbstr && sizeInBytes) {
if (n >= sizeInBytes) {
n = sizeInBytes - 1;
}
mbstr[n] = '\0';
}
/* Length of resulting multi-bytes string WITH zero-terminator */
if (pReturnValue) {
*pReturnValue = n + 1;
}
/* Success */
error = 0;
}
else {
/* Cannot convert string */
error = 1;
}
#endif
return error;
}
/* Set errno variable */
static void
dirent_set_errno(
int error)
{
#if defined(_MSC_VER) && _MSC_VER >= 1400
/* Microsoft Visual Studio 2005 and later */
_set_errno(error);
#else
/* Non-Microsoft compiler or older Microsoft compiler */
errno = error;
#endif
}
#ifdef __cplusplus
}
#endif
#endif /*DIRENT_H*/

View File

@@ -2,6 +2,8 @@
/* CCExtractor, originally by carlos at ccextractor.org, now a lot of people.
Credits: See AUTHORS.TXT
License: GPL 2.0
CI verification run: 2025-12-19T08:30 - Testing merged fixes from PRs #1847 and #1848
*/
#include "ccextractor.h"
#include <stdio.h>
@@ -38,7 +40,7 @@ void print_end_msg(void)
mprint("https://github.com/CCExtractor/ccextractor/issues\n");
}
int api_start(struct ccx_s_options api_options)
int start_ccx()
{
struct lib_ccx_ctx *ctx = NULL; // Context for libs
struct lib_cc_decode *dec_ctx = NULL; // Context for decoder
@@ -48,17 +50,8 @@ int api_start(struct ccx_s_options api_options)
#if defined(ENABLE_OCR) && defined(_WIN32)
setMsgSeverity(LEPT_MSG_SEVERITY);
#endif
#ifdef ENABLE_HARDSUBX
if (api_options.hardsubx)
{
// Perform burned in subtitle extraction
hardsubx(&api_options);
return 0;
}
#endif
// Initialize CCExtractor libraries
ctx = init_libraries(&api_options);
ctx = init_libraries(&ccx_options);
if (!ctx)
{
@@ -74,6 +67,15 @@ int api_start(struct ccx_s_options api_options)
fatal(EXIT_NOT_CLASSIFIED, "Unable to create Library Context %d\n", errno);
}
#ifdef ENABLE_HARDSUBX
if (ccx_options.hardsubx)
{
// Perform burned in subtitle extraction
hardsubx(&ccx_options, ctx);
return 0;
}
#endif
#ifdef WITH_LIBCURL
curl_global_init(CURL_GLOBAL_ALL);
@@ -97,11 +99,11 @@ int api_start(struct ccx_s_options api_options)
tlt_config.page = ((tlt_config.page / 100) << 8) | (((tlt_config.page / 10) % 10) << 4) | (tlt_config.page % 10);
}
if (api_options.transcript_settings.xds)
if (ccx_options.transcript_settings.xds)
{
if (api_options.write_format != CCX_OF_TRANSCRIPT)
if (ccx_options.write_format != CCX_OF_TRANSCRIPT)
{
api_options.transcript_settings.xds = 0;
ccx_options.transcript_settings.xds = 0;
mprint("Warning: -xds ignored, XDS can only be exported to transcripts at this time.\n");
}
}
@@ -109,7 +111,7 @@ int api_start(struct ccx_s_options api_options)
time_t start, final;
time(&start);
if (api_options.binary_concat)
if (ccx_options.binary_concat)
{
ctx->total_inputsize = get_total_file_size(ctx);
if (ctx->total_inputsize < 0)
@@ -138,27 +140,10 @@ int api_start(struct ccx_s_options api_options)
#endif
terminate_asap = 0;
#ifdef ENABLE_SHARING
if (api_options.translate_enabled && ctx->num_input_files > 1)
{
mprint("[share] WARNING: simultaneous translation of several input files is not supported yet\n");
api_options.translate_enabled = 0;
api_options.sharing_enabled = 0;
}
if (api_options.translate_enabled)
{
mprint("[share] launching translate service\n");
ccx_share_launch_translator(api_options.translate_langs, api_options.translate_key);
}
#endif //ENABLE_SHARING
ret = 0;
while (switch_to_next_file(ctx, 0))
{
prepare_for_new_file(ctx);
#ifdef ENABLE_SHARING
if (api_options.sharing_enabled)
ccx_share_start(ctx->basefilename);
#endif //ENABLE_SHARING
stream_mode = ctx->demux_ctx->get_stream_mode(ctx->demux_ctx);
// Disable sync check for raw formats - they have the right timeline.
@@ -183,9 +168,10 @@ int api_start(struct ccx_s_options api_options)
----------------------------------------------------------------- */
switch (stream_mode)
{
// Note: This case is meant to fall through
case CCX_SM_ELEMENTARY_OR_NOT_FOUND:
if (!api_options.use_gop_as_pts) // If !0 then the user selected something
api_options.use_gop_as_pts = 1; // Force GOP timing for ES
if (!ccx_options.use_gop_as_pts) // If !0 then the user selected something
ccx_options.use_gop_as_pts = 1; // Force GOP timing for ES
ccx_common_timing_settings.is_elementary_stream = 1;
case CCX_SM_TRANSPORT:
case CCX_SM_PROGRAM:
@@ -196,9 +182,14 @@ int api_start(struct ccx_s_options api_options)
#ifdef ENABLE_FFMPEG
case CCX_SM_FFMPEG:
#endif
if (!api_options.use_gop_as_pts) // If !0 then the user selected something
api_options.use_gop_as_pts = 0;
if (api_options.ignore_pts_jumps)
if (!ccx_options.use_gop_as_pts) // If !0 then the user selected something
ccx_options.use_gop_as_pts = 0;
if (ccx_options.ignore_pts_jumps)
ccx_common_timing_settings.disable_sync_check = 1;
// When using GOP timing (--goptime), disable sync check because
// GOP time (wall-clock) and PES PTS (stream-relative) are in
// different time bases and will always appear as huge jumps.
if (ccx_options.use_gop_as_pts == 1)
ccx_common_timing_settings.disable_sync_check = 1;
mprint("\rAnalyzing data in general mode\n");
tmp = general_loop(ctx);
@@ -231,7 +222,7 @@ int api_start(struct ccx_s_options api_options)
{
fatal(EXIT_INCOMPATIBLE_PARAMETERS, "MP4 requires an actual file, it's not possible to read from a stream, including stdin.\n");
}
if (api_options.extract_chapters)
if (ccx_options.extract_chapters)
{
tmp = dumpchapters(ctx, &ctx->mp4_cfg, ctx->inputfile[ctx->current_file]);
}
@@ -239,7 +230,7 @@ int api_start(struct ccx_s_options api_options)
{
tmp = processmp4(ctx, &ctx->mp4_cfg, ctx->inputfile[ctx->current_file]);
}
if (api_options.print_file_reports)
if (ccx_options.print_file_reports)
print_file_report(ctx);
if (!ret)
ret = tmp;
@@ -309,14 +300,6 @@ int api_start(struct ccx_s_options api_options)
dec_ctx->timing->fts_now = 0;
dec_ctx->timing->fts_max = 0;
#ifdef ENABLE_SHARING
if (api_options.sharing_enabled)
{
ccx_share_stream_done(ctx->basefilename);
ccx_share_stop();
}
#endif //ENABLE_SHARING
if (dec_ctx->total_pulldownframes)
mprint("incl. pulldown frames: %s (%u frames at %.2ffps)\n",
print_mstime_static((LLONG)(dec_ctx->total_pulldownframes * 1000 / current_fps)),
@@ -425,25 +408,26 @@ int api_start(struct ccx_s_options api_options)
mprint("code in the MythTV's branch. Please report results to the address above. If\n");
mprint("something is broken it will be fixed. Thanks\n");
}
return ret ? EXIT_OK : EXIT_NO_CAPTIONS;
}
struct ccx_s_options *api_init_options()
{
init_options(&ccx_options);
return &ccx_options;
return ret ? EXIT_OK : EXIT_NO_CAPTIONS;
}
int main(int argc, char *argv[])
{
setlocale(LC_ALL, ""); // Supports non-English CCs
// Use POSIX locale for numbers so we get "." as decimal separator and no
// thousands' groupoing instead of what the locale might say
setlocale(LC_NUMERIC, "POSIX");
init_options(&ccx_options);
struct ccx_s_options *api_options = api_init_options();
parse_configuration(api_options);
// If "ccextractor.cnf" is present, takes options from it.
// See docs/ccextractor.cnf.sample for more info.
parse_configuration(&ccx_options);
int compile_ret = parse_parameters(api_options, argc, argv);
ccxr_init_basic_logger();
int compile_ret = ccxr_parse_parameters(argc, argv);
if (compile_ret == EXIT_NO_INPUT_FILES)
{
@@ -459,6 +443,6 @@ int main(int argc, char *argv[])
exit(compile_ret);
}
int start_ret = api_start(*api_options);
int start_ret = start_ccx();
return start_ret;
}

View File

@@ -19,7 +19,6 @@
#include "lib_ccx/ccx_common_option.h"
#include "lib_ccx/ccx_mp4.h"
#include "lib_ccx/hardsubx.h"
#include "lib_ccx/ccx_share.h"
#ifdef WITH_LIBCURL
CURL *curl;
CURLcode res;
@@ -30,17 +29,16 @@ CURLcode res;
extern struct ccx_s_options ccx_options;
extern struct lib_ccx_ctx *signal_ctx;
//volatile int terminate_asap = 0;
// volatile int terminate_asap = 0;
struct ccx_s_options* api_init_options();
struct ccx_s_options *api_init_options();
int api_start(struct ccx_s_options api_options);
void sigterm_handler(int sig);
void sigint_handler(int sig);
void print_end_msg(void);
int main(int argc, char *argv[]);
#endif //CCEXTRACTOR_H
#endif // CCEXTRACTOR_H

View File

@@ -6,25 +6,19 @@ cc_library(
hdrs = glob (["*.h", "zvbi/*.h", "*.xbm"]) + [ "//src:ccextractor.h" ],
visibility = ["//visibility:public"],
deps = [
"//src/thirdparty/protobuf-c:protobuf-c",
"//src/thirdparty/libpng:libpng",
"//src/thirdparty/freetype:freetype",
"//src/thirdparty/gpacmp4:gpacmp4",
"//src/thirdparty/lib_hash:lib_hash",
"//src/thirdparty/utf8proc:utf8proc",
],
includes = [ "thirdparty/protobuf-c", "thirdparty/libpng", "thirdparty/gpacmp4" , "." ,
includes = [ "thirdparty/libpng", "." ,
"thirdparty/freetype/include" ],
copts = [ "-Isrc/thirdparty/protobuf-c",
"-Isrc/thirdparty/libpng",
copts = [ "-Isrc/thirdparty/libpng",
"-Isrc/",
"-Isrc/thirdparty/gpacmp4",
"-Isrc/thirdparty/freetype",
"-Isrc/thirdparty/lib_hash",
"-Isrc/thirdparty/freetype/include",
"-Isrc/thirdparty/",
"-DGPAC_HAVE_CONFIG_H"
"-Isrc/thirdparty/"
]
)

View File

@@ -10,6 +10,12 @@ if(WIN32)
add_definitions(-DWIN32)
endif(WIN32)
find_package(PkgConfig)
pkg_check_modules (GPAC REQUIRED gpac)
set (EXTRA_INCLUDES ${EXTRA_INCLUDES} ${GPAC_INCLUDE_DIRS})
set (EXTRA_LIBS ${EXTRA_LIBS} ${GPAC_LIBRARIES})
if (WITH_FFMPEG)
find_package(PkgConfig)
@@ -50,12 +56,8 @@ if (WITH_OCR)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DENABLE_OCR")
endif (WITH_OCR)
if (WITH_SHARING)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DENABLE_SHARING")
endif (WITH_SHARING)
aux_source_directory ("${PROJECT_SOURCE_DIR}/lib_ccx/" SOURCEFILE)
aux_source_directory ("${PROJECT_SOURCE_DIR}/gpacmp4/" SOURCEFILE)
add_library (ccx ${SOURCEFILE} ccx_dtvcc.h ccx_dtvcc.c ccx_encoders_mcc.c ccx_encoders_mcc.h)
target_link_libraries (ccx ${EXTRA_LIBS})
@@ -67,38 +69,24 @@ if (WITH_HARDSUBX)
pkg_check_modules (AVFORMAT REQUIRED libavformat)
pkg_check_modules (AVUTIL REQUIRED libavutil)
pkg_check_modules (AVCODEC REQUIRED libavcodec)
pkg_check_modules (AVFILTER REQUIRED libavfilter)
pkg_check_modules (SWSCALE REQUIRED libswscale)
set (EXTRA_LIBS ${EXTRA_LIBS} ${AVFORMAT_LIBRARIES})
set (EXTRA_LIBS ${EXTRA_LIBS} ${AVUTIL_LIBRARIES})
set (EXTRA_LIBS ${EXTRA_LIBS} ${AVCODEC_LIBRARIES})
set (EXTRA_LIBS ${EXTRA_LIBS} ${AVFILTER_LIBRARIES})
set (EXTRA_LIBS ${EXTRA_LIBS} ${SWSCALE_LIBRARIES})
set (EXTRA_INCLUDES ${EXTRA_INCLUDES} ${AVFORMAT_INCLUDE_DIRS})
set (EXTRA_INCLUDES ${EXTRA_INCLUDES} ${AVUTIL_INCLUDE_DIRS})
set (EXTRA_INCLUDES ${EXTRA_INCLUDES} ${AVCODEC_INCLUDE_DIRS})
set (EXTRA_INCLUDES ${EXTRA_INCLUDES} ${AVFILTER_INCLUDE_DIRS})
set (EXTRA_INCLUDES ${EXTRA_INCLUDES} ${SWSCALE_INCLUDE_DIRS})
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DENABLE_HARDSUBX")
endif (WITH_HARDSUBX)
if (MINGW OR CYGWIN)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DGPAC_CONFIG_WIN32")
endif (MINGW OR CYGWIN)
if (WITH_RUST)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DENABLE_RUST")
endif (WITH_RUST)
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DGPAC_CONFIG_LINUX")
endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DGPAC_CONFIG_DARWIN")
endif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
file (GLOB HeaderFiles *.h)
file (WRITE ccx.pc "prefix=${CMAKE_INSTALL_PREFIX}\n"
"includedir=\${prefix}/include\n"

View File

@@ -4,7 +4,6 @@ relevant events. */
#include "lib_ccx.h"
#include "ccx_common_option.h"
static int credits_shown = 0;
unsigned long net_activity_gui = 0;
/* Print current progress. For percentage, -1 -> streaming mode */
@@ -16,7 +15,7 @@ void activity_progress(int percentage, int cur_min, int cur_sec)
mprint("Streaming | %02d:%02d\r", cur_min, cur_sec);
else
mprint("%3d%% | %02d:%02d\r", percentage, cur_min, cur_sec);
if (ccx_options.pes_header_to_stdout || ccx_options.debug_mask & CCX_DMT_DVB) //For PES Header dumping and DVB debug traces
if (ccx_options.pes_header_to_stdout || ccx_options.debug_mask & CCX_DMT_DVB) // For PES Header dumping and DVB debug traces
{
mprint("\n");
}
@@ -129,11 +128,7 @@ void activity_report_data_read(void)
void activity_header(void)
{
if (!credits_shown)
{
credits_shown = 1;
mprint("CCExtractor %s, Carlos Fernandez Sanz, Volker Quetschke.\n", VERSION);
mprint("Teletext portions taken from Petr Kutalek's telxcc\n");
mprint("--------------------------------------------------------------------------\n");
}
mprint("CCExtractor %s, Carlos Fernandez Sanz, Volker Quetschke.\n", VERSION);
mprint("Teletext portions taken from Petr Kutalek's telxcc\n");
mprint("--------------------------------------------------------------------------\n");
}

View File

@@ -2,16 +2,16 @@
#define ACTIVITY_H
extern unsigned long net_activity_gui;
void activity_header (void);
void activity_progress (int percentaje, int cur_min, int cur_sec);
void activity_report_version (void);
void activity_input_file_closed (void);
void activity_input_file_open (const char *filename);
void activity_message (const char *fmt, ...);
void activity_video_info (int hor_size,int vert_size,
const char *aspect_ratio, const char *framerate);
void activity_program_number (unsigned program_number);
void activity_header(void);
void activity_progress(int percentaje, int cur_min, int cur_sec);
void activity_report_version(void);
void activity_input_file_closed(void);
void activity_input_file_open(const char *filename);
void activity_message(const char *fmt, ...);
void activity_video_info(int hor_size, int vert_size,
const char *aspect_ratio, const char *framerate);
void activity_program_number(unsigned program_number);
void activity_library_process(enum ccx_common_logging_gui message_type, ...);
void activity_report_data_read (void);
void activity_report_data_read(void);
#endif

View File

@@ -30,28 +30,30 @@
// 10.13 - Undocumented DVR-MS properties
#define DVRMS_PTS "\x2A\xC0\x3C\xFD\xDB\x06\xFA\x4C\x80\x1C\x72\x12\xD3\x87\x45\xE4"
typedef struct {
typedef struct
{
int VideoStreamNumber;
int AudioStreamNumber;
int CaptionStreamNumber;
int CaptionStreamStyle; // 1 = NTSC, 2 = ATSC
int DecodeStreamNumber; // The stream that is chosen to be decoded
int DecodeStreamPTS; // This will be used for the next returned block
int CaptionStreamStyle; // 1 = NTSC, 2 = ATSC
int DecodeStreamNumber; // The stream that is chosen to be decoded
int DecodeStreamPTS; // This will be used for the next returned block
int currDecodeStreamPTS; // Time of the data returned by the function
int prevDecodeStreamPTS; // Previous time
int VideoStreamMS; // See ableve, just for video
int VideoStreamMS; // See ableve, just for video
int currVideoStreamMS;
int prevVideoStreamMS;
int VideoJump; // Remember a jump in the video timeline
int VideoJump; // Remember a jump in the video timeline
} asf_data_stream_properties;
#define STREAMNUM 10
#define STREAMNUM 10
#define PAYEXTNUM 10
typedef struct {
typedef struct
{
// Generic buffer to hold data
unsigned char *parsebuf;
long parsebufsize;
int64_t parsebufsize;
// Header Object variables
int64_t HeaderObjectSize;
int64_t FileSize;
@@ -72,23 +74,23 @@ typedef struct {
uint32_t TotalDataPackets;
int VideoClosedCaptioningFlag;
// Payload data
int PayloadLType; // ASF - Payload Length Type. <>0 for multiple payloads
uint32_t PayloadLength; // ASF - Payload Length
int NumberOfPayloads; // ASF - Number of payloads.
int payloadcur; // local
int PayloadLType; // ASF - Payload Length Type. <>0 for multiple payloads
uint32_t PayloadLength; // ASF - Payload Length
int NumberOfPayloads; // ASF - Number of payloads.
int payloadcur; // local
int PayloadStreamNumber; // ASF
int KeyFrame; // ASF
int KeyFrame; // ASF
uint32_t PayloadMediaNumber; // ASF
// Data Object Loop
uint32_t datapacketcur; // Current packet number
int64_t dobjectread; // Bytes read in Data Object
uint32_t datapacketcur; // Current packet number
int64_t dobjectread; // Bytes read in Data Object
// Payload parsing information
int MultiplePayloads; // ASF
int PacketLType; // ASF
int ReplicatedLType; // ASF
int OffsetMediaLType; // ASF
int MediaNumberLType; // ASF
int StreamNumberLType; // ASF
int MultiplePayloads; // ASF
int PacketLType; // ASF
int ReplicatedLType; // ASF
int OffsetMediaLType; // ASF
int MediaNumberLType; // ASF
int StreamNumberLType; // ASF
uint32_t PacketLength;
uint32_t PaddingLength;
} asf_data;

View File

@@ -42,14 +42,14 @@ char *gui_data_string(void *val)
{
static char sbuf[40];
sprintf(sbuf, "%08lX-%04X-%04X-",
(long)*((uint32_t *)((char *)val + 0)),
(int)*((uint16_t *)((char *)val + 4)),
(int)*((uint16_t *)((char *)val + 6)));
snprintf(sbuf, sizeof(sbuf), "%08lX-%04X-%04X-",
(long)*((uint32_t *)((char *)val + 0)),
(int)*((uint16_t *)((char *)val + 4)),
(int)*((uint16_t *)((char *)val + 6)));
for (int ii = 0; ii < 2; ii++)
sprintf(sbuf + 19 + ii * 2, "%02X-", *((unsigned char *)val + 8 + ii));
snprintf(sbuf + 19 + ii * 2, sizeof(sbuf) - 19 - ii * 2, "%02X-", *((unsigned char *)val + 8 + ii));
for (int ii = 0; ii < 6; ii++)
sprintf(sbuf + 24 + ii * 2, "%02X", *((unsigned char *)val + 10 + ii));
snprintf(sbuf + 24 + ii * 2, sizeof(sbuf) - 24 - ii * 2, "%02X", *((unsigned char *)val + 10 + ii));
return sbuf;
}
@@ -150,6 +150,10 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
.StreamNumberLType = 0,
.PacketLength = 0,
.PaddingLength = 0};
// Check for allocation failure
if (!asf_data_container.parsebuf)
fatal(EXIT_NOT_ENOUGH_MEMORY, "In asf_getmoredata: Out of memory allocating initial parse buffer.");
// Initialize the Payload Extension System
for (int stream = 0; stream < STREAMNUM; stream++)
{
@@ -185,9 +189,13 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
if (asf_data_container.HeaderObjectSize > asf_data_container.parsebufsize)
{
asf_data_container.parsebuf = (unsigned char *)realloc(asf_data_container.parsebuf, (size_t)asf_data_container.HeaderObjectSize);
if (!asf_data_container.parsebuf)
unsigned char *tmp = (unsigned char *)realloc(asf_data_container.parsebuf, (size_t)asf_data_container.HeaderObjectSize);
if (!tmp)
{
free(asf_data_container.parsebuf);
fatal(EXIT_NOT_ENOUGH_MEMORY, "In asf_getmoredata: Out of memory requesting buffer for data container.");
}
asf_data_container.parsebuf = tmp;
asf_data_container.parsebufsize = (long)asf_data_container.HeaderObjectSize;
}
@@ -509,14 +517,14 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
if (asf_data_container.StreamProperties.CaptionStreamNumber > 0 && (asf_data_container.StreamProperties.CaptionStreamStyle == 1 ||
(asf_data_container.StreamProperties.CaptionStreamStyle == 2 && ccx_options.wtvconvertfix)))
{
//if (debug_parse)
// if (debug_parse)
mprint("\nNTSC captions in stream #%d\n\n", asf_data_container.StreamProperties.CaptionStreamNumber);
data->bufferdatatype = CCX_RAW;
asf_data_container.StreamProperties.DecodeStreamNumber = asf_data_container.StreamProperties.CaptionStreamNumber;
}
else if (asf_data_container.StreamProperties.CaptionStreamNumber > 0 && asf_data_container.StreamProperties.CaptionStreamStyle == 2)
{
//if (debug_parse)
// if (debug_parse)
mprint("\nATSC captions (probably) in stream #%d - Decode the video stream #%d instead\n\n",
asf_data_container.StreamProperties.CaptionStreamNumber, asf_data_container.StreamProperties.VideoStreamNumber);
asf_data_container.StreamProperties.DecodeStreamNumber = asf_data_container.StreamProperties.VideoStreamNumber;
@@ -524,7 +532,7 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
else
{
asf_data_container.StreamProperties.DecodeStreamNumber = asf_data_container.StreamProperties.VideoStreamNumber;
//if (debug_parse)
// if (debug_parse)
mprint("\nAssume CC info in video stream #%d (No caption stream found)\n\n",
asf_data_container.StreamProperties.DecodeStreamNumber);
}
@@ -561,7 +569,7 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
dbg_print(CCX_DMT_PARSE, "Number of data packets: %ld\n", (long)asf_data_container.TotalDataPackets);
reentry = 0; // Make sure we read the Data Packet Headers
} // End of if (firstcall)
} // End of if (firstcall)
firstcall = 0;
// Start loop over Data Packets
@@ -751,9 +759,13 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
if ((long)replicated_length > asf_data_container.parsebufsize)
{
asf_data_container.parsebuf = (unsigned char *)realloc(asf_data_container.parsebuf, replicated_length);
if (!asf_data_container.parsebuf)
unsigned char *tmp = (unsigned char *)realloc(asf_data_container.parsebuf, replicated_length);
if (!tmp)
{
free(asf_data_container.parsebuf);
fatal(EXIT_NOT_ENOUGH_MEMORY, "In asf_getmoredata: Not enough memory for buffer, unable to continue.\n");
}
asf_data_container.parsebuf = tmp;
asf_data_container.parsebufsize = replicated_length;
}
result = buffered_read(ctx->demux_ctx, asf_data_container.parsebuf, (long)replicated_length);
@@ -768,7 +780,7 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
// Parse Replicated data
unsigned char *replicate_position = asf_data_container.parsebuf;
int media_object_size = 0;
int presentation_time_millis = 0; //Payload ms time stamp
int presentation_time_millis = 0; // Payload ms time stamp
int extsize = 0;
// int32_t dwVersion = 0;
// int32_t unknown = 0;
@@ -797,7 +809,7 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
extsize = asf_data_container.PayloadExtSize[asf_data_container.PayloadStreamNumber][i];
}
replicate_position += extsize;
//printf("%2d. Ext. System - size: %d\n", i, extsize);
// printf("%2d. Ext. System - size: %d\n", i, extsize);
}
if (asf_data_container.PayloadExtPTSEntry[asf_data_container.PayloadStreamNumber] > 0)
{
@@ -806,7 +818,7 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
rtStart = *((int64_t *)(replicate_position + 8));
rtEnd = *((int64_t *)(replicate_position + 16));
//printf("dwVersion: %d unknown: 0x%04X\n", dwVersion, unknown);
// printf("dwVersion: %d unknown: 0x%04X\n", dwVersion, unknown);
}
// Avoid problems with unset PTS times
@@ -1029,7 +1041,7 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
ctx->demux_ctx->past += result;
// Don not set end_of_file (although it is true) as this would
// produce an premature end error.
//end_of_file=1;
// end_of_file=1;
// parsebuf is freed automatically when the program closes.
}

View File

@@ -48,6 +48,7 @@ struct avc_ctx *init_avc(void)
ctx->cc_databufsize = 1024;
ctx->cc_buffer_saved = CCX_TRUE; // Was the CC buffer saved after it was last updated?
ctx->is_hevc = 0;
ctx->got_seq_para = 0;
ctx->nal_ref_idc = 0;
ctx->seq_parameter_set_id = 0;
@@ -87,16 +88,43 @@ struct avc_ctx *init_avc(void)
return ctx;
}
// HEVC NAL unit types for SEI messages
#define HEVC_NAL_PREFIX_SEI 39
#define HEVC_NAL_SUFFIX_SEI 40
#define HEVC_NAL_VPS 32
#define HEVC_NAL_SPS 33
#define HEVC_NAL_PPS 34
void do_NAL(struct encoder_ctx *enc_ctx, struct lib_cc_decode *dec_ctx, unsigned char *NAL_start, LLONG NAL_length, struct cc_subtitle *sub)
{
unsigned char *NAL_stop;
enum ccx_avc_nal_types nal_unit_type = *NAL_start & 0x1F;
int nal_unit_type;
int nal_header_size;
unsigned char *payload_start;
// Determine if this is HEVC or H.264 based on NAL header
// H.264 NAL header: 1 byte, type in bits [4:0]
// HEVC NAL header: 2 bytes, type in bits [6:1] of first byte
if (dec_ctx->avc_ctx->is_hevc)
{
// HEVC: NAL type is in bits [6:1] of byte 0
nal_unit_type = (NAL_start[0] >> 1) & 0x3F;
nal_header_size = 2;
}
else
{
// H.264: NAL type is in bits [4:0] of byte 0
nal_unit_type = NAL_start[0] & 0x1F;
nal_header_size = 1;
}
NAL_stop = NAL_length + NAL_start;
NAL_stop = remove_03emu(NAL_start + 1, NAL_stop); // Add +1 to NAL_stop for TS, without it for MP4. Still don't know why
NAL_stop = remove_03emu(NAL_start + nal_header_size, NAL_stop);
payload_start = NAL_start + nal_header_size;
dvprint("BEGIN NAL unit type: %d length %d ref_idc: %d - Buffered captions before: %d\n",
nal_unit_type, NAL_stop - NAL_start - 1, dec_ctx->avc_ctx->nal_ref_idc, !dec_ctx->avc_ctx->cc_buffer_saved);
dvprint("BEGIN NAL unit type: %d length %d ref_idc: %d - Buffered captions before: %d (HEVC: %d)\n",
nal_unit_type, NAL_stop - NAL_start - nal_header_size, dec_ctx->avc_ctx->nal_ref_idc,
!dec_ctx->avc_ctx->cc_buffer_saved, dec_ctx->avc_ctx->is_hevc);
if (NAL_stop == NULL) // remove_03emu failed.
{
@@ -104,51 +132,76 @@ void do_NAL(struct encoder_ctx *enc_ctx, struct lib_cc_decode *dec_ctx, unsigned
return;
}
if (nal_unit_type == CCX_NAL_TYPE_ACCESS_UNIT_DELIMITER_9)
if (dec_ctx->avc_ctx->is_hevc)
{
// Found Access Unit Delimiter
// HEVC NAL unit processing
if (nal_unit_type == HEVC_NAL_VPS || nal_unit_type == HEVC_NAL_SPS || nal_unit_type == HEVC_NAL_PPS)
{
// Found HEVC parameter set - mark as having sequence params
// We don't parse HEVC SPS fully, but we need to enable SEI processing
dec_ctx->avc_ctx->got_seq_para = 1;
}
else if (nal_unit_type == HEVC_NAL_PREFIX_SEI || nal_unit_type == HEVC_NAL_SUFFIX_SEI)
{
// Found HEVC SEI (used for subtitles)
// SEI payload format is similar to H.264
sei_rbsp(dec_ctx->avc_ctx, payload_start, NAL_stop);
}
}
else if (nal_unit_type == CCX_NAL_TYPE_SEQUENCE_PARAMETER_SET_7)
else
{
// Found sequence parameter set
// We need this to parse NAL type 1 (CCX_NAL_TYPE_CODED_SLICE_NON_IDR_PICTURE_1)
dec_ctx->avc_ctx->num_nal_unit_type_7++;
seq_parameter_set_rbsp(dec_ctx->avc_ctx, NAL_start + 1, NAL_stop);
dec_ctx->avc_ctx->got_seq_para = 1;
}
else if (dec_ctx->avc_ctx->got_seq_para && (nal_unit_type == CCX_NAL_TYPE_CODED_SLICE_NON_IDR_PICTURE_1 ||
nal_unit_type == CCX_NAL_TYPE_CODED_SLICE_IDR_PICTURE)) // Only if nal_unit_type=1
{
// Found coded slice of a non-IDR picture
// We only need the slice header data, no need to implement
// slice_layer_without_partitioning_rbsp( );
slice_header(enc_ctx, dec_ctx, NAL_start + 1, NAL_stop, nal_unit_type, sub);
}
else if (dec_ctx->avc_ctx->got_seq_para && nal_unit_type == CCX_NAL_TYPE_SEI)
{
// Found SEI (used for subtitles)
//set_fts(ctx->timing); // FIXME - check this!!!
sei_rbsp(dec_ctx->avc_ctx, NAL_start + 1, NAL_stop);
}
else if (dec_ctx->avc_ctx->got_seq_para && nal_unit_type == CCX_NAL_TYPE_PICTURE_PARAMETER_SET)
{
// Found Picture parameter set
// H.264 NAL unit processing (original code)
if (nal_unit_type == CCX_NAL_TYPE_ACCESS_UNIT_DELIMITER_9)
{
// Found Access Unit Delimiter
}
else if (nal_unit_type == CCX_NAL_TYPE_SEQUENCE_PARAMETER_SET_7)
{
// Found sequence parameter set
// We need this to parse NAL type 1 (CCX_NAL_TYPE_CODED_SLICE_NON_IDR_PICTURE_1)
dec_ctx->avc_ctx->num_nal_unit_type_7++;
seq_parameter_set_rbsp(dec_ctx->avc_ctx, payload_start, NAL_stop);
dec_ctx->avc_ctx->got_seq_para = 1;
}
else if (dec_ctx->avc_ctx->got_seq_para && (nal_unit_type == CCX_NAL_TYPE_CODED_SLICE_NON_IDR_PICTURE_1 ||
nal_unit_type == CCX_NAL_TYPE_CODED_SLICE_IDR_PICTURE))
{
// Found coded slice of a non-IDR picture
// We only need the slice header data
slice_header(enc_ctx, dec_ctx, payload_start, NAL_stop, nal_unit_type, sub);
}
else if (dec_ctx->avc_ctx->got_seq_para && nal_unit_type == CCX_NAL_TYPE_SEI)
{
// Found SEI (used for subtitles)
sei_rbsp(dec_ctx->avc_ctx, payload_start, NAL_stop);
}
else if (dec_ctx->avc_ctx->got_seq_para && nal_unit_type == CCX_NAL_TYPE_PICTURE_PARAMETER_SET)
{
// Found Picture parameter set
}
}
if (temp_debug)
{
int len = NAL_stop - (NAL_start + 1);
int len = NAL_stop - payload_start;
dbg_print(CCX_DMT_VIDES, "\n After decoding, the actual thing was (length =%d)\n", len);
dump(CCX_DMT_VIDES, NAL_start + 1, len > 160 ? 160 : len, 0, 0);
dump(CCX_DMT_VIDES, payload_start, len > 160 ? 160 : len, 0, 0);
}
dvprint("END NAL unit type: %d length %d ref_idc: %d - Buffered captions after: %d\n",
nal_unit_type, NAL_stop - NAL_start - 1, dec_ctx->avc_ctx->nal_ref_idc, !dec_ctx->avc_ctx->cc_buffer_saved);
nal_unit_type, NAL_stop - NAL_start - nal_header_size, dec_ctx->avc_ctx->nal_ref_idc, !dec_ctx->avc_ctx->cc_buffer_saved);
}
// Process inbuf bytes in buffer holding and AVC (H.264) video stream.
// The number of processed bytes is returned.
#ifndef DISABLE_RUST
size_t ccxr_process_avc(struct encoder_ctx *enc_ctx, struct lib_cc_decode *dec_ctx, unsigned char *avcbuf, size_t avcbuflen, struct cc_subtitle *sub);
#endif
size_t process_avc(struct encoder_ctx *enc_ctx, struct lib_cc_decode *dec_ctx, unsigned char *avcbuf, size_t avcbuflen, struct cc_subtitle *sub)
{
#ifndef DISABLE_RUST
return ccxr_process_avc(enc_ctx, dec_ctx, avcbuf, avcbuflen, sub);
#else
unsigned char *buffer_position = avcbuf;
unsigned char *NAL_start;
unsigned char *NAL_stop;
@@ -250,6 +303,7 @@ size_t process_avc(struct encoder_ctx *enc_ctx, struct lib_cc_decode *dec_ctx, u
}
return avcbuflen;
#endif
}
#define ZEROBYTES_SHORTSTARTCODE 2
@@ -266,16 +320,16 @@ int EBSPtoRBSP(unsigned char *streamBuffer, int end_bytepos, int begin_bytepos)
j = begin_bytepos;
for (i = begin_bytepos; i < end_bytepos; ++i)
{ //starting from begin_bytepos to avoid header information
//in NAL unit, 0x000000, 0x000001 or 0x000002 shall not occur at any byte-aligned position
{ // starting from begin_bytepos to avoid header information
// in NAL unit, 0x000000, 0x000001 or 0x000002 shall not occur at any byte-aligned position
if (count == ZEROBYTES_SHORTSTARTCODE && streamBuffer[i] < 0x03)
return -1;
if (count == ZEROBYTES_SHORTSTARTCODE && streamBuffer[i] == 0x03)
{
//check the 4th byte after 0x000003, except when cabac_zero_word is used, in which case the last three bytes of this NAL unit must be 0x000003
// check the 4th byte after 0x000003, except when cabac_zero_word is used, in which case the last three bytes of this NAL unit must be 0x000003
if ((i < end_bytepos - 1) && (streamBuffer[i + 1] > 0x03))
return -1;
//if cabac_zero_word is used, the final byte of this NAL unit(0x03) is discarded, and the last two bytes of RBSP must be 0x0000
// if cabac_zero_word is used, the final byte of this NAL unit(0x03) is discarded, and the last two bytes of RBSP must be 0x0000
if (i == end_bytepos - 1)
return j;
@@ -301,7 +355,7 @@ u32 avc_remove_emulation_bytes(const unsigned char *buffer_src, unsigned char *b
unsigned char *remove_03emu(unsigned char *from, unsigned char *to)
{
int num = to - from;
int newsize = EBSPtoRBSP(from, num, 0); //TODO: Do something if newsize == -1 (broken NAL)
int newsize = EBSPtoRBSP(from, num, 0); // TODO: Do something if newsize == -1 (broken NAL)
if (newsize == -1)
return NULL;
return from + newsize;
@@ -503,9 +557,13 @@ void user_data_registered_itu_t_t35(struct avc_ctx *ctx, unsigned char *userbuf,
// Save the data and process once we know the sequence number
if (((ctx->cc_count + local_cc_count) * 3) + 1 > ctx->cc_databufsize)
{
ctx->cc_data = (unsigned char *)realloc(ctx->cc_data, (size_t)((ctx->cc_count + local_cc_count) * 6) + 1);
if (!ctx->cc_data)
unsigned char *tmp = (unsigned char *)realloc(ctx->cc_data, (size_t)((ctx->cc_count + local_cc_count) * 6) + 1);
if (!tmp)
{
free(ctx->cc_data);
fatal(EXIT_NOT_ENOUGH_MEMORY, "In user_data_registered_itu_t_t35: Out of memory to allocate buffer for CC data.");
}
ctx->cc_data = tmp;
ctx->cc_databufsize = (long)((ctx->cc_count + local_cc_count) * 6) + 1;
}
// Copy new cc data into cc_data
@@ -574,15 +632,19 @@ void user_data_registered_itu_t_t35(struct avc_ctx *ctx, unsigned char *userbuf,
// Save the data and process once we know the sequence number
if ((((local_cc_count + ctx->cc_count) * 3) + 1) > ctx->cc_databufsize)
{
ctx->cc_data = (unsigned char *)realloc(ctx->cc_data, (size_t)(((local_cc_count + ctx->cc_count) * 6) + 1));
if (!ctx->cc_data)
unsigned char *tmp = (unsigned char *)realloc(ctx->cc_data, (size_t)(((local_cc_count + ctx->cc_count) * 6) + 1));
if (!tmp)
{
free(ctx->cc_data);
fatal(EXIT_NOT_ENOUGH_MEMORY, "In user_data_registered_itu_t_t35: Not enough memory trying to allocate buffer for CC data.");
}
ctx->cc_data = tmp;
ctx->cc_databufsize = (long)(((local_cc_count + ctx->cc_count) * 6) + 1);
}
// Copy new cc data into cc_data - replace command below.
copy_ccdata_to_buffer(ctx, (char *)cc_tmp_data, local_cc_count);
//dump(tbuf,user_data_len-1,0);
// dump(tbuf,user_data_len-1,0);
break;
default:
mprint("Not a supported user data SEI\n");
@@ -833,8 +895,8 @@ void seq_parameter_set_rbsp(struct avc_ctx *ctx, unsigned char *seqbuf, unsigned
if (tmp)
{
dvprint("nal_hrd. Not implemented for now. Hopefully not needed. Skipping rest of NAL\n");
//printf("Boom nal_hrd\n");
// exit(1);
// printf("Boom nal_hrd\n");
// exit(1);
ctx->num_nal_hrd++;
return;
}
@@ -862,7 +924,7 @@ void seq_parameter_set_rbsp(struct avc_ctx *ctx, unsigned char *seqbuf, unsigned
// it was not set in the testfile. Ignore the rest here, it's
// currently not needed.
}
//exit(1);
// exit(1);
}
/**
@@ -892,6 +954,15 @@ void slice_header(struct encoder_ctx *enc_ctx, struct lib_cc_decode *dec_ctx, un
dvprint("first_mb_in_slice= % 4lld (%#llX)\n", tmp, tmp);
slice_type = read_exp_golomb_unsigned(&q1);
dvprint("slice_type= % 4llX\n", slice_type);
// Validate slice_type to prevent buffer overflow in slice_types[] array
// Valid H.264 slice_type values are 0-9 (H.264 spec Table 7-6)
if (slice_type >= 10)
{
mprint("Invalid slice_type %lld in slice header, skipping.\n", slice_type);
return;
}
tmp = read_exp_golomb_unsigned(&q1);
dvprint("pic_parameter_set_id= % 4lld (%#llX)\n", tmp, tmp);
@@ -924,7 +995,7 @@ void slice_header(struct encoder_ctx *enc_ctx, struct lib_cc_decode *dec_ctx, un
{
tmp = read_exp_golomb_unsigned(&q1);
dvprint("idr_pic_id= % 4lld (%#llX)\n", tmp, tmp);
//TODO
// TODO
}
if (dec_ctx->avc_ctx->pic_order_cnt_type == 0)
{
@@ -936,7 +1007,7 @@ void slice_header(struct encoder_ctx *enc_ctx, struct lib_cc_decode *dec_ctx, un
fatal(CCX_COMMON_EXIT_BUG_BUG, "In slice_header: AVC: ctx->avc_ctx->pic_order_cnt_type == 1 not yet supported.");
}
//Ignore slice with same pic order or pts
// Ignore slice with same pic order or pts
if (ccx_options.usepicorder)
{
if (dec_ctx->avc_ctx->last_pic_order_cnt_lsb == pic_order_cnt_lsb)
@@ -1031,7 +1102,12 @@ void slice_header(struct encoder_ctx *enc_ctx, struct lib_cc_decode *dec_ctx, un
}
// if slices are buffered - flush
if (isref)
// For I/P-only streams (like HDHomeRun recordings), flushing on every
// reference frame defeats reordering since all frames are reference frames.
// Only flush and reset on IDR frames (nal_unit_type==5), not P-frames.
// This allows P-frames to accumulate in the buffer and be sorted by PTS.
int is_idr = (nal_unit_type == CCX_NAL_TYPE_CODED_SLICE_IDR_PICTURE);
if (isref && is_idr)
{
dvprint("\nReference pic! [%s]\n", slice_types[slice_type]);
dbg_print(CCX_DMT_TIME, "\nReference pic! [%s] maxrefcnt: %3d\n",
@@ -1126,8 +1202,32 @@ void slice_header(struct encoder_ctx *enc_ctx, struct lib_cc_decode *dec_ctx, un
if (abs(current_index) >= MAXBFRAMES)
{
// Probably a jump in the timeline. Warn and handle gracefully.
mprint("\nFound large gap(%d) in PTS! Trying to recover ...\n", current_index);
// Large PTS gap detected. This can happen with certain encoders
// (like HDHomeRun) that produce streams where PTS jumps are common.
// Instead of just resetting current_index to 0 (which causes captions
// to pile up at the same buffer slot and become garbled), we need to:
// 1. Flush any buffered captions
// 2. Reset the reference PTS to the current PTS
// 3. Set current_index to 0 for a fresh start
// This ensures subsequent frames use the new reference point.
dbg_print(CCX_DMT_VERBOSE, "\nLarge PTS gap(%d) detected, flushing buffer and resetting reference.\n", current_index);
// Flush any buffered captions before resetting
if (dec_ctx->has_ccdata_buffered)
{
process_hdcc(enc_ctx, dec_ctx, sub);
}
// Reset the reference point to current PTS
dec_ctx->avc_ctx->currefpts = dec_ctx->timing->current_pts;
// Reset tracking variables for the new reference
dec_ctx->avc_ctx->lastmaxidx = -1;
dec_ctx->avc_ctx->maxidx = 0;
dec_ctx->avc_ctx->lastminidx = 10000;
dec_ctx->avc_ctx->minidx = 10000;
// Start with index 0 relative to the new reference
current_index = 0;
}

View File

@@ -1,15 +1,15 @@
#ifndef AVC_FUNCTION_H
#define AVC_FUNCTION_H
struct avc_ctx
{
unsigned char cc_count;
// buffer to hold cc data
unsigned char *cc_data;
long cc_databufsize;
int64_t cc_databufsize;
int cc_buffer_saved; // Was the CC buffer saved after it was last updated?
int is_hevc; // Flag to indicate HEVC (H.265) mode vs H.264
int got_seq_para;
unsigned nal_ref_idc;
LLONG seq_parameter_set_id;
@@ -19,11 +19,11 @@ struct avc_ctx
int frame_mbs_only_flag;
// Use and throw stats for debug, remove this ugliness soon
long num_nal_unit_type_7;
long num_vcl_hrd;
long num_nal_hrd;
long num_jump_in_frames;
long num_unexpected_sei_length;
int64_t num_nal_unit_type_7;
int64_t num_vcl_hrd;
int64_t num_nal_hrd;
int64_t num_jump_in_frames;
int64_t num_unexpected_sei_length;
int ccblocks_in_avc_total;
int ccblocks_in_avc_lost;
@@ -50,6 +50,6 @@ struct avc_ctx
struct avc_ctx *init_avc(void);
void dinit_avc(struct avc_ctx **ctx);
void do_NAL (struct encoder_ctx *enc_ctx, struct lib_cc_decode *ctx, unsigned char *NAL_start, LLONG NAL_length, struct cc_subtitle *sub);
void do_NAL(struct encoder_ctx *enc_ctx, struct lib_cc_decode *ctx, unsigned char *NAL_start, LLONG NAL_length, struct cc_subtitle *sub);
size_t process_avc(struct encoder_ctx *enc_ctx, struct lib_cc_decode *ctx, unsigned char *avcbuf, size_t avcbuflen, struct cc_subtitle *sub);
#endif

View File

@@ -3,6 +3,19 @@
// Hold functions to read streams on a bit or byte oriented basis
// plus some data related helper functions.
extern uint64_t ccxr_next_bits(struct bitstream *bs, uint32_t bnum);
extern uint64_t ccxr_read_bits(struct bitstream *bs, uint32_t bnum);
extern int ccxr_skip_bits(struct bitstream *bs, uint32_t bnum);
extern int ccxr_is_byte_aligned(struct bitstream *bs);
extern void ccxr_make_byte_aligned(struct bitstream *bs);
extern const uint8_t *ccxr_next_bytes(struct bitstream *bs, size_t bynum);
extern const uint8_t *ccxr_read_bytes(struct bitstream *bs, size_t bynum);
extern uint64_t ccxr_read_exp_golomb_unsigned(struct bitstream *bs);
extern int64_t ccxr_read_exp_golomb(struct bitstream *bs);
extern uint8_t ccxr_reverse8(uint8_t data);
extern uint64_t ccxr_bitstream_get_num(struct bitstream *bs, unsigned bytes, int advance);
extern int64_t ccxr_read_int(struct bitstream *bs, unsigned bnum);
// Guidelines for all bitsream functions:
// * No function shall advance the pointer past the end marker
// * If bitstream.bitsleft < 0 do not attempt any read access,
@@ -35,88 +48,14 @@ int init_bitstream(struct bitstream *bstr, unsigned char *start, unsigned char *
// there are not enough bits left in the bitstream.
uint64_t next_bits(struct bitstream *bstr, unsigned bnum)
{
uint64_t res = 0;
if (bnum > 64)
fatal(CCX_COMMON_EXIT_BUG_BUG, "In next_bits: Argument is greater than the maximum bit number i.e. 64: %u!", bnum);
// Sanity check
if (bstr->end - bstr->pos < 0)
fatal(CCX_COMMON_EXIT_BUG_BUG, "In next_bits: Bitstream can not have negative length!");
// Keep a negative bitstream.bitsleft, but correct it.
if (bstr->bitsleft <= 0)
{
bstr->bitsleft -= bnum;
return 0;
}
// Calculate the remaining number of bits in bitstream after reading.
bstr->bitsleft = 0LL + (bstr->end - bstr->pos - 1) * 8 + bstr->bpos - bnum;
if (bstr->bitsleft < 0)
return 0;
// Special case for reading zero bits. Return zero
if (bnum == 0)
return 0;
int vbit = bstr->bpos;
unsigned char *vpos = bstr->pos;
if (vbit < 1 || vbit > 8)
{
fatal(CCX_COMMON_EXIT_BUG_BUG, "In next_bits: Illegal bit position value %d!", vbit);
}
while (1)
{
if (vpos >= bstr->end)
{
// We should not get here ...
fatal(CCX_COMMON_EXIT_BUG_BUG, "In next_bits: Trying to read after end of data ...");
}
res |= (*vpos & (0x01 << (vbit - 1)) ? 1 : 0);
vbit--;
bnum--;
if (vbit == 0)
{
vpos++;
vbit = 8;
}
if (bnum)
{
res <<= 1;
}
else
break;
}
// Remember the bitstream position
bstr->_i_bpos = vbit;
bstr->_i_pos = vpos;
return res;
return ccxr_next_bits(bstr, bnum);
}
// Read bnum bits from bitstream bstr with the most significant
// bit read first. A 64 bit unsigned integer is returned.
uint64_t read_bits(struct bitstream *bstr, unsigned bnum)
{
uint64_t res = next_bits(bstr, bnum);
// Special case for reading zero bits. Also abort when not enough
// bits are left. Return zero
if (bnum == 0 || bstr->bitsleft < 0)
return 0;
// Advance the bitstream
bstr->bpos = bstr->_i_bpos;
bstr->pos = bstr->_i_pos;
return res;
return ccxr_read_bits(bstr, bnum);
}
// This function will advance the bitstream by bnum bits, if possible.
@@ -124,35 +63,7 @@ uint64_t read_bits(struct bitstream *bstr, unsigned bnum)
// Return TRUE when successful, otherwise FALSE
int skip_bits(struct bitstream *bstr, unsigned bnum)
{
// Sanity check
if (bstr->end - bstr->pos < 0)
fatal(CCX_COMMON_EXIT_BUG_BUG, "In skip_bits: bitstream length cannot be negative!");
// Keep a negative bstr->bitsleft, but correct it.
if (bstr->bitsleft < 0)
{
bstr->bitsleft -= bnum;
return 0;
}
// Calculate the remaining number of bits in bitstream after reading.
bstr->bitsleft = 0LL + (bstr->end - bstr->pos - 1) * 8 + bstr->bpos - bnum;
if (bstr->bitsleft < 0)
return 0;
// Special case for reading zero bits. Return zero
if (bnum == 0)
return 1;
bstr->bpos -= bnum % 8;
bstr->pos += bnum / 8;
if (bstr->bpos < 1)
{
bstr->bpos += 8;
bstr->pos += 1;
}
return 1;
return ccxr_skip_bits(bstr, bnum);
}
// Return TRUE if the current position in the bitstream is on a byte
@@ -160,54 +71,13 @@ int skip_bits(struct bitstream *bstr, unsigned bnum)
// a byte, otherwise return FALSE
int is_byte_aligned(struct bitstream *bstr)
{
// Sanity check
if (bstr->end - bstr->pos < 0)
fatal(CCX_COMMON_EXIT_BUG_BUG, "In is_byte_aligned: bitstream length can not be negative!");
int vbit = bstr->bpos;
if (vbit == 0 || vbit > 8)
{
fatal(CCX_COMMON_EXIT_BUG_BUG, "In is_byte_aligned: Illegal bit position value %d!\n", vbit);
}
if (vbit == 8)
return 1;
else
return 0;
return ccxr_is_byte_aligned(bstr);
}
// Move bitstream to next byte border. Adjust bitsleft.
void make_byte_aligned(struct bitstream *bstr)
{
// Sanity check
if (bstr->end - bstr->pos < 0)
fatal(CCX_COMMON_EXIT_BUG_BUG, "In make_byte_aligned: bitstream length can not be negative!");
int vbit = bstr->bpos;
if (vbit == 0 || vbit > 8)
{
fatal(CCX_COMMON_EXIT_BUG_BUG, "In make_byte_aligned: Illegal bit position value %d!\n", vbit);
}
// Keep a negative bstr->bitsleft, but correct it.
if (bstr->bitsleft < 0)
{
// Pay attention to the bit alignment
bstr->bitsleft = (bstr->bitsleft - 7) / 8 * 8;
return;
}
if (bstr->bpos != 8)
{
bstr->bpos = 8;
bstr->pos += 1;
}
// Reset, in case a next_???() function was used before
bstr->bitsleft = 0LL + 8 * (bstr->end - bstr->pos - 1) + bstr->bpos;
return;
ccxr_make_byte_aligned(bstr);
}
// Return pointer to first of bynum bytes from the bitstream if the
@@ -217,27 +87,7 @@ void make_byte_aligned(struct bitstream *bstr)
// This function does not advance the bitstream pointer.
unsigned char *next_bytes(struct bitstream *bstr, unsigned bynum)
{
// Sanity check
if (bstr->end - bstr->pos < 0)
fatal(CCX_COMMON_EXIT_BUG_BUG, "In next_bytes: bitstream length can not be negative!");
// Keep a negative bstr->bitsleft, but correct it.
if (bstr->bitsleft < 0)
{
bstr->bitsleft -= bynum * 8;
return NULL;
}
bstr->bitsleft = 0LL + (bstr->end - bstr->pos - 1) * 8 + bstr->bpos - bynum * 8;
if (!is_byte_aligned(bstr) || bstr->bitsleft < 0 || bynum < 1)
return NULL;
// Remember the bitstream position
bstr->_i_bpos = 8;
bstr->_i_pos = bstr->pos + bynum;
return bstr->pos;
return (unsigned char *)ccxr_next_bytes(bstr, bynum);
}
// Return pointer to first of bynum bytes from the bitstream if the
@@ -247,15 +97,7 @@ unsigned char *next_bytes(struct bitstream *bstr, unsigned bynum)
// This function does advance the bitstream pointer.
unsigned char *read_bytes(struct bitstream *bstr, unsigned bynum)
{
unsigned char *res = next_bytes(bstr, bynum);
// Advance the bitstream when a read was possible
if (res)
{
bstr->bpos = bstr->_i_bpos;
bstr->pos = bstr->_i_pos;
}
return res;
return (unsigned char *)ccxr_read_bytes(bstr, bynum);
}
// Return an integer number with "bytes" precision from the current
@@ -266,65 +108,19 @@ unsigned char *read_bytes(struct bitstream *bstr, unsigned bynum)
// little-endian and big-endian CPUs.
uint64_t bitstream_get_num(struct bitstream *bstr, unsigned bytes, int advance)
{
void *bpos;
uint64_t rval = 0;
if (advance)
bpos = read_bytes(bstr, bytes);
else
bpos = next_bytes(bstr, bytes);
if (!bpos)
return 0;
switch (bytes)
{
case 1:
case 2:
case 4:
case 8:
break;
default:
fatal(CCX_COMMON_EXIT_BUG_BUG, "In bitstream_get_num: Illegal precision value [%u]!",
bytes);
break;
}
for (unsigned i = 0; i < bytes; i++)
{
unsigned char *ucpos = ((unsigned char *)bpos) + bytes - i - 1; // Read backwards
unsigned char uc = *ucpos;
rval = (rval << 8) + uc;
}
return rval;
return ccxr_bitstream_get_num(bstr, bytes, advance);
}
// Read unsigned Exp-Golomb code from bitstream
uint64_t read_exp_golomb_unsigned(struct bitstream *bstr)
{
uint64_t res = 0;
int zeros = 0;
while (!read_bits(bstr, 1) && bstr->bitsleft >= 0)
zeros++;
res = (0x01 << zeros) - 1 + read_bits(bstr, zeros);
return res;
return ccxr_read_exp_golomb_unsigned(bstr);
}
// Read signed Exp-Golomb code from bitstream
int64_t read_exp_golomb(struct bitstream *bstr)
{
int64_t res = 0;
res = read_exp_golomb_unsigned(bstr);
// The following function might truncate when res+1 overflows
//res = (res+1)/2 * (res % 2 ? 1 : -1);
// Use this:
res = (res / 2 + (res % 2 ? 1 : 0)) * (res % 2 ? 1 : -1);
return res;
return ccxr_read_exp_golomb(bstr);
}
// Read unsigned integer with bnum bits length. Basically an
@@ -337,25 +133,11 @@ uint64_t read_int_unsigned(struct bitstream *bstr, unsigned bnum)
// Read signed integer with bnum bits length.
int64_t read_int(struct bitstream *bstr, unsigned bnum)
{
uint64_t res = read_bits(bstr, bnum);
// Special case for reading zero bits. Return zero
if (bnum == 0)
return 0;
return (0xFFFFFFFFFFFFFFFFULL << bnum) | res;
return ccxr_read_int(bstr, bnum);
}
// Return the value with the bit order reversed.
uint8_t reverse8(uint8_t data)
{
uint8_t res = 0;
for (int k = 0; k < 8; k++)
{
res <<= 1;
res |= (data & (0x01 << k) ? 1 : 0);
}
return res;
return ccxr_reverse8(data);
}

View File

@@ -1,7 +1,6 @@
#ifndef _BITSTREAM_
#define _BITSTREAM_
// The structure holds the current position in the bitstream.
// pos points to the current byte position and bpos counts the
// bits left unread at the current byte pos. No bit read means
@@ -27,26 +26,25 @@ struct bitstream
int _i_bpos;
};
#define read_u8(bstream) (uint8_t)bitstream_get_num(bstream,1,1)
#define read_u16(bstream) (uint16_t)bitstream_get_num(bstream,2,1)
#define read_u32(bstream) (uint32_t)bitstream_get_num(bstream,4,1)
#define read_u64(bstream) (uint64_t)bitstream_get_num(bstream,8,1)
#define read_i8(bstream) (int8_t)bitstream_get_num(bstream,1,1)
#define read_i16(bstream) (int16_t)bitstream_get_num(bstream,2,1)
#define read_i32(bstream) (int32_t)bitstream_get_num(bstream,4,1)
#define read_i64(bstream) (int64_t)bitstream_get_num(bstream,8,1)
#define read_u8(bstream) (uint8_t)bitstream_get_num(bstream, 1, 1)
#define read_u16(bstream) (uint16_t)bitstream_get_num(bstream, 2, 1)
#define read_u32(bstream) (uint32_t)bitstream_get_num(bstream, 4, 1)
#define read_u64(bstream) (uint64_t)bitstream_get_num(bstream, 8, 1)
#define read_i8(bstream) (int8_t)bitstream_get_num(bstream, 1, 1)
#define read_i16(bstream) (int16_t)bitstream_get_num(bstream, 2, 1)
#define read_i32(bstream) (int32_t)bitstream_get_num(bstream, 4, 1)
#define read_i64(bstream) (int64_t)bitstream_get_num(bstream, 8, 1)
#define skip_u32(bstream) (void)bitstream_get_num(bstream,4,1)
#define next_u8(bstream) (uint8_t)bitstream_get_num(bstream,1,0)
#define next_u16(bstream) (uint16_t)bitstream_get_num(bstream,2,0)
#define next_u32(bstream) (uint32_t)bitstream_get_num(bstream,4,0)
#define next_u64(bstream) (uint64_t)bitstream_get_num(bstream,8,0)
#define next_i8(bstream) (int8_t)bitstream_get_num(bstream,1,0)
#define next_i16(bstream) (int16_t)bitstream_get_num(bstream,2,0)
#define next_i32(bstream) (int32_t)bitstream_get_num(bstream,4,0)
#define next_i64(bstream) (int64_t)bitstream_get_num(bstream,8,0)
#define skip_u32(bstream) (void)bitstream_get_num(bstream, 4, 1)
#define next_u8(bstream) (uint8_t)bitstream_get_num(bstream, 1, 0)
#define next_u16(bstream) (uint16_t)bitstream_get_num(bstream, 2, 0)
#define next_u32(bstream) (uint32_t)bitstream_get_num(bstream, 4, 0)
#define next_u64(bstream) (uint64_t)bitstream_get_num(bstream, 8, 0)
#define next_i8(bstream) (int8_t)bitstream_get_num(bstream, 1, 0)
#define next_i16(bstream) (int16_t)bitstream_get_num(bstream, 2, 0)
#define next_i32(bstream) (int32_t)bitstream_get_num(bstream, 4, 0)
#define next_i64(bstream) (int64_t)bitstream_get_num(bstream, 8, 0)
int init_bitstream(struct bitstream *bstr, unsigned char *start, unsigned char *end);
uint64_t next_bits(struct bitstream *bstr, unsigned bnum);

View File

@@ -35,6 +35,8 @@ void get_char_in_latin_1(unsigned char *buffer, unsigned char c)
case 0x7e: // lowercase n tilde
c1 = 0xf1;
break;
case 0x7f: // Solid Block - Does not exist in Latin 1
break;
default:
c1 = c;
break;
@@ -292,6 +294,10 @@ void get_char_in_unicode(unsigned char *buffer, unsigned char c)
unsigned char c1, c2;
switch (c)
{
case 0x7f: // Solid block
c2 = 0x25;
c1 = 0xa0;
break;
case 0x84: // Trademark symbol (TM)
c2 = 0x21;
c1 = 0x22;

View File

@@ -26,14 +26,7 @@ int fdprintf(int fd, const char *fmt, ...)
void millis_to_time(LLONG milli, unsigned *hours, unsigned *minutes,
unsigned *seconds, unsigned *ms)
{
// LLONG milli = (LLONG) ((ccblock*1000)/29.97);
*ms = (unsigned)(milli % 1000); // milliseconds
milli = (milli - *ms) / 1000; // Remainder, in seconds
*seconds = (int)milli % 60;
milli = (milli - *seconds) / 60; // Remainder, in minutes
*minutes = (int)(milli % 60);
milli = (milli - *minutes) / 60; // Remainder, in hours
*hours = (int)milli;
return ccxr_millis_to_time(milli, hours, minutes, seconds, ms);
}
/* Frees the given pointer */

View File

@@ -10,44 +10,47 @@
<100 means display whatever was output to stderr as a warning
>=100 means display whatever was output to stdout as an error
*/
#define EXIT_OK 0
#define EXIT_NO_INPUT_FILES 2
#define EXIT_TOO_MANY_INPUT_FILES 3
#define EXIT_INCOMPATIBLE_PARAMETERS 4
#define EXIT_UNABLE_TO_DETERMINE_FILE_SIZE 6
#define EXIT_MALFORMED_PARAMETER 7
#define EXIT_READ_ERROR 8
#define EXIT_WITH_HELP 9
#define EXIT_NO_CAPTIONS 10
#define EXIT_NOT_CLASSIFIED 300
#define EXIT_ERROR_IN_CAPITALIZATION_FILE 501
#define EXIT_BUFFER_FULL 502
#define EXIT_MISSING_ASF_HEADER 1001
#define EXIT_MISSING_RCWT_HEADER 1002
#define EXIT_OK 0
#define EXIT_NO_INPUT_FILES 2
#define EXIT_TOO_MANY_INPUT_FILES 3
#define EXIT_INCOMPATIBLE_PARAMETERS 4
#define EXIT_UNABLE_TO_DETERMINE_FILE_SIZE 6
#define EXIT_MALFORMED_PARAMETER 7
#define EXIT_READ_ERROR 8
#define EXIT_NO_CAPTIONS 10
#define EXIT_WITH_HELP 11
#define EXIT_NOT_CLASSIFIED 300
#define EXIT_ERROR_IN_CAPITALIZATION_FILE 501
#define EXIT_BUFFER_FULL 502
#define EXIT_MISSING_ASF_HEADER 1001
#define EXIT_MISSING_RCWT_HEADER 1002
#define CCX_COMMON_EXIT_FILE_CREATION_FAILED 5
#define CCX_COMMON_EXIT_UNSUPPORTED 9
#define EXIT_NOT_ENOUGH_MEMORY 500
#define CCX_COMMON_EXIT_BUG_BUG 1000
#define CCX_COMMON_EXIT_FILE_CREATION_FAILED 5
#define CCX_COMMON_EXIT_UNSUPPORTED 9
#define EXIT_NOT_ENOUGH_MEMORY 500
#define CCX_COMMON_EXIT_BUG_BUG 1000
#define CCX_OK 0
#define CCX_FALSE 0
#define CCX_TRUE 1
#define CCX_EAGAIN -100
#define CCX_EOF -101
#define CCX_EINVAL -102
#define CCX_OK 0
#define CCX_FALSE 0
#define CCX_TRUE 1
#define CCX_EAGAIN -100
#define CCX_EOF -101
#define CCX_EINVAL -102
#define CCX_ENOSUPP -103
#define CCX_ENOMEM -104
#define CCX_ENOMEM -104
// Declarations
int cc608_parity(unsigned int byte);
int fdprintf(int fd, const char *fmt, ...);
void millis_to_time(LLONG milli, unsigned *hours, unsigned *minutes,unsigned *seconds, unsigned *ms);
void millis_to_time(LLONG milli, unsigned *hours, unsigned *minutes, unsigned *seconds, unsigned *ms);
extern void ccxr_millis_to_time(LLONG milli, unsigned *hours, unsigned *minutes, unsigned *seconds, unsigned *ms);
void freep(void *arg);
void dbg_print(LLONG mask, const char *fmt, ...);
unsigned char *debug_608_to_ASC(unsigned char *ccdata, int channel);
int add_cc_sub_text(struct cc_subtitle *sub, char *str, LLONG start_time,
LLONG end_time, char *info, char *mode, enum ccx_encoding_type);
LLONG end_time, char *info, char *mode, enum ccx_encoding_type);
extern int cc608_parity_table[256]; // From myth
#endif

View File

@@ -1,13 +1,13 @@
#include "ccx_common_constants.h"
// RCWT header (11 bytes):
//byte(s) value description (All values below are hex numbers, not
// byte(s) value description (All values below are hex numbers, not
// actual numbers or values
//0-2 CCCCED magic number, for Closed Caption CC Extractor Data
//3 CC Creating program. Legal values: CC = CC Extractor
//4-5 0050 Program version number
//6-7 0001 File format version
//8-10 000000 Padding, required :-)
// 0-2 CCCCED magic number, for Closed Caption CC Extractor Data
// 3 CC Creating program. Legal values: CC = CC Extractor
// 4-5 0050 Program version number
// 6-7 0001 File format version
// 8-10 000000 Padding, required :-)
unsigned char rcwt_header[11] = {0xCC, 0xCC, 0xED, 0xCC, 0x00, 0x50, 0, 1, 0, 0, 0};
const unsigned char BROADCAST_HEADER[] = {0xff, 0xff, 0xff, 0xff};
@@ -17,8 +17,8 @@ const unsigned char UTF8_BOM[] = {0xef, 0xbb, 0xbf};
const unsigned char DVD_HEADER[8] = {0x00, 0x00, 0x01, 0xb2, 0x43, 0x43, 0x01, 0xf8};
const unsigned char lc1[1] = {0x8a};
const unsigned char lc2[1] = {0x8f};
const unsigned char lc3[2] = {0x16, 0xfe};
const unsigned char lc4[2] = {0x1e, 0xfe};
const unsigned char lc3[1] = {0x16}; // McPoodle uses single-byte loop markers
const unsigned char lc4[1] = {0x1e};
const unsigned char lc5[1] = {0xff};
const unsigned char lc6[1] = {0xfe};
@@ -122,7 +122,7 @@ enum
*/
const char *language[NB_LANGUAGE] =
{
/*0*/ "und", //Undefined
/*0*/ "und", // Undefined
/*1*/ "eng",
/*2*/ "afr",
/*3*/ "amh",

View File

@@ -22,45 +22,42 @@ extern const unsigned char UTF8_BOM[3];
extern const unsigned char DVD_HEADER[8];
extern const unsigned char lc1[1];
extern const unsigned char lc2[1];
extern const unsigned char lc3[2];
extern const unsigned char lc4[2];
extern const unsigned char lc3[1];
extern const unsigned char lc4[1];
extern const unsigned char lc5[1];
extern const unsigned char lc6[1];
extern unsigned char rcwt_header[11];
#define ONEPASS 120 /* Bytes we can always look ahead without going out of limits */
#define BUFSIZE (2048*1024+ONEPASS) /* 2 Mb plus the safety pass */
#define ONEPASS 120 /* Bytes we can always look ahead without going out of limits */
#define BUFSIZE (2048 * 1024 + ONEPASS) /* 2 Mb plus the safety pass */
#define MAX_CLOSED_CAPTION_DATA_PER_PICTURE 32
#define EIA_708_BUFFER_LENGTH 2048 // TODO: Find out what the real limit is
#define TS_PACKET_PAYLOAD_LENGTH 184 // From specs
#define SUBLINESIZE 2048 // Max. length of a .srt line - TODO: Get rid of this
#define STARTBYTESLENGTH (1024*1024)
#define EIA_708_BUFFER_LENGTH 2048 // TODO: Find out what the real limit is
#define TS_PACKET_PAYLOAD_LENGTH 184 // From specs
#define SUBLINESIZE 2048 // Max. length of a .srt line - TODO: Get rid of this
#define STARTBYTESLENGTH (1024 * 1024)
#define UTF8_MAX_BYTES 6
#define XMLRPC_CHUNK_SIZE (64*1024) // 64 Kb per chunk, to avoid too many realloc()
#define XMLRPC_CHUNK_SIZE (64 * 1024) // 64 Kb per chunk, to avoid too many realloc()
enum ccx_debug_message_types
{
/* Each debug message now belongs to one of these types. Use bitmaps in case
we want one message to belong to more than one type. */
CCX_DMT_PARSE = 1, // Show information related to parsing the container
CCX_DMT_VIDES = 2, // Show video stream related information
CCX_DMT_TIME = 4, // Show GOP and PTS timing information
CCX_DMT_VERBOSE = 8, // Show lots of debugging output
CCX_DMT_DECODER_608 = 0x10, // Show CC-608 decoder debug?
CCX_DMT_708 = 0x20, // Show CC-708 decoder debug?
CCX_DMT_DECODER_XDS = 0x40, // Show XDS decoder debug?
CCX_DMT_CBRAW = 0x80, // Caption blocks with FTS timing
CCX_DMT_PARSE = 1, // Show information related to parsing the container
CCX_DMT_VIDES = 2, // Show video stream related information
CCX_DMT_TIME = 4, // Show GOP and PTS timing information
CCX_DMT_VERBOSE = 8, // Show lots of debugging output
CCX_DMT_DECODER_608 = 0x10, // Show CC-608 decoder debug?
CCX_DMT_708 = 0x20, // Show CC-708 decoder debug?
CCX_DMT_DECODER_XDS = 0x40, // Show XDS decoder debug?
CCX_DMT_CBRAW = 0x80, // Caption blocks with FTS timing
CCX_DMT_GENERIC_NOTICES = 0x100, // Generic, always displayed even if no debug is selected
CCX_DMT_TELETEXT = 0x200, // Show teletext debug?
CCX_DMT_PAT = 0x400, // Program Allocation Table dump
CCX_DMT_PMT = 0x800, // Program Map Table dump
CCX_DMT_LEVENSHTEIN = 0x1000, // Levenshtein distance calculations
CCX_DMT_DVB = 0x2000, // DVB
#ifdef ENABLE_SHARING
CCX_DMT_SHARE = 0x2000, // Extracted captions sharing service
#endif //ENABLE_SHARING
CCX_DMT_DUMPDEF = 0x4000 // Dump defective TS packets
CCX_DMT_TELETEXT = 0x200, // Show teletext debug?
CCX_DMT_PAT = 0x400, // Program Allocation Table dump
CCX_DMT_PMT = 0x800, // Program Map Table dump
CCX_DMT_LEVENSHTEIN = 0x1000, // Levenshtein distance calculations
CCX_DMT_DVB = 0x2000, // DVB
CCX_DMT_DUMPDEF = 0x4000 // Dump defective TS packets
};
// AVC NAL types
@@ -104,95 +101,95 @@ enum ccx_avc_nal_types
enum ccx_stream_type
{
CCX_STREAM_TYPE_UNKNOWNSTREAM = 0,
/*
/*
The later constants are defined by MPEG-TS standard
Explore at: https://exiftool.org/TagNames/M2TS.html
Explore at: https://exiftool.org/TagNames/M2TS.html
*/
CCX_STREAM_TYPE_VIDEO_MPEG1 = 0x01,
CCX_STREAM_TYPE_VIDEO_MPEG2 = 0x02,
CCX_STREAM_TYPE_AUDIO_MPEG1 = 0x03,
CCX_STREAM_TYPE_AUDIO_MPEG2 = 0x04,
CCX_STREAM_TYPE_PRIVATE_TABLE_MPEG2 = 0x05,
CCX_STREAM_TYPE_PRIVATE_MPEG2 = 0x06,
CCX_STREAM_TYPE_MHEG_PACKETS = 0x07,
CCX_STREAM_TYPE_MPEG2_ANNEX_A_DSM_CC = 0x08,
CCX_STREAM_TYPE_ITU_T_H222_1 = 0x09,
CCX_STREAM_TYPE_VIDEO_MPEG1 = 0x01,
CCX_STREAM_TYPE_VIDEO_MPEG2 = 0x02,
CCX_STREAM_TYPE_AUDIO_MPEG1 = 0x03,
CCX_STREAM_TYPE_AUDIO_MPEG2 = 0x04,
CCX_STREAM_TYPE_PRIVATE_TABLE_MPEG2 = 0x05,
CCX_STREAM_TYPE_PRIVATE_MPEG2 = 0x06,
CCX_STREAM_TYPE_MHEG_PACKETS = 0x07,
CCX_STREAM_TYPE_MPEG2_ANNEX_A_DSM_CC = 0x08,
CCX_STREAM_TYPE_ITU_T_H222_1 = 0x09,
CCX_STREAM_TYPE_ISO_IEC_13818_6_TYPE_A = 0x0A,
CCX_STREAM_TYPE_ISO_IEC_13818_6_TYPE_B = 0x0B,
CCX_STREAM_TYPE_ISO_IEC_13818_6_TYPE_C = 0x0C,
CCX_STREAM_TYPE_ISO_IEC_13818_6_TYPE_D = 0x0D,
CCX_STREAM_TYPE_AUDIO_AAC = 0x0f,
CCX_STREAM_TYPE_VIDEO_MPEG4 = 0x10,
CCX_STREAM_TYPE_VIDEO_H264 = 0x1b,
CCX_STREAM_TYPE_PRIVATE_USER_MPEG2 = 0x80,
CCX_STREAM_TYPE_AUDIO_AC3 = 0x81,
CCX_STREAM_TYPE_AUDIO_HDMV_DTS = 0x82,
CCX_STREAM_TYPE_AUDIO_DTS = 0x8a
CCX_STREAM_TYPE_AUDIO_AAC = 0x0f,
CCX_STREAM_TYPE_VIDEO_MPEG4 = 0x10,
CCX_STREAM_TYPE_VIDEO_H264 = 0x1b,
CCX_STREAM_TYPE_VIDEO_HEVC = 0x24,
CCX_STREAM_TYPE_PRIVATE_USER_MPEG2 = 0x80,
CCX_STREAM_TYPE_AUDIO_AC3 = 0x81,
CCX_STREAM_TYPE_AUDIO_HDMV_DTS = 0x82,
CCX_STREAM_TYPE_AUDIO_DTS = 0x8a
};
enum ccx_mpeg_descriptor
{
/*
/*
The later constants are defined by ETSI EN 300 468 standard
Explore at: https://www.etsi.org/deliver/etsi_en/300400_300499/300468/01.11.01_60/en_300468v011101p.pdf
Explore at: https://www.etsi.org/deliver/etsi_en/300400_300499/300468/01.11.01_60/en_300468v011101p.pdf
*/
CCX_MPEG_DSC_REGISTRATION = 0x05,
CCX_MPEG_DSC_DATA_STREAM_ALIGNMENT = 0x06,
CCX_MPEG_DSC_ISO639_LANGUAGE = 0x0A,
CCX_MPEG_DSC_VBI_DATA_DESCRIPTOR = 0x45,
CCX_MPEG_DSC_REGISTRATION = 0x05,
CCX_MPEG_DSC_DATA_STREAM_ALIGNMENT = 0x06,
CCX_MPEG_DSC_ISO639_LANGUAGE = 0x0A,
CCX_MPEG_DSC_VBI_DATA_DESCRIPTOR = 0x45,
CCX_MPEG_DSC_VBI_TELETEXT_DESCRIPTOR = 0x46,
CCX_MPEG_DSC_TELETEXT_DESCRIPTOR = 0x56,
CCX_MPEG_DSC_DVB_SUBTITLE = 0x59,
CCX_MPEG_DSC_TELETEXT_DESCRIPTOR = 0x56,
CCX_MPEG_DSC_DVB_SUBTITLE = 0x59,
/* User defined */
CCX_MPEG_DSC_CAPTION_SERVICE = 0x86,
CCX_MPEG_DESC_DATA_COMP = 0xfd // Consider to change DESC to DSC
CCX_MPEG_DSC_CAPTION_SERVICE = 0x86,
CCX_MPEG_DESC_DATA_COMP = 0xfd // Consider to change DESC to DSC
};
enum
{
CCX_MESSAGES_QUIET = 0,
CCX_MESSAGES_QUIET = 0,
CCX_MESSAGES_STDOUT = 1,
CCX_MESSAGES_STDERR = 2
};
enum ccx_datasource
{
CCX_DS_FILE = 0,
CCX_DS_STDIN = 1,
CCX_DS_FILE = 0,
CCX_DS_STDIN = 1,
CCX_DS_NETWORK = 2,
CCX_DS_TCP = 3
CCX_DS_TCP = 3
};
enum ccx_output_format
{
CCX_OF_RAW = 0,
CCX_OF_SRT = 1,
CCX_OF_SAMI = 2,
CCX_OF_RAW = 0,
CCX_OF_SRT = 1,
CCX_OF_SAMI = 2,
CCX_OF_TRANSCRIPT = 3,
CCX_OF_RCWT = 4,
CCX_OF_NULL = 5,
CCX_OF_SMPTETT = 6,
CCX_OF_SPUPNG = 7,
CCX_OF_DVDRAW = 8, // See -d at http://www.theneitherworld.com/mcpoodle/SCC_TOOLS/DOCS/SCC_TOOLS.HTML#CCExtract
CCX_OF_WEBVTT = 9,
CCX_OF_RCWT = 4,
CCX_OF_NULL = 5,
CCX_OF_SMPTETT = 6,
CCX_OF_SPUPNG = 7,
CCX_OF_DVDRAW = 8, // See -d at http://www.theneitherworld.com/mcpoodle/SCC_TOOLS/DOCS/SCC_TOOLS.HTML#CCExtract
CCX_OF_WEBVTT = 9,
CCX_OF_SIMPLE_XML = 10,
CCX_OF_G608 = 11,
CCX_OF_CURL = 12,
CCX_OF_SSA = 13,
CCX_OF_MCC = 14,
CCX_OF_SCC = 15,
CCX_OF_CCD = 16,
CCX_OF_G608 = 11,
CCX_OF_CURL = 12,
CCX_OF_SSA = 13,
CCX_OF_MCC = 14,
CCX_OF_SCC = 15,
CCX_OF_CCD = 16,
};
enum ccx_output_date_format
{
ODF_NONE = 0,
ODF_HHMMSS = 1,
ODF_SECONDS = 2,
ODF_DATE = 3,
ODF_HHMMSSMS = 4 // HH:MM:SS,MILIS (.srt style)
ODF_NONE = 0,
ODF_HHMMSS = 1,
ODF_SECONDS = 2,
ODF_DATE = 3,
ODF_HHMMSSMS = 4 // HH:MM:SS,MILIS (.srt style)
};
enum ccx_stream_mode_enum
@@ -202,9 +199,9 @@ enum ccx_stream_mode_enum
CCX_SM_PROGRAM = 2,
CCX_SM_ASF = 3,
CCX_SM_MCPOODLESRAW = 4,
CCX_SM_RCWT = 5, // Raw Captions With Time, not used yet.
CCX_SM_MYTH = 6, // Use the myth loop
CCX_SM_MP4 = 7, // MP4, ISO-
CCX_SM_RCWT = 5, // Raw Captions With Time, not used yet.
CCX_SM_MYTH = 6, // Use the myth loop
CCX_SM_MP4 = 7, // MP4, ISO-
#ifdef WTV_DEBUG
CCX_SM_HEX_DUMP = 8, // Hexadecimal dump generated by wtvccdump
#endif
@@ -223,8 +220,8 @@ enum ccx_encoding_type
{
CCX_ENC_UNICODE = 0,
CCX_ENC_LATIN_1 = 1,
CCX_ENC_UTF_8 = 2,
CCX_ENC_ASCII = 3
CCX_ENC_UTF_8 = 2,
CCX_ENC_ASCII = 3
};
enum ccx_bufferdata_type
@@ -240,7 +237,8 @@ enum ccx_bufferdata_type
CCX_ISDB_SUBTITLE = 8,
/* BUffer where cc data contain 3 byte cc_valid ccdata 1 ccdata 2 */
CCX_RAW_TYPE = 9,
CCX_DVD_SUBTITLE = 10
CCX_DVD_SUBTITLE = 10,
CCX_HEVC = 11
};
enum ccx_frame_type
@@ -252,32 +250,33 @@ enum ccx_frame_type
CCX_FRAME_TYPE_D_FRAME = 4
};
typedef enum {
NO = 0,
typedef enum
{
NO = 0,
YES = 1,
UNDEFINED = 0xff
} bool_t;
enum ccx_code_type
{
CCX_CODEC_ANY = 0,
CCX_CODEC_ANY = 0,
CCX_CODEC_TELETEXT = 1,
CCX_CODEC_DVB = 2,
CCX_CODEC_ISDB_CC = 3,
CCX_CODEC_ATSC_CC = 4,
CCX_CODEC_NONE = 5
CCX_CODEC_DVB = 2,
CCX_CODEC_ISDB_CC = 3,
CCX_CODEC_ATSC_CC = 4,
CCX_CODEC_NONE = 5
};
/* Caption Distribution Packet */
enum cdp_section_type
{
/*
/*
The later constants are defined by SMPTE ST 334
Purchase for 80$ at: https://ieeexplore.ieee.org/document/8255806
*/
CDP_SECTION_DATA = 0x72,
CDP_SECTION_DATA = 0x72,
CDP_SECTION_SVC_INFO = 0x73,
CDP_SECTION_FOOTER = 0x74
CDP_SECTION_FOOTER = 0x74
};
/*
@@ -290,9 +289,9 @@ enum cdp_section_type
*
*/
#define IS_VALID_TELETEXT_DESC(desc) ( ((desc) == CCX_MPEG_DSC_VBI_DATA_DESCRIPTOR )|| \
( (desc) == CCX_MPEG_DSC_VBI_TELETEXT_DESCRIPTOR ) || \
( (desc) == CCX_MPEG_DSC_TELETEXT_DESCRIPTOR ) )
#define IS_VALID_TELETEXT_DESC(desc) (((desc) == CCX_MPEG_DSC_VBI_DATA_DESCRIPTOR) || \
((desc) == CCX_MPEG_DSC_VBI_TELETEXT_DESCRIPTOR) || \
((desc) == CCX_MPEG_DSC_TELETEXT_DESCRIPTOR))
/*
* This macro to be used when you want to find out whether you
@@ -311,19 +310,19 @@ enum cdp_section_type
* @param f_sel pass the codec name whom you are testing to be feasible
* to parse.
*/
#define IS_FEASIBLE(u_sel,u_nsel,f_sel) ( ( (u_sel) == CCX_CODEC_ANY && (u_nsel) != (f_sel) ) || (u_sel) == (f_sel) )
#define CCX_TXT_FORBIDDEN 0 // Ignore teletext packets
#define CCX_TXT_AUTO_NOT_YET_FOUND 1
#define CCX_TXT_IN_USE 2 // Positive auto-detected, or forced, etc
#define IS_FEASIBLE(u_sel, u_nsel, f_sel) (((u_sel) == CCX_CODEC_ANY && (u_nsel) != (f_sel)) || (u_sel) == (f_sel))
#define CCX_TXT_FORBIDDEN 0 // Ignore teletext packets
#define CCX_TXT_AUTO_NOT_YET_FOUND 1
#define CCX_TXT_IN_USE 2 // Positive auto-detected, or forced, etc
#define NB_LANGUAGE 100
extern const char *language[NB_LANGUAGE];
#define DEF_VAL_STARTCREDITSNOTBEFORE "0"
#define DEF_VAL_STARTCREDITSNOTBEFORE "0"
// To catch the theme after the teaser in TV shows
#define DEF_VAL_STARTCREDITSNOTAFTER "5:00"
#define DEF_VAL_STARTCREDITSFORATLEAST "2"
#define DEF_VAL_STARTCREDITSFORATMOST "5"
#define DEF_VAL_ENDCREDITSFORATLEAST "2"
#define DEF_VAL_ENDCREDITSFORATMOST "5"
#define DEF_VAL_STARTCREDITSNOTAFTER "5:00"
#define DEF_VAL_STARTCREDITSFORATLEAST "2"
#define DEF_VAL_STARTCREDITSFORATMOST "5"
#define DEF_VAL_ENDCREDITSFORATLEAST "2"
#define DEF_VAL_ENDCREDITSFORATMOST "5"
#endif

View File

@@ -22,10 +22,12 @@ void init_options(struct ccx_s_options *options)
options->settings_608.force_rollup = 0;
options->settings_608.screens_to_process = -1;
options->settings_608.default_color = COL_TRANSPARENT; // Defaults to transparent/no-color.
options->is_608_enabled = 0;
options->is_708_enabled = 0;
options->extract = 1; // Extract 1st field only (primary language)
options->cc_channel = 1; // Channel we want to dump in srt mode
options->binary_concat = 1; // Disabled by -ve or --videoedited
options->binary_concat = 1; // Disabled by --videoedited
options->use_gop_as_pts = 0; // Use GOP instead of PTS timing (0=do as needed, 1=always, -1=never)
options->fix_padding = 0; // Replace 0000 with 8080 in HDTV (needed for some cards)
options->gui_mode_reports = 0; // If 1, output in stderr progress updates so the GUI can grab them
@@ -39,7 +41,7 @@ void init_options(struct ccx_s_options *options)
options->live_stream = 0; // 0 -> A regular file
options->messages_target = 1; // 1=stdout
options->print_file_reports = 0;
options->no_timestamp_map = 0; // Enable timestamps by default
options->timestamp_map = 0; // Disable X-TIMESTAMP-MAP header by default
/* Levenshtein's parameters, for string comparison */
options->dolevdist = 1; // By default attempt to correct typos
@@ -63,14 +65,15 @@ void init_options(struct ccx_s_options *options)
options->xmltvonlycurrent = 0; // 0 off 1 on
options->keep_output_closed = 0; // By default just keep the file open.
options->force_flush = 0; // Don't flush whenever content is written.
options->append_mode = 0; //By default, files are overwritten.
options->append_mode = 0; // By default, files are overwritten.
options->ucla = 0; // By default, -UCLA not used
options->tickertext = 0; // By default, do not assume ticker style text
options->hardsubx = 0; // By default, don't try to extract hard subtitles
options->dvblang = NULL; // By default, autodetect DVB language
options->ocrlang = NULL; // By default, autodetect .traineddata file
options->ocr_oem = -1; // By default, OEM mode depends on the tesseract version
options->ocr_quantmode = 1; // CCExtractor's internal
options->psm = 3; // Default PSM mode (3 is the default tesseract as well)
options->ocr_quantmode = 0; // No quantization (better OCR accuracy for DVB subtitles)
options->mkvlang = NULL; // By default, all the languages are extracted
options->ignore_pts_jumps = 1;
options->analyze_video_stream = 0;
@@ -83,6 +86,7 @@ void init_options(struct ccx_s_options *options)
options->hardsubx_conf_thresh = 0.0;
options->hardsubx_hue = 0.0;
options->hardsubx_lum_thresh = 95.0;
options->hardsubx_and_common = 0;
options->transcript_settings = ccx_encoders_default_transcript_settings;
options->millis_separator = ',';
@@ -131,32 +135,23 @@ void init_options(struct ccx_s_options *options)
options->enc_cfg.start_credits_text = NULL;
options->enc_cfg.end_credits_text = NULL;
options->enc_cfg.encoding = CCX_ENC_UTF_8;
#ifdef _WIN32
options->enc_cfg.no_bom = 0; // Use BOM by default for windows only
#else
options->enc_cfg.no_bom = 1;
#endif
options->enc_cfg.services_charsets = NULL;
options->enc_cfg.all_services_charset = NULL;
options->enc_cfg.with_semaphore = 0;
options->enc_cfg.force_dropframe = 0; // Assume No Drop Frame for MCC Encode.
options->enc_cfg.extract_only_708 = 0;
options->settings_dtvcc.enabled = 0;
options->settings_dtvcc.active_services_count = 0;
options->settings_dtvcc.print_file_reports = 1;
options->settings_dtvcc.no_rollup = 0;
options->settings_dtvcc.report = NULL;
options->settings_dtvcc.timing = NULL;
memset(
options->settings_dtvcc.services_enabled, 0,
CCX_DTVCC_MAX_SERVICES * sizeof(options->settings_dtvcc.services_enabled[0]));
#ifdef ENABLE_SHARING
options->sharing_enabled = 0;
options->sharing_url = NULL;
options->translate_enabled = 0;
options->translate_key = NULL;
options->translate_langs = NULL;
#endif //ENABLE_SHARING
#ifdef WITH_LIBCURL
options->curlposturl = NULL;
#endif

View File

@@ -15,39 +15,38 @@ struct demuxer_cfg
enum ccx_code_type codec;
enum ccx_code_type nocodec;
unsigned ts_autoprogram; // Try to find a stream with captions automatically (no -pn needed)
unsigned ts_autoprogram; // Try to find a stream with captions automatically (no -pn needed)
unsigned ts_allprogram;
unsigned ts_cappids[128]; // PID for stream that holds caption information
unsigned ts_cappids[128]; // PID for stream that holds caption information
int nb_ts_cappid;
unsigned ts_forced_cappid ; // If 1, never mess with the selected PID
int ts_forced_program; // Specific program to process in TS files, if ts_forced_program_selected==1
unsigned ts_forced_cappid; // If 1, never mess with the selected PID
int ts_forced_program; // Specific program to process in TS files, if ts_forced_program_selected==1
unsigned ts_forced_program_selected;
int ts_datastreamtype ; // User WANTED stream type (i.e. use the stream that has this type)
int ts_datastreamtype; // User WANTED stream type (i.e. use the stream that has this type)
unsigned ts_forced_streamtype; // User selected (forced) stream type
};
struct encoder_cfg
{
int extract; // Extract 1st, 2nd or both fields
int dtvcc_extract; // 1 or 0
int gui_mode_reports; // If 1, output in stderr progress updates so the GUI can grab them
int extract; // Extract 1st, 2nd or both fields
int dtvcc_extract; // 1 or 0
int gui_mode_reports; // If 1, output in stderr progress updates so the GUI can grab them
char *output_filename;
enum ccx_output_format write_format; // 0=Raw, 1=srt, 2=SMI
int keep_output_closed;
int force_flush; // Force flush on content write
int append_mode; // Append mode for output files
int ucla; // 1 if -UCLA used, 0 if not
int no_timestamp_map; // 1 if timestamps disabled for WebVTT
int force_flush; // Force flush on content write
int append_mode; // Append mode for output files
int ucla; // 1 if -UCLA used, 0 if not
enum ccx_encoding_type encoding;
enum ccx_output_date_format date_format;
char millis_separator;
int autodash; // Add dashes (-) before each speaker automatically?
int trim_subs; // " Remove spaces at sides? "
int autodash; // Add dashes (-) before each speaker automatically?
int trim_subs; // " Remove spaces at sides? "
int sentence_cap; // FIX CASE? = Fix case?
int splitbysentence; // Split text into complete sentences and prorate time?
#ifdef WITH_LIBCURL
char *curlposturl; // If out=curl, where do we send the data to?
char *curlposturl; // If out=curl, where do we send the data to?
#endif
int filter_profanity; // Censors profane words from subtitles
@@ -55,44 +54,45 @@ struct encoder_cfg
/* Credit stuff */
char *start_credits_text;
char *end_credits_text;
struct ccx_boundary_time startcreditsnotbefore, startcreditsnotafter; // Where to insert start credits, if possible
struct ccx_boundary_time startcreditsnotbefore, startcreditsnotafter; // Where to insert start credits, if possible
struct ccx_boundary_time startcreditsforatleast, startcreditsforatmost; // How long to display them?
struct ccx_boundary_time endcreditsforatleast, endcreditsforatmost;
ccx_encoders_transcript_format transcript_settings; // Keeps the settings for generating transcript output files.
unsigned int send_to_srv;
int no_bom; // Set to 1 when no BOM (Byte Order Mark) should be used for files. Note, this might make files unreadable in windows!
int no_bom; // Set to 1 when no BOM (Byte Order Mark) should be used for files. Note, this might make files unreadable in windows!
char *first_input_file;
int multiple_files;
int no_font_color;
int no_type_setting;
int cc_to_stdout; // If this is set to 1, the stdout will be flushed when data was written to the screen during a process_608 call.
int line_terminator_lf; // 0 = CRLF, 1=LF
LLONG subs_delay; // ms to delay (or advance) subs
int cc_to_stdout; // If this is set to 1, the stdout will be flushed when data was written to the screen during a process_608 call.
int line_terminator_lf; // 0 = CRLF, 1=LF
LLONG subs_delay; // ms to delay (or advance) subs
int program_number;
unsigned char in_format;
int nospupngocr; // 1 if we don't want to OCR bitmaps to add the text as comments in the XML file in spupng
int nospupngocr; // 1 if we don't want to OCR bitmaps to add the text as comments in the XML file in spupng
// MCC File
int force_dropframe; // 1 if dropframe frame count should be used. defaults to no drop frame.
int force_dropframe; // 1 if dropframe frame count should be used. defaults to no drop frame.
// text -> png (text render)
char *render_font; // The font used to render text if needed (e.g. teletext->spupng)
char *render_font; // The font used to render text if needed (e.g. teletext->spupng)
char *render_font_italics;
//CEA-708
// CEA-708
int services_enabled[CCX_DTVCC_MAX_SERVICES];
char** services_charsets;
char* all_services_charset;
char **services_charsets;
char *all_services_charset;
int extract_only_708; // 1 if only 708 subs extraction is enabled
};
struct ccx_s_options // Options from user parameters
{
int extract; // Extract 1st, 2nd or both fields
int no_rollup; // Disable roll-up emulation (no duplicate output in generated file)
int extract; // Extract 1st, 2nd or both fields
int no_rollup; // Disable roll-up emulation (no duplicate output in generated file)
int noscte20;
int webvtt_create_css;
int cc_channel; // Channel we want to dump in srt mode
int cc_channel; // Channel we want to dump in srt mode
int buffer_input;
int nofontcolor;
int nohtmlescape;
@@ -100,53 +100,57 @@ struct ccx_s_options // Options from user parameters
struct ccx_boundary_time extraction_start, extraction_end; // Segment we actually process
int print_file_reports;
ccx_decoder_608_settings settings_608; // Contains the settings for the 608 decoder.
ccx_decoder_dtvcc_settings settings_dtvcc; // Same for 708 decoder
ccx_decoder_608_settings settings_608; // Contains the settings for the 608 decoder.
ccx_decoder_dtvcc_settings settings_dtvcc; // Same for 708 decoder
int is_608_enabled; // Is 608 enabled by explicitly using flags(-1,-2,-12)
int is_708_enabled; // Is 708 enabled by explicitly using flags(-svc)
char millis_separator;
int binary_concat; // Disabled by -ve or --videoedited
int use_gop_as_pts; // Use GOP instead of PTS timing (0=do as needed, 1=always, -1=never)
int fix_padding; // Replace 0000 with 8080 in HDTV (needed for some cards)
int gui_mode_reports; // If 1, output in stderr progress updates so the GUI can grab them
int no_progress_bar; // If 1, suppress the output of the progress to stdout
char *sentence_cap_file; // Extra capitalization word file
int live_stream; /* -1 -> Not a complete file but a live stream, without timeout
0 -> A regular file
>0 -> Live stream with a timeout of this value in seconds */
char *filter_profanity_file; // Extra profanity word file
int messages_target; // 0 = nowhere (quiet), 1=stdout, 2=stderr
int no_timestamp_map; // 1 for no timestamps for WebVTT, 0 for the timestamp header
int binary_concat; // Disabled by -ve or --videoedited
int use_gop_as_pts; // Use GOP instead of PTS timing (0=do as needed, 1=always, -1=never)
int fix_padding; // Replace 0000 with 8080 in HDTV (needed for some cards)
int gui_mode_reports; // If 1, output in stderr progress updates so the GUI can grab them
int no_progress_bar; // If 1, suppress the output of the progress to stdout
char *sentence_cap_file; // Extra capitalization word file
int live_stream; /* -1 -> Not a complete file but a live stream, without timeout
0 -> A regular file
>0 -> Live stream with a timeout of this value in seconds */
char *filter_profanity_file; // Extra profanity word file
int messages_target; // 0 = nowhere (quiet), 1=stdout, 2=stderr
int timestamp_map; // If 1, add WebVTT X-TIMESTAMP-MAP header
/* Levenshtein's parameters, for string comparison */
int dolevdist; // 0 => don't attempt to correct typos with this algorithm
int dolevdist; // 0 => don't attempt to correct typos with this algorithm
int levdistmincnt, levdistmaxpct; // Means 2 fails or less is "the same", 10% or less is also "the same"
int investigate_packets; // Look for captions in all packets when everything else fails
int fullbin; // Disable pruning of padding cc blocks
int nosync; // Disable syncing
unsigned int hauppauge_mode; // If 1, use PID=1003, process specially and so on
int wtvconvertfix; // Fix broken Windows 7 conversion
int investigate_packets; // Look for captions in all packets when everything else fails
int fullbin; // Disable pruning of padding cc blocks
int nosync; // Disable syncing
unsigned int hauppauge_mode; // If 1, use PID=1003, process specially and so on
int wtvconvertfix; // Fix broken Windows 7 conversion
int wtvmpeg2;
int auto_myth; // Use myth-tv mpeg code? 0=no, 1=yes, 2=auto
int auto_myth; // Use myth-tv mpeg code? 0=no, 1=yes, 2=auto
/* MP4 related stuff */
unsigned mp4vidtrack; // Process the video track even if a CC dedicated track exists.
int extract_chapters; // If 1, extracts chapters (if present), from MP4 files.
unsigned mp4vidtrack; // Process the video track even if a CC dedicated track exists.
int extract_chapters; // If 1, extracts chapters (if present), from MP4 files.
/* General settings */
int usepicorder; // Force the use of pic_order_cnt_lsb in AVC/H.264 data streams
int xmltv; // 1 = full output. 2 = live output. 3 = both
int xmltvliveinterval; // interval in seconds between writing xmltv output files in live mode
int xmltvoutputinterval; // interval in seconds between writing xmltv full file output
int xmltvonlycurrent; // 0 off 1 on
int usepicorder; // Force the use of pic_order_cnt_lsb in AVC/H.264 data streams
int xmltv; // 1 = full output. 2 = live output. 3 = both
int xmltvliveinterval; // interval in seconds between writing xmltv output files in live mode
int xmltvoutputinterval; // interval in seconds between writing xmltv full file output
int xmltvonlycurrent; // 0 off 1 on
int keep_output_closed;
int force_flush; // Force flush on content write
int append_mode; // Append mode for output files
int ucla; // 1 if UCLA used, 0 if not
int tickertext; // 1 if ticker text style burned in subs, 0 if not
int hardsubx; // 1 if burned-in subtitles to be extracted
char *dvblang; // The name of the language stream for DVB
const char *ocrlang; // The name of the .traineddata file to be loaded with tesseract
int ocr_oem; // The Tesseract OEM mode, could be 0 (default), 1 or 2
int ocr_quantmode; // How to quantize the bitmap before passing to to tesseract (0=no quantization at all, 1=CCExtractor's internal)
char *mkvlang; // The name of the language stream for MKV
int analyze_video_stream; // If 1, the video stream will be processed even if we're using a different one for subtitles.
int force_flush; // Force flush on content write
int append_mode; // Append mode for output files
int ucla; // 1 if UCLA used, 0 if not
int tickertext; // 1 if ticker text style burned in subs, 0 if not
int hardsubx; // 1 if burned-in subtitles to be extracted
int hardsubx_and_common; // 1 if both burned-in and not burned in need to be extracted
char *dvblang; // The name of the language stream for DVB
const char *ocrlang; // The name of the .traineddata file to be loaded with tesseract
int ocr_oem; // The Tesseract OEM mode, could be 0 (default), 1 or 2
int psm; // The Tesseract PSM mode, could be between 0 and 13. 3 is tesseract default
int ocr_quantmode; // How to quantize the bitmap before passing to to tesseract (0=no quantization at all, 1=CCExtractor's internal)
char *mkvlang; // The name of the language stream for MKV
int analyze_video_stream; // If 1, the video stream will be processed even if we're using a different one for subtitles.
/*HardsubX related stuff*/
int hardsubx_ocr_mode;
@@ -160,53 +164,42 @@ struct ccx_s_options // Options from user parameters
ccx_encoders_transcript_format transcript_settings; // Keeps the settings for generating transcript output files.
enum ccx_output_date_format date_format;
unsigned send_to_srv;
enum ccx_output_format write_format; // 0=Raw, 1=srt, 2=SMI
enum ccx_output_format write_format; // 0=Raw, 1=srt, 2=SMI
int write_format_rewritten;
int use_ass_instead_of_ssa;
int use_webvtt_styling;
LLONG debug_mask; // dbg_print will use this mask to print or ignore different types
LLONG debug_mask_on_debug; // If we're using temp_debug to enable/disable debug "live", this is the mask when temp_debug=1
LLONG debug_mask; // dbg_print will use this mask to print or ignore different types
LLONG debug_mask_on_debug; // If we're using temp_debug to enable/disable debug "live", this is the mask when temp_debug=1
/* Networking */
char *udpsrc;
char *udpaddr;
unsigned udpport; // Non-zero => Listen for UDP packets on this port, no files.
unsigned udpport; // Non-zero => Listen for UDP packets on this port, no files.
char *tcpport;
char *tcp_password;
char *tcp_desc;
char *srv_addr;
char *srv_port;
int noautotimeref; // Do NOT set time automatically?
enum ccx_datasource input_source; // Files, stdin or network
int noautotimeref; // Do NOT set time automatically?
enum ccx_datasource input_source; // Files, stdin or network
char *output_filename;
char **inputfile; // List of files to process
int num_input_files; // How many?
char **inputfile; // List of files to process
int num_input_files; // How many?
struct demuxer_cfg demux_cfg;
struct encoder_cfg enc_cfg;
LLONG subs_delay; // ms to delay (or advance) subs
int cc_to_stdout; // If this is set to 1, the stdout will be flushed when data was written to the screen during a process_608 call.
int pes_header_to_stdout; // If this is set to 1, the PES Header will be printed to console (debugging purposes)
int ignore_pts_jumps; // If 1, the program will ignore PTS jumps. Sometimes this parameter is required for DVB subs with > 30s pause time
LLONG subs_delay; // ms to delay (or advance) subs
int cc_to_stdout; // If this is set to 1, the stdout will be flushed when data was written to the screen during a process_608 call.
int pes_header_to_stdout; // If this is set to 1, the PES Header will be printed to console (debugging purposes)
int ignore_pts_jumps; // If 1, the program will ignore PTS jumps. Sometimes this parameter is required for DVB subs with > 30s pause time
int multiprogram;
int out_interval;
int segment_on_key_frames_only;
#ifdef WITH_LIBCURL
char *curlposturl;
#endif
#ifdef ENABLE_SHARING
//CC sharing
int sharing_enabled;
char *sharing_url;
//Translating
int translate_enabled;
char *translate_langs;
char *translate_key;
#endif
};
extern struct ccx_s_options ccx_options;
void init_options (struct ccx_s_options *options);
void init_options(struct ccx_s_options *options);
#endif

View File

@@ -1,119 +1,122 @@
#ifndef CCX_PLATFORM_H
#define CCX_PLATFORM_H
// Default includes (cross-platform)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <fcntl.h>
#include <stdarg.h>
#include <errno.h>
#define __STDC_FORMAT_MACROS
#ifdef _WIN32
#define inline _inline
#define typeof decltype
#include <io.h>
#include <ws2tcpip.h>
#include <windows.h>
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
#include "inttypes.h"
#define UINT64_MAX _UI64_MAX
typedef int socklen_t;
typedef int ssize_t;
typedef uint32_t in_addr_t;
#ifndef IN_CLASSD
#define IN_CLASSD(i) (((INT32)(i) & 0xf0000000) == 0xe0000000)
#define IN_MULTICAST(i) IN_CLASSD(i)
#endif
#include <direct.h>
#define mkdir(path, mode) _mkdir(path)
#ifndef snprintf
// Added ifndef because VS2013 warns for macro redefinition.
#define snprintf(buf, len, fmt, ...) _snprintf(buf, len, fmt, __VA_ARGS__)
#endif
#define sleep(sec) Sleep((sec) * 1000)
#include <fcntl.h>
#else // _WIN32
#include <unistd.h>
#define __STDC_LIMIT_MACROS
#include <inttypes.h>
#include <stdint.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/stat.h>
#include <sys/types.h>
#endif // _WIN32
#include "disable_warnings.h"
#ifdef _MSC_VER
#include "stdintmsc.h"
// Don't bug me with strcpy() deprecation warnings
#pragma warning(disable : 4996)
#else
#include <stdint.h>
#endif
#ifdef __OpenBSD__
#define FOPEN64 fopen
#define OPEN open
#define FSEEK fseek
#define FTELL ftell
#define LSEEK lseek
#define FSTAT fstat
#else
#ifdef _WIN32
#define OPEN _open
// 64 bit file functions
#if defined(_MSC_VER)
#define FSEEK _fseeki64
#define FTELL _ftelli64
#else
// For MinGW
#define FSEEK fseeko64
#define FTELL ftello64
#endif
#define TELL _telli64
#define LSEEK _lseeki64
typedef struct _stati64 FSTATSTRUCT;
#else
// Linux internally maps these functions to 64bit usage,
// if _FILE_OFFSET_BITS macro is set to 64
#define FOPEN64 fopen
#define OPEN open
#define LSEEK lseek
#define FSEEK fseek
#define FTELL ftell
#define FSTAT fstat
#define TELL tell
#include <stdint.h>
#endif
#endif
#ifndef int64_t_C
#define int64_t_C(c) (c ## LL)
#define uint64_t_C(c) (c ## ULL)
#endif
#ifndef O_BINARY
#define O_BINARY 0 // Not present in Linux because it's always binary
#endif
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
typedef int64_t LLONG;
typedef uint64_t ULLONG;
typedef uint8_t UBYTE;
#endif // CCX_PLATFORM_H
#ifndef CCX_PLATFORM_H
#define CCX_PLATFORM_H
// Default includes (cross-platform)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <fcntl.h>
#include <stdarg.h>
#include <errno.h>
#define __STDC_FORMAT_MACROS
#ifdef _WIN32
#define inline _inline
#define typeof decltype
#include <io.h>
#include <ws2tcpip.h>
#include <windows.h>
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
#include "inttypes.h"
#undef UINT64_MAX
#define UINT64_MAX _UI64_MAX
typedef int socklen_t;
#if !defined(__MINGW64__) && !defined(__MINGW32__)
typedef int ssize_t;
#endif
typedef uint32_t in_addr_t;
#ifndef IN_CLASSD
#define IN_CLASSD(i) (((INT32)(i) & 0xf0000000) == 0xe0000000)
#define IN_MULTICAST(i) IN_CLASSD(i)
#endif
#include <direct.h>
#define mkdir(path, mode) _mkdir(path)
#ifndef snprintf
// Added ifndef because VS2013 warns for macro redefinition.
#define snprintf(buf, len, fmt, ...) _snprintf(buf, len, fmt, __VA_ARGS__)
#endif
#define sleep(sec) Sleep((sec) * 1000)
#include <fcntl.h>
#else // _WIN32
#include <unistd.h>
#define __STDC_LIMIT_MACROS
#include <inttypes.h>
#include <stdint.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/stat.h>
#include <sys/types.h>
#endif // _WIN32
// #include "disable_warnings.h"
#if defined(_MSC_VER) && !defined(__clang__)
#include "stdintmsc.h"
// Don't bug me with strcpy() deprecation warnings
#pragma warning(disable : 4996)
#else
#include <stdint.h>
#endif
#ifdef __OpenBSD__
#define FOPEN64 fopen
#define OPEN open
#define FSEEK fseek
#define FTELL ftell
#define LSEEK lseek
#define FSTAT fstat
#else
#ifdef _WIN32
#define OPEN _open
// 64 bit file functions
#if defined(_MSC_VER)
#define FSEEK _fseeki64
#define FTELL _ftelli64
#else
// For MinGW
#define FSEEK fseeko64
#define FTELL ftello64
#endif
#define TELL _telli64
#define LSEEK _lseeki64
typedef struct _stati64 FSTATSTRUCT;
#else
// Linux internally maps these functions to 64bit usage,
// if _FILE_OFFSET_BITS macro is set to 64
#define FOPEN64 fopen
#define OPEN open
#define LSEEK lseek
#define FSEEK fseek
#define FTELL ftell
#define FSTAT fstat
#define TELL tell
#include <stdint.h>
#endif
#endif
#ifndef int64_t_C
#define int64_t_C(c) (c##LL)
#define uint64_t_C(c) (c##ULL)
#endif
#ifndef O_BINARY
#define O_BINARY 0 // Not present in Linux because it's always binary
#endif
#ifndef max
#define max(a, b) (((a) > (b)) ? (a) : (b))
#endif
typedef int64_t LLONG;
typedef uint64_t ULLONG;
typedef uint8_t UBYTE;
#endif // CCX_PLATFORM_H

View File

@@ -3,26 +3,28 @@
#include "ccx_common_constants.h"
enum ccx_common_logging_gui {
CCX_COMMON_LOGGING_GUI_XDS_PROGRAM_NAME, // Called with xds_program_name
CCX_COMMON_LOGGING_GUI_XDS_PROGRAM_ID_NR, // Called with current_xds_min, current_xds_hour, current_xds_date, current_xds_month
enum ccx_common_logging_gui
{
CCX_COMMON_LOGGING_GUI_XDS_PROGRAM_NAME, // Called with xds_program_name
CCX_COMMON_LOGGING_GUI_XDS_PROGRAM_ID_NR, // Called with current_xds_min, current_xds_hour, current_xds_date, current_xds_month
CCX_COMMON_LOGGING_GUI_XDS_PROGRAM_DESCRIPTION, // Called with line_num, xds_desc
CCX_COMMON_LOGGING_GUI_XDS_CALL_LETTERS // Called with current_xds_call_letters
CCX_COMMON_LOGGING_GUI_XDS_CALL_LETTERS // Called with current_xds_call_letters
};
struct ccx_common_logging_t {
LLONG debug_mask; // The debug mask that is used to determine if things should be printed or not.
void(*fatal_ftn) (int exit_code, const char *fmt, ...); // Used when an unrecoverable error happens. This should log output/save the error and then exit the program.
void(*debug_ftn) (LLONG mask, const char *fmt, ...); // Used to process debug output. Mask can be ignored (custom set by debug_mask).
void(*log_ftn)(const char *fmt, ...); // Used to print things. Replacement of standard printf, to allow more control.
void(*gui_ftn)(enum ccx_common_logging_gui message_type, ...); // Used to display things in a gui (if appropriate). Is called with the message_type and appropriate variables (described in enum)
struct ccx_common_logging_t
{
LLONG debug_mask; // The debug mask that is used to determine if things should be printed or not.
void (*fatal_ftn)(int exit_code, const char *fmt, ...); // Used when an unrecoverable error happens. This should log output/save the error and then exit the program.
void (*debug_ftn)(LLONG mask, const char *fmt, ...); // Used to process debug output. Mask can be ignored (custom set by debug_mask).
void (*log_ftn)(const char *fmt, ...); // Used to print things. Replacement of standard printf, to allow more control.
void (*gui_ftn)(enum ccx_common_logging_gui message_type, ...); // Used to display things in a gui (if appropriate). Is called with the message_type and appropriate variables (described in enum)
};
extern struct ccx_common_logging_t ccx_common_logging;
enum subdatatype
{
CC_DATATYPE_GENERIC=0,
CC_DATATYPE_DVB=1
CC_DATATYPE_GENERIC = 0,
CC_DATATYPE_DVB = 1
};
enum subtype
@@ -34,18 +36,18 @@ enum subtype
};
/**
* Raw Subtitle struct used as output of decoder (cc608)
* and input for encoder (sami, srt, transcript or smptett etc)
*
* if subtype CC_BITMAP then data contain nb_data numbers of rectangle
* which have to be displayed at same time.
*/
* Raw Subtitle struct used as output of decoder (cc608)
* and input for encoder (sami, srt, transcript or smptett etc)
*
* if subtype CC_BITMAP then data contain nb_data numbers of rectangle
* which have to be displayed at same time.
*/
struct cc_subtitle
{
/**
* A generic data which contain data according to decoder
* @warn decoder cant output multiple types of data
*/
* A generic data which contain data according to decoder
* @warn decoder cant output multiple types of data
*/
void *data;
enum subdatatype datatype;
@@ -56,11 +58,11 @@ struct cc_subtitle
enum subtype type;
/** Encoding type of Text, must be ignored in case of subtype as bitmap or cc_screen*/
enum ccx_encoding_type enc_type;
enum ccx_encoding_type enc_type;
/* set only when all the data is to be displayed at same time
* Unit is of time is ms
*/
* Unit is of time is ms
*/
LLONG start_time;
LLONG end_time;
@@ -72,13 +74,19 @@ struct cc_subtitle
/** flag to tell that decoder has given output */
int got_output;
char mode[5];
char info[4];
/** Used for DVB end time in ms */
int time_out;
/** Raw PTS value when this subtitle started (for DVB timing) */
LLONG start_pts;
/** Teletext page number (for multi-page extraction, issue #665) */
uint16_t teletext_page;
struct cc_subtitle *next;
struct cc_subtitle *prev;
};

View File

@@ -30,6 +30,18 @@ int gop_rollover = 0;
struct ccx_common_timing_settings_t ccx_common_timing_settings;
void ccxr_add_current_pts(struct ccx_common_timing_ctx *ctx, LLONG pts);
void ccxr_set_current_pts(struct ccx_common_timing_ctx *ctx, LLONG pts);
int ccxr_set_fts(struct ccx_common_timing_ctx *ctx);
LLONG ccxr_get_fts(struct ccx_common_timing_ctx *ctx, int current_field);
LLONG ccxr_get_fts_max(struct ccx_common_timing_ctx *ctx);
LLONG ccxr_get_visible_start(struct ccx_common_timing_ctx *ctx, int current_field);
LLONG ccxr_get_visible_end(struct ccx_common_timing_ctx *ctx, int current_field);
char *ccxr_print_mstime_static(LLONG mstime, char *buf);
void ccxr_print_debug_timing(struct ccx_common_timing_ctx *ctx);
void ccxr_calculate_ms_gop_time(struct gop_time_code *g);
int ccxr_gop_accepted(struct gop_time_code *g);
void ccx_common_timing_init(LLONG *file_position, int no_sync)
{
ccx_common_timing_settings.disable_sync_check = 0;
@@ -53,6 +65,9 @@ struct ccx_common_timing_ctx *init_timing_ctx(struct ccx_common_timing_settings_
ctx->current_pts = 0;
ctx->current_picture_coding_type = CCX_FRAME_TYPE_RESET_OR_UNKNOWN;
ctx->min_pts_adjusted = 0;
ctx->seen_known_frame_type = 0;
ctx->pending_min_pts = 0x01FFFFFFFFLL;
ctx->unknown_frame_count = 0;
ctx->min_pts = 0x01FFFFFFFFLL; // 33 bit
ctx->max_pts = 0;
ctx->sync_pts = 0;
@@ -73,236 +88,71 @@ struct ccx_common_timing_ctx *init_timing_ctx(struct ccx_common_timing_settings_
void add_current_pts(struct ccx_common_timing_ctx *ctx, LLONG pts)
{
set_current_pts(ctx, ctx->current_pts + pts);
return ccxr_add_current_pts(ctx, pts);
}
void set_current_pts(struct ccx_common_timing_ctx *ctx, LLONG pts)
{
LLONG prev_pts = ctx->current_pts;
ctx->current_pts = pts;
if (ctx->pts_set == 0)
ctx->pts_set = 1;
dbg_print(CCX_DMT_VIDES, "PTS: %s (%8u)", print_mstime_static(ctx->current_pts / (MPEG_CLOCK_FREQ / 1000)),
(unsigned)(ctx->current_pts));
dbg_print(CCX_DMT_VIDES, " FTS: %s \n", print_mstime_static(ctx->fts_now));
// Check if PTS reset
if (ctx->current_pts < prev_pts)
{
ctx->pts_reset = 1;
}
return ccxr_set_current_pts(ctx, pts);
}
int set_fts(struct ccx_common_timing_ctx *ctx)
{
int pts_jump = 0;
// ES don't have PTS unless GOP timing is used
if (!ctx->pts_set && ccx_common_timing_settings.is_elementary_stream)
return CCX_OK;
// First check for timeline jump (only when min_pts was set (implies sync_pts)).
int dif = 0;
if (ctx->pts_set == 2)
{
dif = (int)(ctx->current_pts - ctx->sync_pts) / MPEG_CLOCK_FREQ;
if (ccx_common_timing_settings.disable_sync_check)
{
// Disables sync check. Used for several input formats.
dif = 0;
}
if (dif < -0.2 || dif >= max_dif)
{
// ATSC specs: More than 3501 ms means missing component
ccx_common_logging.log_ftn("\nWarning: Reference clock has changed abruptly (%d seconds filepos=%lld), attempting to synchronize\n", (int)dif, *ccx_common_timing_settings.file_position);
ccx_common_logging.log_ftn("Last sync PTS value: %lld\n", ctx->sync_pts);
ccx_common_logging.log_ftn("Current PTS value: %lld\n", ctx->current_pts);
ccx_common_logging.log_ftn("Note: You can disable this behavior by adding -ignoreptsjumps to the parameters.\n");
pts_jump = 1;
pts_big_change = 1;
// Discard the gap if it is not on an I-frame or temporal reference zero.
if (ctx->current_tref != 0 && ctx->current_picture_coding_type != CCX_FRAME_TYPE_I_FRAME)
{
ctx->fts_now = ctx->fts_max;
ccx_common_logging.log_ftn("Change did not occur on first frame - probably a broken GOP\n");
return CCX_OK;
}
}
}
// If min_pts was set just before a rollover we compensate by "roll-oving" it too
if (ctx->pts_set == 2 && !ctx->min_pts_adjusted) // min_pts set
{
// We want to be aware of the upcoming rollover, not after it happened, so we don't take
// the 3 most significant bits but the 3 next ones
uint64_t min_pts_big_bits = (ctx->min_pts >> 30) & 7;
uint64_t cur_pts_big_bits = (ctx->current_pts >> 30) & 7;
if (cur_pts_big_bits == 7 && !min_pts_big_bits)
{
// Huge difference possibly means the first min_pts was actually just over the boundary
// Take the current_pts (smaller, accounting for the rollover) instead
ctx->min_pts = ctx->current_pts;
ctx->min_pts_adjusted = 1;
}
else if (cur_pts_big_bits >= 1 && cur_pts_big_bits <= 6) // Far enough from the boundary
{
// Prevent the eventual difference with min_pts to make a bad adjustment
ctx->min_pts_adjusted = 1;
}
}
// Set min_pts, fts_offset
if (ctx->pts_set != 0)
{
ctx->pts_set = 2;
// Use this part only the first time min_pts is set. Later treat
// it as a reference clock change
if (ctx->current_pts < ctx->min_pts && !pts_jump)
{
// If this is the first GOP, and seq 0 was not encountered yet
// we might reset min_pts/fts_offset again
ctx->min_pts = ctx->current_pts;
// Avoid next async test
ctx->sync_pts = (LLONG)(ctx->current_pts - ctx->current_tref * 1000.0 / current_fps * (MPEG_CLOCK_FREQ / 1000));
if (ctx->current_tref == 0)
{ // Earliest time in GOP.
ctx->fts_offset = 0;
}
else if (total_frames_count - frames_since_ref_time == 0)
{ // If this is the first frame (PES) there cannot be an offset.
// This part is also reached for dvr-ms/NTSC (RAW) as
// total_frames_count = frames_since_ref_time = 0 when
// this is called for the first time.
ctx->fts_offset = 0;
}
else
{ // It needs to be "+1" because the current frame is
// not yet counted.
ctx->fts_offset = (LLONG)((total_frames_count - frames_since_ref_time + 1) * 1000.0 / current_fps);
}
ccx_common_logging.debug_ftn(CCX_DMT_TIME, "\nFirst sync time PTS: %s %+lldms (time before this PTS)\n",
print_mstime_static(ctx->min_pts / (MPEG_CLOCK_FREQ / 1000)),
ctx->fts_offset);
ccx_common_logging.debug_ftn(CCX_DMT_TIME, "Total_frames_count %u frames_since_ref_time %u\n",
total_frames_count, frames_since_ref_time);
}
// -nosync disables syncing
if (pts_jump && !ccx_common_timing_settings.no_sync)
{
// The current time in the old time base is calculated using
// sync_pts (set at the beginning of the last GOP) plus the
// time of the frames since then.
ctx->fts_offset = ctx->fts_offset + (ctx->sync_pts - ctx->min_pts) / (MPEG_CLOCK_FREQ / 1000) + (LLONG)(frames_since_ref_time * 1000 / current_fps);
ctx->fts_max = ctx->fts_offset;
// Start counting again from here
ctx->pts_set = 1; // Force min to be set again
ctx->sync_pts2fts_set = 0; // Make note of the new conversion values
// Avoid next async test - the gap might have occured on
// current_tref != 0.
ctx->sync_pts = (LLONG)(ctx->current_pts - ctx->current_tref * 1000.0 / current_fps * (MPEG_CLOCK_FREQ / 1000));
// Set min_pts = sync_pts as this is used for fts_now
ctx->min_pts = ctx->sync_pts;
ccx_common_logging.debug_ftn(CCX_DMT_TIME, "\nNew min PTS time: %s %+lldms (time before this PTS)\n",
print_mstime_static(ctx->min_pts / (MPEG_CLOCK_FREQ / 1000)),
ctx->fts_offset);
}
}
// Set sync_pts, fts_offset
if (ctx->current_tref == 0)
ctx->sync_pts = ctx->current_pts;
// Reset counters
cb_field1 = 0;
cb_field2 = 0;
cb_708 = 0;
// Avoid wrong "Calc. difference" and "Asynchronous by" numbers
// for uninitialized min_pts
if (1) // CFS: Remove or think decent condition
{
if (ctx->pts_set)
{
// If pts_set is TRUE we have min_pts
ctx->fts_now = (LLONG)((ctx->current_pts - ctx->min_pts) / (MPEG_CLOCK_FREQ / 1000) + ctx->fts_offset);
if (!ctx->sync_pts2fts_set)
{
ctx->sync_pts2fts_pts = ctx->current_pts;
ctx->sync_pts2fts_fts = ctx->fts_now;
ctx->sync_pts2fts_set = 1;
}
}
else
{
// No PTS info at all!!
ccx_common_logging.log_ftn("Set PTS called without any global timestamp set\n");
return CCX_EINVAL;
}
}
if (ctx->fts_now > ctx->fts_max)
{
ctx->fts_max = ctx->fts_now;
}
// If PTS resets, then fix minimum_fts and fts_max
if (ctx->pts_reset)
{
ctx->minimum_fts = 0;
ctx->fts_max = ctx->fts_now;
ctx->pts_reset = 0;
}
return CCX_OK;
return ccxr_set_fts(ctx);
}
LLONG get_fts(struct ccx_common_timing_ctx *ctx, int current_field)
{
LLONG fts;
switch (current_field)
{
case 1:
fts = ctx->fts_now + ctx->fts_global + cb_field1 * 1001 / 30;
break;
case 2:
fts = ctx->fts_now + ctx->fts_global + cb_field2 * 1001 / 30;
break;
case 3:
fts = ctx->fts_now + ctx->fts_global + cb_708 * 1001 / 30;
break;
default:
fatal(CCX_COMMON_EXIT_BUG_BUG, "get_fts: unhandled branch");
}
// ccx_common_logging.debug_ftn(CCX_DMT_TIME, "[FTS] "
// "fts: %llu, fts_now: %llu, fts_global: %llu, current_field: %llu, cb_708: %llu\n",
// fts, fts_now, fts_global, current_field, cb_708);
return fts;
return ccxr_get_fts(ctx, current_field);
}
LLONG get_fts_max(struct ccx_common_timing_ctx *ctx)
{
// This returns the maximum FTS that belonged to a frame. Caption block
// counters are not applicable.
return ctx->fts_max + ctx->fts_global;
return ccxr_get_fts_max(ctx);
}
/**
* SCC Time formatting
* Note: buf must have at least 32 bytes available from the write position
*/
size_t print_scc_time(struct ccx_boundary_time time, char *buf)
{
char *fmt = "%02u:%02u:%02u;%02u";
double frame;
// Format produces "HH:MM:SS;FF" = 11 chars + null, use 32 for safety
const size_t max_time_len = 32;
frame = ((double)(time.time_in_ms - 1000 * (time.ss + 60 * (time.mm + 60 * time.hh))) * 29.97 / 1000);
return (size_t)snprintf(buf + time.set, max_time_len, fmt, time.hh, time.mm, time.ss, (unsigned)frame);
}
struct ccx_boundary_time get_time(LLONG time)
{
if (time < 0) // Avoid loss of data warning with abs()
time = -time;
struct ccx_boundary_time result;
result.hh = (unsigned)(time / 1000 / 60 / 60);
result.mm = (unsigned)(time / 1000 / 60 - 60 * result.hh);
result.ss = (unsigned)(time / 1000 - 60 * (result.mm + 60 * result.hh));
result.time_in_ms = time;
result.set = (time < 0 ? 1 : 0);
return result;
}
/**
* Fill buffer with a time string using specified format
* @param fmt has to contain 4 format specifiers for h, m, s and ms respectively
* Note: buf must have at least 32 bytes available from the write position
*/
size_t print_mstime_buff(LLONG mstime, char *fmt, char *buf)
{
unsigned hh, mm, ss, ms;
int signoffset = (mstime < 0 ? 1 : 0);
// Typical format produces "HH:MM:SS:MSS" = 12 chars + null, use 32 for safety
const size_t max_time_len = 32;
if (mstime < 0) // Avoid loss of data warning with abs()
mstime = -mstime;
@@ -314,7 +164,7 @@ size_t print_mstime_buff(LLONG mstime, char *fmt, char *buf)
buf[0] = '-';
return (size_t)sprintf(buf + signoffset, fmt, hh, mm, ss, ms);
return (size_t)snprintf(buf + signoffset, max_time_len, fmt, hh, mm, ss, ms);
}
/* Fill a static buffer with a time string (hh:mm:ss:ms) corresponding
@@ -322,63 +172,21 @@ size_t print_mstime_buff(LLONG mstime, char *fmt, char *buf)
char *print_mstime_static(LLONG mstime)
{
static char buf[15]; // 14 should be long enough
print_mstime_buff(mstime, "%02u:%02u:%02u:%03u", buf);
return buf;
return ccxr_print_mstime_static(mstime, buf);
}
/* Helper function for to display debug timing info. */
void print_debug_timing(struct ccx_common_timing_ctx *ctx)
{
// Avoid wrong "Calc. difference" and "Asynchronous by" numbers
// for uninitialized min_pts
LLONG tempmin_pts = (ctx->min_pts == 0x01FFFFFFFFLL ? ctx->sync_pts : ctx->min_pts);
ccx_common_logging.log_ftn("Sync time stamps: PTS: %s ",
print_mstime_static((ctx->sync_pts) / (MPEG_CLOCK_FREQ / 1000)));
ccx_common_logging.log_ftn("GOP: %s \n", print_mstime_static(gop_time.ms));
// Length first GOP to last GOP
LLONG goplenms = (LLONG)(gop_time.ms - first_gop_time.ms);
// Length at last sync point
LLONG ptslenms = (unsigned)((ctx->sync_pts - tempmin_pts) / (MPEG_CLOCK_FREQ / 1000) + ctx->fts_offset);
ccx_common_logging.log_ftn("Last FTS: %s",
print_mstime_static(get_fts_max(ctx)));
ccx_common_logging.log_ftn(" GOP start FTS: %s\n",
print_mstime_static(fts_at_gop_start));
// Times are based on last GOP and/or sync time
ccx_common_logging.log_ftn("Max FTS diff. to PTS: %6lldms GOP: %6lldms\n\n",
get_fts_max(ctx) + (LLONG)(1000.0 / current_fps) - ptslenms,
get_fts_max(ctx) + (LLONG)(1000.0 / current_fps) - goplenms);
return ccxr_print_debug_timing(ctx);
}
void calculate_ms_gop_time(struct gop_time_code *g)
{
int seconds = (g->time_code_hours * 3600) + (g->time_code_minutes * 60) + g->time_code_seconds;
g->ms = (LLONG)(1000 * (seconds + g->time_code_pictures / current_fps));
if (gop_rollover)
g->ms += 24 * 60 * 60 * 1000;
return ccxr_calculate_ms_gop_time(g);
}
int gop_accepted(struct gop_time_code *g)
{
if (!((g->time_code_hours <= 23) && (g->time_code_minutes <= 59) && (g->time_code_seconds <= 59) && (g->time_code_pictures <= 59)))
return 0;
if (gop_time.time_code_hours == 23 && gop_time.time_code_minutes == 59 &&
g->time_code_hours == 0 && g->time_code_minutes == 0)
{
gop_rollover = 1;
return 1;
}
if (gop_time.inited)
{
if (gop_time.ms > g->ms)
{
// We are going back in time but it's not a complete day rollover
return 0;
}
}
return 1;
return ccxr_gop_accepted(g);
}

View File

@@ -17,40 +17,43 @@ struct gop_time_code
struct ccx_common_timing_settings_t
{
int disable_sync_check; // If 1, timeline jumps will be ignored. This is important in several input formats that are assumed to have correct timing, no matter what.
int no_sync; // If 1, there will be no sync at all. Mostly useful for debugging.
int disable_sync_check; // If 1, timeline jumps will be ignored. This is important in several input formats that are assumed to have correct timing, no matter what.
int no_sync; // If 1, there will be no sync at all. Mostly useful for debugging.
int is_elementary_stream; // Needs to be set, as it's used in set_fts.
LLONG *file_position; // The position of the file
LLONG *file_position; // The position of the file
};
extern struct ccx_common_timing_settings_t ccx_common_timing_settings;
struct ccx_boundary_time
{
int hh,mm,ss;
int hh, mm, ss;
LLONG time_in_ms;
int set;
};
struct ccx_common_timing_ctx
{
int pts_set; // 0 = No, 1 = received, 2 = min_pts set
int min_pts_adjusted; // 0 = No, 1=Yes (don't adjust again)
int pts_set; // 0 = No, 1 = received, 2 = min_pts set
int min_pts_adjusted; // 0 = No, 1=Yes (don't adjust again)
int seen_known_frame_type; // 0 = No, 1 = Yes. Tracks if we've seen a frame with known type
LLONG pending_min_pts; // Minimum PTS seen while waiting for frame type determination
unsigned int unknown_frame_count; // Count of set_fts calls with unknown frame type
LLONG current_pts;
enum ccx_frame_type current_picture_coding_type;
int current_tref; // Store temporal reference of current frame
int current_tref; // Store temporal reference of current frame
LLONG min_pts;
LLONG max_pts;
LLONG sync_pts;
LLONG minimum_fts; // No screen should start before this FTS
LLONG fts_now; // Time stamp of current file (w/ fts_offset, w/o fts_global)
LLONG fts_now; // Time stamp of current file (w/ fts_offset, w/o fts_global)
LLONG fts_offset; // Time before first sync_pts
LLONG fts_fc_offset; // Time before first GOP
LLONG fts_max; // Remember the maximum fts that we saw in current file
LLONG fts_max; // Remember the maximum fts that we saw in current file
LLONG fts_global; // Duration of previous files (-ve mode)
int sync_pts2fts_set; // 0 = No, 1 = Yes
LLONG sync_pts2fts_fts;
LLONG sync_pts2fts_pts;
int pts_reset; // 0 = No, 1 = Yes. PTS resets when current_pts is lower than prev
int pts_reset; // 0 = No, 1 = Yes. PTS resets when current_pts is lower than prev
};
// Count 608 (per field) and 708 blocks since last set_fts() call
extern int cb_field1, cb_field2, cb_708;
@@ -60,7 +63,6 @@ extern int MPEG_CLOCK_FREQ; // This is part of the standard
extern int max_dif;
extern unsigned pts_big_change;
extern enum ccx_frame_type current_picture_coding_type;
extern double current_fps;
extern int frames_since_ref_time;
@@ -77,13 +79,15 @@ struct ccx_common_timing_ctx *init_timing_ctx(struct ccx_common_timing_settings_
void set_current_pts(struct ccx_common_timing_ctx *ctx, LLONG pts);
void add_current_pts(struct ccx_common_timing_ctx *ctx, LLONG pts);
struct ccx_boundary_time get_time(LLONG mstime);
size_t print_scc_time(struct ccx_boundary_time time, char *buf);
int set_fts(struct ccx_common_timing_ctx *ctx);
LLONG get_fts(struct ccx_common_timing_ctx *ctx, int current_field);
LLONG get_fts_max(struct ccx_common_timing_ctx *ctx);
char *print_mstime_static(LLONG mstime);
size_t print_mstime_buff(LLONG mstime, char *fmt, char *buf);
void print_debug_timing(struct ccx_common_timing_ctx *ctx);
int gop_accepted(struct gop_time_code* g);
int gop_accepted(struct gop_time_code *g);
void calculate_ms_gop_time(struct gop_time_code *g);
#endif

View File

@@ -10,7 +10,7 @@ static const int rowdata[] = {11, -1, 1, 2, 3, 4, 12, 13, 14, 15, 5, 6, 7, 8, 9,
// Relationship between the first PAC byte and the row number
int in_xds_mode = 0;
//unsigned char str[2048]; // Another generic general purpose buffer
// unsigned char str[2048]; // Another generic general purpose buffer
const unsigned char pac2_attribs[][3] = // Color, font, ident
{
@@ -127,6 +127,8 @@ ccx_decoder_608_context *ccx_decoder_608_init_library(struct ccx_decoder_608_set
ccx_decoder_608_context *data = NULL;
data = malloc(sizeof(ccx_decoder_608_context));
if (!data)
return NULL;
data->cursor_column = 0;
data->cursor_row = 0;
@@ -147,10 +149,11 @@ ccx_decoder_608_context *ccx_decoder_608_init_library(struct ccx_decoder_608_set
data->my_field = field;
data->my_channel = channel;
data->have_cursor_position = 0;
data->rollup_from_popon = 0;
data->output_format = output_format;
data->cc_to_stdout = cc_to_stdout;
data->textprinted = 0;
data->ts_start_of_current_line = 0;
// Note: ts_start_of_current_line already set to -1 above
data->halt = halt;
@@ -225,7 +228,9 @@ void write_char(const unsigned char c, ccx_decoder_608_context *context)
if (use_buffer->empty)
{
if (MODE_POPON != context->mode)
// Don't set start time if we're in a transition from pop-on to roll-up
// In this case, start time will be set when CR causes scrolling
if (MODE_POPON != context->mode && !context->rollup_from_popon)
context->current_visible_start_ms = get_visible_start(context->timing, context->my_field);
}
use_buffer->empty = 0;
@@ -263,7 +268,7 @@ void handle_text_attr(const unsigned char c1, const unsigned char c2, ccx_decode
font_text[context->font]);
// Mid-row codes should put a non-transparent space at the current position
// and advance the cursor
//so use write_char
// so use write_char
write_char(0x20, context);
}
}
@@ -311,12 +316,13 @@ int write_cc_buffer(ccx_decoder_608_context *context, struct cc_subtitle *sub)
if (!data->empty && context->output_format != CCX_OF_NULL)
{
sub->data = (struct eia608_screen *)realloc(sub->data, (sub->nb_data + 1) * sizeof(*data));
if (!sub->data)
struct eia608_screen *new_data = (struct eia608_screen *)realloc(sub->data, (sub->nb_data + 1) * sizeof(*data));
if (!new_data)
{
ccx_common_logging.log_ftn("No Memory left");
return 0;
}
sub->data = new_data;
sub->datatype = CC_DATATYPE_GENERIC;
memcpy(((struct eia608_screen *)sub->data) + sub->nb_data, data, sizeof(*data));
sub->nb_data++;
@@ -380,12 +386,13 @@ int write_cc_line(ccx_decoder_608_context *context, struct cc_subtitle *sub)
if (!data->empty)
{
sub->data = (struct eia608_screen *)realloc(sub->data, (sub->nb_data + 1) * sizeof(*data));
if (!sub->data)
struct eia608_screen *new_data = (struct eia608_screen *)realloc(sub->data, (sub->nb_data + 1) * sizeof(*data));
if (!new_data)
{
ccx_common_logging.log_ftn("No Memory left");
return 0;
}
sub->data = new_data;
memcpy(((struct eia608_screen *)sub->data) + sub->nb_data, data, sizeof(*data));
data = (struct eia608_screen *)sub->data + sub->nb_data;
sub->datatype = CC_DATATYPE_GENERIC;
@@ -720,6 +727,10 @@ void handle_command(unsigned char c1, const unsigned char c2, ccx_decoder_608_co
if (write_cc_buffer(context, sub))
context->screenfuls_counter++;
erase_memory(context, true);
// Track transition from pop-on/paint-on to roll-up for timing adjustment
// Start time will be set when CR causes scrolling (matching FFmpeg behavior)
context->rollup_from_popon = 1;
context->ts_start_of_current_line = -1;
}
erase_memory(context, false);
@@ -772,6 +783,15 @@ void handle_command(unsigned char c1, const unsigned char c2, ccx_decoder_608_co
changes = check_roll_up(context);
if (changes)
{
// Handle pop-on to roll-up transition timing
// Use ts_start_of_current_line (when current line started) as the start time
// This matches FFmpeg's behavior of timestamping when the display changed
if (context->rollup_from_popon && context->ts_start_of_current_line > 0)
{
context->current_visible_start_ms = context->ts_start_of_current_line;
context->rollup_from_popon = 0;
}
// Only if the roll up would actually cause a line to disappear we write the buffer
if (context->output_format != CCX_OF_TRANSCRIPT)
{
@@ -781,8 +801,18 @@ void handle_command(unsigned char c1, const unsigned char c2, ccx_decoder_608_co
erase_memory(context, true); // Make sure the lines we just wrote aren't written again
}
}
roll_up(context); // The roll must be done anyway of course.
context->ts_start_of_current_line = -1; // Unknown.
roll_up(context); // The roll must be done anyway of course.
// When in pop-on to roll-up transition with changes=0 (first CR, only 1 line),
// preserve the CR time so the next caption uses the display state change time,
// not the character typing time. This matches FFmpeg's timing behavior.
if (context->rollup_from_popon && !changes)
{
context->ts_start_of_current_line = get_fts(context->timing, context->my_field);
}
else
{
context->ts_start_of_current_line = -1; // Unknown.
}
if (changes)
context->current_visible_start_ms = get_visible_start(context->timing, context->my_field);
context->cursor_column = 0;
@@ -836,8 +866,8 @@ void handle_command(unsigned char c1, const unsigned char c2, ccx_decoder_608_co
break;
case COM_RESUMEDIRECTCAPTIONING:
context->mode = MODE_PAINTON;
//ccx_common_logging.log_ftn ("\nWarning: Received ResumeDirectCaptioning, this mode is almost impossible.\n");
//ccx_common_logging.log_ftn ("to transcribe to a text file.\n");
// ccx_common_logging.log_ftn ("\nWarning: Received ResumeDirectCaptioning, this mode is almost impossible.\n");
// ccx_common_logging.log_ftn ("to transcribe to a text file.\n");
break;
default:
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\rNot yet implemented.\n");
@@ -1029,20 +1059,20 @@ int check_channel(unsigned char c1, ccx_decoder_608_context *context)
}
/* Handle Command, special char or attribute and also check for
* channel changes.
* Returns 1 if something was written to screen, 0 otherwise */
* channel changes.
* Returns 1 if something was written to screen, 0 otherwise */
int disCommand(unsigned char hi, unsigned char lo, ccx_decoder_608_context *context, struct cc_subtitle *sub)
{
int wrote_to_screen = 0;
/* Full channel changes are only allowed for "GLOBAL CODES",
* "OTHER POSITIONING CODES", "BACKGROUND COLOR CODES",
* "MID-ROW CODES".
* "PREAMBLE ACCESS CODES", "BACKGROUND COLOR CODES" and
* SPECIAL/SPECIAL CHARACTERS allow only switching
* between 1&3 or 2&4. */
* "OTHER POSITIONING CODES", "BACKGROUND COLOR CODES",
* "MID-ROW CODES".
* "PREAMBLE ACCESS CODES", "BACKGROUND COLOR CODES" and
* SPECIAL/SPECIAL CHARACTERS allow only switching
* between 1&3 or 2&4. */
context->new_channel = check_channel(hi, context);
//if (wb->data608->channel!=cc_channel)
// if (wb->data608->channel!=cc_channel)
// continue;
if (hi >= 0x18 && hi <= 0x1f)
@@ -1105,17 +1135,21 @@ int process608(const unsigned char *data, int length, void *private_data, struct
struct ccx_decoder_608_context *context;
int i;
if (dec_ctx->current_field == 1)
if (dec_ctx->current_field == 1 && (dec_ctx->extract == 1 || dec_ctx->extract == 12))
{
context = dec_ctx->context_cc608_field_1;
}
else if (dec_ctx->current_field == 2 && (dec_ctx->extract == 2 || dec_ctx->extract == 12))
{
context = dec_ctx->context_cc608_field_2;
}
else if (dec_ctx->current_field == 2 && dec_ctx->extract == 1)
{
context = NULL;
}
else
{
context = dec_ctx->context_cc608_field_2;
return -1;
}
if (context)
{
@@ -1240,9 +1274,9 @@ int process608(const unsigned char *data, int length, void *private_data, struct
if (!context->textprinted && context->channel == context->my_channel)
{ // Current FTS information after the characters are shown
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "Current FTS: %s\n", print_mstime_static(get_fts(dec_ctx->timing, context->my_field)));
//printf(" N:%u", unsigned(fts_now) );
//printf(" G:%u", unsigned(fts_global) );
//printf(" F:%d %d %d %d\n",
// printf(" N:%u", unsigned(fts_now) );
// printf(" G:%u", unsigned(fts_global) );
// printf(" F:%d %d %d %d\n",
// current_field, cb_field1, cb_field2, cb_708 );
}
@@ -1284,7 +1318,7 @@ unsigned char *debug_608_to_ASC(unsigned char *cc_data, int channel)
if (hi >= 0x20)
{
output[0] = hi;
output[1] = (lo >= 20 ? lo : '.');
output[1] = (lo >= 0x20 ? lo : '.');
output[2] = '\x00';
}
else

View File

@@ -1,5 +1,5 @@
#ifndef CCX_DECODER_608_H
#define CCX_DECODER_608_H
#define CCX_DECODER_608_H
#include "ccx_common_platform.h"
#include "ccx_common_structs.h"
#include "ccx_decoders_structs.h"
@@ -19,11 +19,11 @@ struct ccx_decoder_608_report
typedef struct ccx_decoder_608_settings
{
int direct_rollup; // Write roll-up captions directly instead of line by line?
int force_rollup; // 0=Disabled, 1, 2 or 3=max lines in roll-up mode
int no_rollup; // If 1, write one line at a time
int direct_rollup; // Write roll-up captions directly instead of line by line?
int force_rollup; // 0=Disabled, 1, 2 or 3=max lines in roll-up mode
int no_rollup; // If 1, write one line at a time
enum ccx_decoder_608_color_code default_color; // Default color to use.
int screens_to_process; // How many screenfuls we want? Use -1 for unlimited
int screens_to_process; // How many screenfuls we want? Use -1 for unlimited
struct ccx_decoder_608_report *report;
} ccx_decoder_608_settings;
@@ -34,33 +34,33 @@ typedef struct ccx_decoder_608_context
struct eia608_screen buffer2;
int cursor_row, cursor_column;
int visible_buffer;
int screenfuls_counter; // Number of meaningful screenfuls written
int screenfuls_counter; // Number of meaningful screenfuls written
LLONG current_visible_start_ms; // At what time did the current visible buffer became so?
enum cc_modes mode;
unsigned char last_c1, last_c2;
int channel; // Currently selected channel
enum ccx_decoder_608_color_code current_color; // Color we are currently using to write
enum font_bits font; // Font we are currently using to write
int channel; // Currently selected channel
enum ccx_decoder_608_color_code current_color; // Color we are currently using to write
enum font_bits font; // Font we are currently using to write
int rollup_base_row;
LLONG ts_start_of_current_line; /* Time at which the first character for current line was received, =-1 no character received yet */
LLONG ts_last_char_received; /* Time at which the last written character was received, =-1 no character received yet */
int new_channel; // The new channel after a channel change
int my_field; // Used for sanity checks
int my_channel; // Used for sanity checks
long bytes_processed_608; // To be written ONLY by process_608
LLONG ts_last_char_received; /* Time at which the last written character was received, =-1 no character received yet */
int new_channel; // The new channel after a channel change
int my_field; // Used for sanity checks
int my_channel; // Used for sanity checks
int rollup_from_popon; // Track transition from pop-on/paint-on to roll-up mode
int64_t bytes_processed_608; // To be written ONLY by process_608
int have_cursor_position;
int *halt; // Can be used to halt the feeding of caption data. Set to 1 if screens_to_progress != -1 && screenfuls_counter >= screens_to_process
int cc_to_stdout; // If this is set to 1, the stdout will be flushed when data was written to the screen during a process_608 call.
int *halt; // Can be used to halt the feeding of caption data. Set to 1 if screens_to_progress != -1 && screenfuls_counter >= screens_to_process
int cc_to_stdout; // If this is set to 1, the stdout will be flushed when data was written to the screen during a process_608 call.
struct ccx_decoder_608_report *report;
LLONG subs_delay; // ms to delay (or advance) subs
LLONG subs_delay; // ms to delay (or advance) subs
enum ccx_output_format output_format; // What kind of output format should be used?
int textprinted;
struct ccx_common_timing_ctx *timing;
} ccx_decoder_608_context;
#define MAX_COLOR 10
extern const char *color_text[MAX_COLOR][2];
@@ -80,7 +80,7 @@ enum command_code
COM_ERASENONDISPLAYEDMEMORY = 11,
COM_BACKSPACE = 12,
COM_RESUMETEXTDISPLAY = 13,
COM_ALARMOFF =14,
COM_ALARMOFF = 14,
COM_ALARMON = 15,
COM_DELETETOENDOFROW = 16,
COM_RESUMEDIRECTCAPTIONING = 17,
@@ -89,15 +89,14 @@ enum command_code
COM_FAKE_RULLUP1 = 18
};
void ccx_decoder_608_dinit_library(void **ctx);
/*
*
*/
ccx_decoder_608_context* ccx_decoder_608_init_library(struct ccx_decoder_608_settings *settings, int channel,
int field, int *halt,
int cc_to_stdout,
enum ccx_output_format output_format, struct ccx_common_timing_ctx *timing);
ccx_decoder_608_context *ccx_decoder_608_init_library(struct ccx_decoder_608_settings *settings, int channel,
int field, int *halt,
int cc_to_stdout,
enum ccx_output_format output_format, struct ccx_common_timing_ctx *timing);
/**
* @param data raw cc608 data to be processed

View File

@@ -104,7 +104,7 @@ dtvcc_pen_attribs dtvcc_default_pen_attribs =
dtvcc_window_attribs dtvcc_predefined_window_styles[] =
{
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Dummy, unused (position 0 doesn't use the table)
{ //1 - NTSC Style PopUp Captions
{ // 1 - NTSC Style PopUp Captions
DTVCC_WINDOW_JUSTIFY_LEFT,
DTVCC_WINDOW_PD_LEFT_RIGHT,
DTVCC_WINDOW_SD_BOTTOM_TOP,
@@ -116,7 +116,7 @@ dtvcc_window_attribs dtvcc_predefined_window_styles[] =
DTVCC_WINDOW_FO_SOLID,
DTVCC_WINDOW_BORDER_NONE,
0},
{//2 - PopUp Captions w/o Black Background
{// 2 - PopUp Captions w/o Black Background
DTVCC_WINDOW_JUSTIFY_LEFT,
DTVCC_WINDOW_PD_LEFT_RIGHT,
DTVCC_WINDOW_SD_BOTTOM_TOP,
@@ -128,7 +128,7 @@ dtvcc_window_attribs dtvcc_predefined_window_styles[] =
DTVCC_WINDOW_FO_TRANSPARENT,
DTVCC_WINDOW_BORDER_NONE,
0},
{//3 - NTSC Style Centered PopUp Captions
{// 3 - NTSC Style Centered PopUp Captions
DTVCC_WINDOW_JUSTIFY_CENTER,
DTVCC_WINDOW_PD_LEFT_RIGHT,
DTVCC_WINDOW_SD_BOTTOM_TOP,
@@ -140,7 +140,7 @@ dtvcc_window_attribs dtvcc_predefined_window_styles[] =
DTVCC_WINDOW_FO_SOLID,
DTVCC_WINDOW_BORDER_NONE,
0},
{//4 - NTSC Style RollUp Captions
{// 4 - NTSC Style RollUp Captions
DTVCC_WINDOW_JUSTIFY_LEFT,
DTVCC_WINDOW_PD_LEFT_RIGHT,
DTVCC_WINDOW_SD_BOTTOM_TOP,
@@ -152,7 +152,7 @@ dtvcc_window_attribs dtvcc_predefined_window_styles[] =
DTVCC_WINDOW_FO_SOLID,
DTVCC_WINDOW_BORDER_NONE,
0},
{//5 - RollUp Captions w/o Black Background
{// 5 - RollUp Captions w/o Black Background
DTVCC_WINDOW_JUSTIFY_LEFT,
DTVCC_WINDOW_PD_LEFT_RIGHT,
DTVCC_WINDOW_SD_BOTTOM_TOP,
@@ -164,7 +164,7 @@ dtvcc_window_attribs dtvcc_predefined_window_styles[] =
DTVCC_WINDOW_FO_TRANSPARENT,
DTVCC_WINDOW_BORDER_NONE,
0},
{//6 - NTSC Style Centered RollUp Captions
{// 6 - NTSC Style Centered RollUp Captions
DTVCC_WINDOW_JUSTIFY_CENTER,
DTVCC_WINDOW_PD_LEFT_RIGHT,
DTVCC_WINDOW_SD_BOTTOM_TOP,
@@ -176,7 +176,7 @@ dtvcc_window_attribs dtvcc_predefined_window_styles[] =
DTVCC_WINDOW_FO_SOLID,
DTVCC_WINDOW_BORDER_NONE,
0},
{//7 - Ticker tape
{// 7 - Ticker tape
DTVCC_WINDOW_JUSTIFY_LEFT,
DTVCC_WINDOW_PD_TOP_BOTTOM,
DTVCC_WINDOW_SD_RIGHT_LEFT,
@@ -240,7 +240,7 @@ void dtvcc_window_clear_text(dtvcc_window *window)
void dtvcc_window_clear(dtvcc_service_decoder *decoder, int window_id)
{
dtvcc_window_clear_text(&decoder->windows[window_id]);
//OPT fill window with a window fill color
// OPT fill window with a window fill color
}
void dtvcc_window_apply_style(dtvcc_window *window, dtvcc_window_attribs *style)
@@ -258,7 +258,7 @@ void dtvcc_window_apply_style(dtvcc_window *window, dtvcc_window_attribs *style)
window->attribs.word_wrap = style->word_wrap;
}
//#define DTVCC_PRINT_DEBUG
// #define DTVCC_PRINT_DEBUG
#ifdef DTVCC_PRINT_DEBUG
int dtvcc_is_win_row_empty(dtvcc_window *window, int row_index)
@@ -503,7 +503,7 @@ int dtvcc_is_window_overlapping(dtvcc_service_decoder *decoder, dtvcc_window *wi
{
flag = OVERLAPPING_WITH_HIGH_PRIORITY;
}
//priority is either higher or equals for *window , hence overlaps decoder->windows[i]
// priority is either higher or equals for *window , hence overlaps decoder->windows[i]
}
}
}
@@ -608,16 +608,16 @@ void dtvcc_window_copy_to_screen(dtvcc_service_decoder *decoder, dtvcc_window *w
void dtvcc_screen_print(dtvcc_ctx *dtvcc, dtvcc_service_decoder *decoder)
{
//TODO use priorities to solve windows overlap (with a video sample, please)
//qsort(wnd, visible, sizeof(dtvcc_window *), dtvcc_compare_win_priorities);
// TODO use priorities to solve windows overlap (with a video sample, please)
// qsort(wnd, visible, sizeof(dtvcc_window *), dtvcc_compare_win_priorities);
ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] dtvcc_screen_print\n");
dtvcc_screen_update_time_hide(decoder->tv, get_visible_end(dtvcc->timing, 3));
#ifdef DTVCC_PRINT_DEBUG
//ccx_common_logging.debug_ftn(CCX_DMT_GENERIC_NOTICES, "[CEA-708] TV dump:\n");
//dtvcc_write_debug(decoder->tv);
// ccx_common_logging.debug_ftn(CCX_DMT_GENERIC_NOTICES, "[CEA-708] TV dump:\n");
// dtvcc_write_debug(decoder->tv);
#endif
decoder->cc_count++;
decoder->tv->cc_count++;
@@ -653,14 +653,14 @@ void dtvcc_process_ff(dtvcc_service_decoder *decoder)
dtvcc_window *window = &decoder->windows[decoder->current_window];
window->pen_column = 0;
window->pen_row = 0;
//CEA-708-D doesn't say we have to clear neither window text nor text line,
//but it seems we have to clean the line
//dtvcc_window_clear_text(window);
// CEA-708-D doesn't say we have to clear neither window text nor text line,
// but it seems we have to clean the line
// dtvcc_window_clear_text(window);
}
void dtvcc_process_etx(dtvcc_service_decoder *decoder)
{
//it can help decoders with screen output, but could it help us?
// it can help decoders with screen output, but could it help us?
}
void dtvcc_process_bs(dtvcc_service_decoder *decoder)
@@ -671,8 +671,8 @@ void dtvcc_process_bs(dtvcc_service_decoder *decoder)
return;
}
//it looks strange, but in some videos (rarely) we have a backspace command
//we just print one character over another
// it looks strange, but in some videos (rarely) we have a backspace command
// we just print one character over another
int cw = decoder->current_window;
dtvcc_window *window = &decoder->windows[cw];
@@ -764,14 +764,12 @@ void dtvcc_process_cr(dtvcc_ctx *dtvcc, dtvcc_service_decoder *decoder)
if (window->is_defined)
{
ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] dtvcc_process_cr: rolling up\n");
dtvcc_window_update_time_hide(window, dtvcc->timing);
dtvcc_window_copy_to_screen(decoder, window);
dtvcc_screen_print(dtvcc, decoder);
if (rollup_required)
{
ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] dtvcc_process_cr: rolling up\n");
dtvcc_window_copy_to_screen(decoder, window);
dtvcc_screen_print(dtvcc, decoder);
if (dtvcc->no_rollup)
dtvcc_window_clear_row(window, window->pen_row);
else
@@ -826,27 +824,6 @@ void dtvcc_process_character(dtvcc_service_decoder *decoder, dtvcc_symbol symbol
}
}
void dtvcc_decoder_flush(dtvcc_ctx *dtvcc, dtvcc_service_decoder *decoder)
{
ccx_common_logging.debug_ftn(
CCX_DMT_708, "[CEA-708] dtvcc_decoder_flush: Flushing decoder\n");
int screen_content_changed = 0;
for (int i = 0; i < CCX_DTVCC_MAX_WINDOWS; i++)
{
dtvcc_window *window = &decoder->windows[i];
if (window->visible)
{
screen_content_changed = 1;
dtvcc_window_update_time_hide(window, dtvcc->timing);
dtvcc_window_copy_to_screen(decoder, window);
window->visible = 0;
}
}
if (screen_content_changed)
dtvcc_screen_print(dtvcc, decoder);
dtvcc_write_done(decoder->tv, dtvcc->encoder);
}
//---------------------------------- COMMANDS ------------------------------------
void dtvcc_handle_CWx_SetCurrentWindow(dtvcc_service_decoder *decoder, int window_id)
@@ -1018,9 +995,9 @@ void dtvcc_handle_DFx_DefineWindow(dtvcc_service_decoder *decoder, int window_id
int anchor_vertical = data[2] & 0x7f;
int relative_pos = data[2] >> 7;
int anchor_horizontal = data[3];
int row_count = (data[4] & 0xf) + 1; //according to CEA-708-D
int row_count = (data[4] & 0xf) + 1; // according to CEA-708-D
int anchor_point = data[4] >> 4;
int col_count = (data[5] & 0x3f) + 1; //according to CEA-708-D
int col_count = (data[5] & 0x3f) + 1; // according to CEA-708-D
int pen_style = data[6] & 0x7;
int win_style = (data[6] >> 3) & 0x7;
@@ -1048,6 +1025,18 @@ void dtvcc_handle_DFx_DefineWindow(dtvcc_service_decoder *decoder, int window_id
if (anchor_horizontal > CCX_DTVCC_SCREENGRID_COLUMNS - col_count)
anchor_horizontal = CCX_DTVCC_SCREENGRID_COLUMNS - col_count;
if (window->is_defined)
{
if (row_count < window->row_count)
{
// Remove the oldest row if the row count is reduced
for (int i = row_count; i < window->row_count; i++)
{
dtvcc_window_rollup(decoder, window);
}
}
}
window->priority = priority;
window->col_lock = col_lock;
window->row_lock = row_lock;
@@ -1074,7 +1063,7 @@ void dtvcc_handle_DFx_DefineWindow(dtvcc_service_decoder *decoder, int window_id
pen_style = 1;
}
//Apply windows attribute presets
// Apply windows attribute presets
if (win_style > 0 && win_style < 8)
{
window->win_style = win_style;
@@ -1093,7 +1082,7 @@ void dtvcc_handle_DFx_DefineWindow(dtvcc_service_decoder *decoder, int window_id
if (pen_style > 0)
{
//TODO apply static pen_style preset
// TODO apply static pen_style preset
window->pen_style = pen_style;
}
@@ -1380,7 +1369,7 @@ void dtvcc_handle_DLC_DelayCancel(dtvcc_service_decoder *decoder)
//-------------------------- CHARACTERS AND COMMANDS -------------------------
void dtvcc_handle_C0_P16(dtvcc_service_decoder *decoder, unsigned char *data) //16-byte chars always have 2 bytes
void dtvcc_handle_C0_P16(dtvcc_service_decoder *decoder, unsigned char *data) // 16-byte chars always have 2 bytes
{
if (decoder->current_window == -1)
{
@@ -1408,7 +1397,7 @@ int dtvcc_handle_G0(dtvcc_service_decoder *decoder, unsigned char *data, int dat
if (decoder->current_window == -1)
{
ccx_common_logging.log_ftn("[CEA-708] dtvcc_handle_G0: Window has to be defined first\n");
return data_length;
return 1;
}
unsigned char c = data[0];
@@ -1684,7 +1673,7 @@ void dtvcc_process_service_block(dtvcc_ctx *dtvcc,
unsigned char *data,
int data_length)
{
//dump(CCX_DMT_708, data, data_length, 0, 0);
// dump(CCX_DMT_708, data, data_length, 0, 0);
int i = 0;
while (i < data_length)
@@ -1706,7 +1695,7 @@ void dtvcc_process_service_block(dtvcc_ctx *dtvcc,
ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] dtvcc_process_service_block: "
"There was a problem handling the data. Reseting service decoder\n");
// TODO: Not sure if a local reset is going to be helpful here.
//dtvcc_windows_reset(decoder);
// dtvcc_windows_reset(decoder);
return;
}
}
@@ -1744,10 +1733,10 @@ void dtvcc_process_current_packet(dtvcc_ctx *dtvcc, int len)
ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] dtvcc_process_current_packet: "
"Unexpected sequence number, it is [%d] but should be [%d]\n",
seq, (dtvcc->last_sequence + 1) % 4);
//WARN: if we reset decoders here, buffer will not be written
//WARN: resetting decoders breaks some samples
//dtvcc_decoders_reset(dtvcc);
//return;
// WARN: if we reset decoders here, buffer will not be written
// WARN: resetting decoders breaks some samples
// dtvcc_decoders_reset(dtvcc);
// return;
}
dtvcc->last_sequence = seq;

View File

@@ -6,7 +6,7 @@
#include "ccx_common_constants.h"
#include "ccx_common_structs.h"
#define CCX_DTVCC_MAX_PACKET_LENGTH 128 //According to EIA-708B, part 5
#define CCX_DTVCC_MAX_PACKET_LENGTH 128 // According to EIA-708B, part 5
#define CCX_DTVCC_MAX_SERVICES 63
#define CCX_DTVCC_MAX_ROWS 15
@@ -14,7 +14,7 @@
* This value should be 32, but there were 16-bit encoded samples (from Korea),
* where RowCount calculated another way and equals 46 (23[8bit]*2)
*/
#define CCX_DTVCC_MAX_COLUMNS (32*2)
#define CCX_DTVCC_MAX_COLUMNS (32 * 2)
#define CCX_DTVCC_SCREENGRID_ROWS 75
#define CCX_DTVCC_SCREENGRID_COLUMNS 210
@@ -30,14 +30,14 @@
enum DTVCC_COMMANDS_C0_CODES
{
DTVCC_C0_NUL = 0x00,
DTVCC_C0_ETX = 0x03,
DTVCC_C0_BS = 0x08,
DTVCC_C0_FF = 0x0c,
DTVCC_C0_CR = 0x0d,
DTVCC_C0_HCR = 0x0e,
DTVCC_C0_NUL = 0x00,
DTVCC_C0_ETX = 0x03,
DTVCC_C0_BS = 0x08,
DTVCC_C0_FF = 0x0c,
DTVCC_C0_CR = 0x0d,
DTVCC_C0_HCR = 0x0e,
DTVCC_C0_EXT1 = 0x10,
DTVCC_C0_P16 = 0x18
DTVCC_C0_P16 = 0x18
};
enum DTVCC_COMMANDS_C1_CODES
@@ -86,21 +86,21 @@ struct DTVCC_S_COMMANDS_C1
enum dtvcc_window_justify
{
DTVCC_WINDOW_JUSTIFY_LEFT = 0,
DTVCC_WINDOW_JUSTIFY_RIGHT = 1,
DTVCC_WINDOW_JUSTIFY_CENTER = 2,
DTVCC_WINDOW_JUSTIFY_FULL = 3
DTVCC_WINDOW_JUSTIFY_LEFT = 0,
DTVCC_WINDOW_JUSTIFY_RIGHT = 1,
DTVCC_WINDOW_JUSTIFY_CENTER = 2,
DTVCC_WINDOW_JUSTIFY_FULL = 3
};
enum dtvcc_window_pd //Print Direction
enum dtvcc_window_pd // Print Direction
{
DTVCC_WINDOW_PD_LEFT_RIGHT = 0, //left -> right
DTVCC_WINDOW_PD_LEFT_RIGHT = 0, // left -> right
DTVCC_WINDOW_PD_RIGHT_LEFT = 1,
DTVCC_WINDOW_PD_TOP_BOTTOM = 2,
DTVCC_WINDOW_PD_BOTTOM_TOP = 3
};
enum dtvcc_window_sd //Scroll Direction
enum dtvcc_window_sd // Scroll Direction
{
DTVCC_WINDOW_SD_LEFT_RIGHT = 0,
DTVCC_WINDOW_SD_RIGHT_LEFT = 1,
@@ -108,14 +108,14 @@ enum dtvcc_window_sd //Scroll Direction
DTVCC_WINDOW_SD_BOTTOM_TOP = 3
};
enum dtvcc_window_sde //Scroll Display Effect
enum dtvcc_window_sde // Scroll Display Effect
{
DTVCC_WINDOW_SDE_SNAP = 0,
DTVCC_WINDOW_SDE_FADE = 1,
DTVCC_WINDOW_SDE_WIPE = 2
};
enum dtvcc_window_ed //Effect Direction
enum dtvcc_window_ed // Effect Direction
{
DTVCC_WINDOW_ED_LEFT_RIGHT = 0,
DTVCC_WINDOW_ED_RIGHT_LEFT = 1,
@@ -123,91 +123,91 @@ enum dtvcc_window_ed //Effect Direction
DTVCC_WINDOW_ED_BOTTOM_TOP = 3
};
enum dtvcc_window_fo //Fill Opacity
enum dtvcc_window_fo // Fill Opacity
{
DTVCC_WINDOW_FO_SOLID = 0,
DTVCC_WINDOW_FO_FLASH = 1,
DTVCC_WINDOW_FO_TRANSLUCENT = 2,
DTVCC_WINDOW_FO_SOLID = 0,
DTVCC_WINDOW_FO_FLASH = 1,
DTVCC_WINDOW_FO_TRANSLUCENT = 2,
DTVCC_WINDOW_FO_TRANSPARENT = 3
};
enum dtvcc_window_border
{
DTVCC_WINDOW_BORDER_NONE = 0,
DTVCC_WINDOW_BORDER_RAISED = 1,
DTVCC_WINDOW_BORDER_DEPRESSED = 2,
DTVCC_WINDOW_BORDER_UNIFORM = 3,
DTVCC_WINDOW_BORDER_SHADOW_LEFT = 4,
DTVCC_WINDOW_BORDER_SHADOW_RIGHT = 5
DTVCC_WINDOW_BORDER_NONE = 0,
DTVCC_WINDOW_BORDER_RAISED = 1,
DTVCC_WINDOW_BORDER_DEPRESSED = 2,
DTVCC_WINDOW_BORDER_UNIFORM = 3,
DTVCC_WINDOW_BORDER_SHADOW_LEFT = 4,
DTVCC_WINDOW_BORDER_SHADOW_RIGHT = 5
};
enum dtvcc_pen_size
{
DTVCC_PEN_SIZE_SMALL = 0,
DTVCC_PEN_SIZE_SMALL = 0,
DTVCC_PEN_SIZE_STANDART = 1,
DTVCC_PEN_SIZE_LARGE = 2
DTVCC_PEN_SIZE_LARGE = 2
};
enum dtvcc_pen_font_style
{
DTVCC_PEN_FONT_STYLE_DEFAULT_OR_UNDEFINED = 0,
DTVCC_PEN_FONT_STYLE_MONOSPACED_WITH_SERIFS = 1,
DTVCC_PEN_FONT_STYLE_PROPORTIONALLY_SPACED_WITH_SERIFS = 2,
DTVCC_PEN_FONT_STYLE_MONOSPACED_WITHOUT_SERIFS = 3,
DTVCC_PEN_FONT_STYLE_PROPORTIONALLY_SPACED_WITHOUT_SERIFS = 4,
DTVCC_PEN_FONT_STYLE_CASUAL_FONT_TYPE = 5,
DTVCC_PEN_FONT_STYLE_CURSIVE_FONT_TYPE = 6,
DTVCC_PEN_FONT_STYLE_SMALL_CAPITALS = 7
DTVCC_PEN_FONT_STYLE_DEFAULT_OR_UNDEFINED = 0,
DTVCC_PEN_FONT_STYLE_MONOSPACED_WITH_SERIFS = 1,
DTVCC_PEN_FONT_STYLE_PROPORTIONALLY_SPACED_WITH_SERIFS = 2,
DTVCC_PEN_FONT_STYLE_MONOSPACED_WITHOUT_SERIFS = 3,
DTVCC_PEN_FONT_STYLE_PROPORTIONALLY_SPACED_WITHOUT_SERIFS = 4,
DTVCC_PEN_FONT_STYLE_CASUAL_FONT_TYPE = 5,
DTVCC_PEN_FONT_STYLE_CURSIVE_FONT_TYPE = 6,
DTVCC_PEN_FONT_STYLE_SMALL_CAPITALS = 7
};
enum dtvcc_pen_text_tag
{
DTVCC_PEN_TEXT_TAG_DIALOG = 0,
DTVCC_PEN_TEXT_TAG_SOURCE_OR_SPEAKER_ID = 1,
DTVCC_PEN_TEXT_TAG_ELECTRONIC_VOICE = 2,
DTVCC_PEN_TEXT_TAG_FOREIGN_LANGUAGE = 3,
DTVCC_PEN_TEXT_TAG_VOICEOVER = 4,
DTVCC_PEN_TEXT_TAG_AUDIBLE_TRANSLATION = 5,
DTVCC_PEN_TEXT_TAG_SUBTITLE_TRANSLATION = 6,
DTVCC_PEN_TEXT_TAG_VOICE_QUALITY_DESCRIPTION = 7,
DTVCC_PEN_TEXT_TAG_SONG_LYRICS = 8,
DTVCC_PEN_TEXT_TAG_SOUND_EFFECT_DESCRIPTION = 9,
DTVCC_PEN_TEXT_TAG_MUSICAL_SCORE_DESCRIPTION = 10,
DTVCC_PEN_TEXT_TAG_EXPLETIVE = 11,
DTVCC_PEN_TEXT_TAG_UNDEFINED_12 = 12,
DTVCC_PEN_TEXT_TAG_UNDEFINED_13 = 13,
DTVCC_PEN_TEXT_TAG_UNDEFINED_14 = 14,
DTVCC_PEN_TEXT_TAG_NOT_TO_BE_DISPLAYED = 15
DTVCC_PEN_TEXT_TAG_DIALOG = 0,
DTVCC_PEN_TEXT_TAG_SOURCE_OR_SPEAKER_ID = 1,
DTVCC_PEN_TEXT_TAG_ELECTRONIC_VOICE = 2,
DTVCC_PEN_TEXT_TAG_FOREIGN_LANGUAGE = 3,
DTVCC_PEN_TEXT_TAG_VOICEOVER = 4,
DTVCC_PEN_TEXT_TAG_AUDIBLE_TRANSLATION = 5,
DTVCC_PEN_TEXT_TAG_SUBTITLE_TRANSLATION = 6,
DTVCC_PEN_TEXT_TAG_VOICE_QUALITY_DESCRIPTION = 7,
DTVCC_PEN_TEXT_TAG_SONG_LYRICS = 8,
DTVCC_PEN_TEXT_TAG_SOUND_EFFECT_DESCRIPTION = 9,
DTVCC_PEN_TEXT_TAG_MUSICAL_SCORE_DESCRIPTION = 10,
DTVCC_PEN_TEXT_TAG_EXPLETIVE = 11,
DTVCC_PEN_TEXT_TAG_UNDEFINED_12 = 12,
DTVCC_PEN_TEXT_TAG_UNDEFINED_13 = 13,
DTVCC_PEN_TEXT_TAG_UNDEFINED_14 = 14,
DTVCC_PEN_TEXT_TAG_NOT_TO_BE_DISPLAYED = 15
};
enum dtvcc_pen_offset
{
DTVCC_PEN_OFFSET_SUBSCRIPT = 0,
DTVCC_PEN_OFFSET_NORMAL = 1,
DTVCC_PEN_OFFSET_SUPERSCRIPT = 2
DTVCC_PEN_OFFSET_SUBSCRIPT = 0,
DTVCC_PEN_OFFSET_NORMAL = 1,
DTVCC_PEN_OFFSET_SUPERSCRIPT = 2
};
enum dtvcc_pen_edge
{
DTVCC_PEN_EDGE_NONE = 0,
DTVCC_PEN_EDGE_RAISED = 1,
DTVCC_PEN_EDGE_DEPRESSED = 2,
DTVCC_PEN_EDGE_UNIFORM = 3,
DTVCC_PEN_EDGE_LEFT_DROP_SHADOW = 4,
DTVCC_PEN_EDGE_RIGHT_DROP_SHADOW = 5
DTVCC_PEN_EDGE_NONE = 0,
DTVCC_PEN_EDGE_RAISED = 1,
DTVCC_PEN_EDGE_DEPRESSED = 2,
DTVCC_PEN_EDGE_UNIFORM = 3,
DTVCC_PEN_EDGE_LEFT_DROP_SHADOW = 4,
DTVCC_PEN_EDGE_RIGHT_DROP_SHADOW = 5
};
enum dtvcc_pen_anchor_point
{
DTVCC_ANCHOR_POINT_TOP_LEFT = 0,
DTVCC_ANCHOR_POINT_TOP_CENTER = 1,
DTVCC_ANCHOR_POINT_TOP_RIGHT = 2,
DTVCC_ANCHOR_POINT_MIDDLE_LEFT = 3,
DTVCC_ANCHOR_POINT_MIDDLE_CENTER = 4,
DTVCC_ANCHOR_POINT_MIDDLE_RIGHT = 5,
DTVCC_ANCHOR_POINT_BOTTOM_LEFT = 6,
DTVCC_ANCHOR_POINT_BOTTOM_CENTER = 7,
DTVCC_ANCHOR_POINT_BOTTOM_RIGHT = 8
DTVCC_ANCHOR_POINT_TOP_LEFT = 0,
DTVCC_ANCHOR_POINT_TOP_CENTER = 1,
DTVCC_ANCHOR_POINT_TOP_RIGHT = 2,
DTVCC_ANCHOR_POINT_MIDDLE_LEFT = 3,
DTVCC_ANCHOR_POINT_MIDDLE_CENTER = 4,
DTVCC_ANCHOR_POINT_MIDDLE_RIGHT = 5,
DTVCC_ANCHOR_POINT_BOTTOM_LEFT = 6,
DTVCC_ANCHOR_POINT_BOTTOM_CENTER = 7,
DTVCC_ANCHOR_POINT_BOTTOM_RIGHT = 8
};
typedef struct dtvcc_pen_color
@@ -252,12 +252,20 @@ typedef struct dtvcc_window_attribs
*/
typedef struct dtvcc_symbol
{
unsigned short sym; //symbol itself, at least 16 bit
unsigned char init; //initialized or not. could be 0 or 1
unsigned short sym; // symbol itself, at least 16 bit
unsigned char init; // initialized or not. could be 0 or 1
} dtvcc_symbol;
#define CCX_DTVCC_SYM_SET(x, c) {x.init = 1; x.sym = c;}
#define CCX_DTVCC_SYM_SET_16(x, c1, c2) {x.init = 1; x.sym = (c1 << 8) | c2;}
#define CCX_DTVCC_SYM_SET(x, c) \
{ \
x.init = 1; \
x.sym = c; \
}
#define CCX_DTVCC_SYM_SET_16(x, c1, c2) \
{ \
x.init = 1; \
x.sym = (c1 << 8) | c2; \
}
#define CCX_DTVCC_SYM(x) ((unsigned char)(x.sym))
#define CCX_DTVCC_SYM_IS_EMPTY(x) (x.init == 0)
#define CCX_DTVCC_SYM_IS_SET(x) (x.init == 1)
@@ -302,6 +310,7 @@ typedef struct dtvcc_tv_screen
LLONG time_ms_hide;
unsigned int cc_count;
int service_number;
int old_cc_time_end;
} dtvcc_tv_screen;
/**
@@ -343,7 +352,7 @@ typedef struct dtvcc_ctx
{
int is_active;
int active_services_count;
int services_active[CCX_DTVCC_MAX_SERVICES]; //0 - inactive, 1 - active
int services_active[CCX_DTVCC_MAX_SERVICES]; // 0 - inactive, 1 - active
int report_enabled;
ccx_decoder_dtvcc_report *report;
@@ -356,21 +365,20 @@ typedef struct dtvcc_ctx
int last_sequence;
void *encoder; //we can't include header, so keeping it this way
void *encoder; // we can't include header, so keeping it this way
int no_rollup;
struct ccx_common_timing_ctx *timing;
} dtvcc_ctx;
void dtvcc_clear_packet(dtvcc_ctx *ctx);
void dtvcc_windows_reset(dtvcc_service_decoder *decoder);
void dtvcc_decoder_flush(dtvcc_ctx *dtvcc, dtvcc_service_decoder *decoder);
void dtvcc_process_current_packet(dtvcc_ctx *dtvcc, int len);
void dtvcc_process_service_block(dtvcc_ctx *dtvcc,
dtvcc_service_decoder *decoder,
unsigned char *data,
int data_length);
dtvcc_service_decoder *decoder,
unsigned char *data,
int data_length);
void dtvcc_tv_clear(dtvcc_service_decoder *decoder);
int dtvcc_decoder_has_visible_windows(dtvcc_service_decoder *decoder);
@@ -380,9 +388,9 @@ void dtvcc_window_clear(dtvcc_service_decoder *decoder, int window_id);
void dtvcc_window_apply_style(dtvcc_window *window, dtvcc_window_attribs *style);
#ifdef DTVCC_PRINT_DEBUG
int dtvcc_is_win_row_empty(dtvcc_window *window, int row_index);
void dtvcc_get_win_write_interval(dtvcc_window *window, int row_index, int *first, int *last);
void dtvcc_window_dump(dtvcc_service_decoder *decoder, dtvcc_window *window);
int dtvcc_is_win_row_empty(dtvcc_window *window, int row_index);
void dtvcc_get_win_write_interval(dtvcc_window *window, int row_index, int *first, int *last);
void dtvcc_window_dump(dtvcc_service_decoder *decoder, dtvcc_window *window);
#endif
void dtvcc_decoders_reset(dtvcc_ctx *dtvcc);
@@ -405,7 +413,7 @@ void dtvcc_process_character(dtvcc_service_decoder *decoder, dtvcc_symbol symbol
void dtvcc_handle_CWx_SetCurrentWindow(dtvcc_service_decoder *decoder, int window_id);
void dtvcc_handle_CLW_ClearWindows(dtvcc_ctx *dtvcc, dtvcc_service_decoder *decoder, int windows_bitmap);
void dtvcc_handle_DSW_DisplayWindows(dtvcc_service_decoder *decoder, int windows_bitmap, struct ccx_common_timing_ctx *timing);
void dtvcc_handle_HDW_HideWindows(dtvcc_ctx *dtvcc,dtvcc_service_decoder *decoder,
void dtvcc_handle_HDW_HideWindows(dtvcc_ctx *dtvcc, dtvcc_service_decoder *decoder,
int windows_bitmap);
void dtvcc_handle_TGW_ToggleWindows(dtvcc_ctx *dtvcc,
dtvcc_service_decoder *decoder,
@@ -425,13 +433,13 @@ void dtvcc_handle_C0_P16(dtvcc_service_decoder *decoder, unsigned char *data);
int dtvcc_handle_G0(dtvcc_service_decoder *decoder, unsigned char *data, int data_length);
int dtvcc_handle_G1(dtvcc_service_decoder *decoder, unsigned char *data, int data_length);
int dtvcc_handle_C0(dtvcc_ctx *dtvcc,
dtvcc_service_decoder *decoder,
unsigned char *data,
int data_length);
dtvcc_service_decoder *decoder,
unsigned char *data,
int data_length);
int dtvcc_handle_C1(dtvcc_ctx *dtvcc,
dtvcc_service_decoder *decoder,
unsigned char *data,
int data_length);
dtvcc_service_decoder *decoder,
unsigned char *data,
int data_length);
int dtvcc_handle_C2(dtvcc_service_decoder *decoder, unsigned char *data, int data_length);
int dtvcc_handle_C3(dtvcc_service_decoder *decoder, unsigned char *data, int data_length);
int dtvcc_handle_extended_char(dtvcc_service_decoder *decoder, unsigned char *data, int data_length);

View File

@@ -11,35 +11,3 @@ EIA-708, SO INTERNALLY WE USE THIS TABLE (FOR CONVENIENCE)
(there are several blank characters here, that's OK)
A0-FF -> Group G1 as is - non-English characters and symbols
*/
unsigned char dtvcc_get_internal_from_G0(unsigned char g0_char)
{
return g0_char;
}
unsigned char dtvcc_get_internal_from_G1(unsigned char g1_char)
{
return g1_char;
}
// TODO: Probably not right
// G2: Extended Control Code Set 1
unsigned char dtvcc_get_internal_from_G2(unsigned char g2_char)
{
if (g2_char >= 0x20 && g2_char <= 0x3F)
return g2_char - (unsigned char)0x20;
if (g2_char >= 0x60 && g2_char <= 0x7F)
return g2_char + (unsigned char)0x20;
// Rest unmapped, so we return a blank space
return 0x20;
}
// TODO: Probably not right
// G3: Future Characters and Icon Expansion
unsigned char dtvcc_get_internal_from_G3(unsigned char g3_char)
{
if (g3_char == 0xa0) // The "CC" (closed captions) sign
return 0x06;
// Rest unmapped, so we return a blank space
return 0x20;
}

View File

@@ -1,11 +1,11 @@
#ifndef _CCX_DECODERS_708_ENCODING_H_
#define _CCX_DECODERS_708_ENCODING_H_
#define CCX_DTVCC_MUSICAL_NOTE_CHAR 9836 // Unicode Character 'BEAMED SIXTEENTH NOTES'
#define CCX_DTVCC_MUSICAL_NOTE_CHAR 9836 // Unicode Character 'BEAMED SIXTEENTH NOTES'
unsigned char dtvcc_get_internal_from_G0(unsigned char g0_char);
unsigned char dtvcc_get_internal_from_G1(unsigned char g1_char);
unsigned char dtvcc_get_internal_from_G2(unsigned char g2_char);
unsigned char dtvcc_get_internal_from_G3(unsigned char g3_char);
extern unsigned char dtvcc_get_internal_from_G0(unsigned char g0_char);
extern unsigned char dtvcc_get_internal_from_G1(unsigned char g1_char);
extern unsigned char dtvcc_get_internal_from_G2(unsigned char g2_char);
extern unsigned char dtvcc_get_internal_from_G3(unsigned char g3_char);
#endif /*_CCX_DECODERS_708_ENCODING_H_*/

View File

@@ -4,7 +4,7 @@
#include "utility.h"
#include "ccx_common_common.h"
#if defined(ENABLE_RUST) && defined(WIN32)
#if defined(WIN32)
extern void ccxr_close_handle(void *handle);
#endif
@@ -57,6 +57,7 @@ void dtvcc_change_pen_colors(dtvcc_tv_screen *tv, dtvcc_pen_color pen_color, int
return;
char *buf = (char *)encoder->buffer;
size_t remaining = INITIAL_ENC_BUFFER_CAPACITY - *buf_len;
dtvcc_pen_color new_pen_color;
if (column_index >= CCX_DTVCC_SCREENGRID_COLUMNS)
@@ -66,7 +67,11 @@ void dtvcc_change_pen_colors(dtvcc_tv_screen *tv, dtvcc_pen_color pen_color, int
if (pen_color.fg_color != new_pen_color.fg_color)
{
if (pen_color.fg_color != 0x3f && !open)
(*buf_len) += sprintf(buf + (*buf_len), "</font>"); // should close older non-white color
{
int written = snprintf(buf + (*buf_len), remaining, "</font>"); // should close older non-white color
if (written > 0 && (size_t)written < remaining)
(*buf_len) += written;
}
if (new_pen_color.fg_color != 0x3f && open)
{
@@ -75,7 +80,10 @@ void dtvcc_change_pen_colors(dtvcc_tv_screen *tv, dtvcc_pen_color pen_color, int
red = (255 / 3) * red;
green = (255 / 3) * green;
blue = (255 / 3) * blue;
(*buf_len) += sprintf(buf + (*buf_len), "<font color=\"%02x%02x%02x\">", red, green, blue);
remaining = INITIAL_ENC_BUFFER_CAPACITY - *buf_len;
int written = snprintf(buf + (*buf_len), remaining, "<font color=\"#%02x%02x%02x\">", red, green, blue);
if (written > 0 && (size_t)written < remaining)
(*buf_len) += written;
}
}
}
@@ -86,6 +94,8 @@ void dtvcc_change_pen_attribs(dtvcc_tv_screen *tv, dtvcc_pen_attribs pen_attribs
return;
char *buf = (char *)encoder->buffer;
size_t remaining;
int written;
dtvcc_pen_attribs new_pen_attribs;
if (column_index >= CCX_DTVCC_SCREENGRID_COLUMNS)
@@ -94,33 +104,47 @@ void dtvcc_change_pen_attribs(dtvcc_tv_screen *tv, dtvcc_pen_attribs pen_attribs
new_pen_attribs = tv->pen_attribs[row_index][column_index];
if (pen_attribs.italic != new_pen_attribs.italic)
{
remaining = INITIAL_ENC_BUFFER_CAPACITY - *buf_len;
if (pen_attribs.italic && !open)
(*buf_len) += sprintf(buf + (*buf_len), "</i>");
{
written = snprintf(buf + (*buf_len), remaining, "</i>");
if (written > 0 && (size_t)written < remaining)
(*buf_len) += written;
}
if (!pen_attribs.italic && open)
(*buf_len) += sprintf(buf + (*buf_len), "<i>");
{
written = snprintf(buf + (*buf_len), remaining, "<i>");
if (written > 0 && (size_t)written < remaining)
(*buf_len) += written;
}
}
if (pen_attribs.underline != new_pen_attribs.underline)
{
remaining = INITIAL_ENC_BUFFER_CAPACITY - *buf_len;
if (pen_attribs.underline && !open)
(*buf_len) += sprintf(buf + (*buf_len), "</u>");
{
written = snprintf(buf + (*buf_len), remaining, "</u>");
if (written > 0 && (size_t)written < remaining)
(*buf_len) += written;
}
if (!pen_attribs.underline && open)
(*buf_len) += sprintf(buf + (*buf_len), "<u>");
{
written = snprintf(buf + (*buf_len), remaining, "<u>");
if (written > 0 && (size_t)written < remaining)
(*buf_len) += written;
}
}
}
size_t write_utf16_char(unsigned short utf16_char, char *out)
{
if ((utf16_char >> 8) != 0)
{
out[0] = (unsigned char)(utf16_char >> 8);
out[1] = (unsigned char)(utf16_char & 0xff);
return 2;
}
else
{
out[0] = (unsigned char)(utf16_char);
return 1;
}
// Always write 2 bytes for consistent UTF-16BE encoding.
// Previously, this function wrote 1 byte for ASCII characters and 2 bytes
// for non-ASCII, creating an invalid mix that iconv couldn't handle properly.
// This caused garbled output with Japanese/Chinese characters (issue #1451).
out[0] = (unsigned char)(utf16_char >> 8);
out[1] = (unsigned char)(utf16_char & 0xff);
return 2;
}
void dtvcc_write_row(dtvcc_writer_ctx *writer, dtvcc_service_decoder *decoder, int row_index, struct encoder_ctx *encoder, int use_colors)
@@ -207,16 +231,31 @@ void dtvcc_write_srt(dtvcc_writer_ctx *writer, dtvcc_service_decoder *decoder, s
char *buf = (char *)encoder->buffer;
memset(buf, 0, INITIAL_ENC_BUFFER_CAPACITY);
size_t buf_len = 0;
size_t remaining = INITIAL_ENC_BUFFER_CAPACITY;
int written;
sprintf(buf, "%u%s", encoder->cea_708_counter, encoder->encoded_crlf);
written = snprintf(buf, remaining, "%u%s", encoder->cea_708_counter, encoder->encoded_crlf);
if (written > 0 && (size_t)written < remaining)
buf_len += written;
remaining = INITIAL_ENC_BUFFER_CAPACITY - buf_len;
print_mstime_buff(tv->time_ms_show + encoder->subs_delay,
"%02u:%02u:%02u,%03u", buf + strlen(buf));
sprintf(buf + strlen(buf), " --> ");
"%02u:%02u:%02u,%03u", buf + buf_len);
buf_len = strlen(buf);
remaining = INITIAL_ENC_BUFFER_CAPACITY - buf_len;
written = snprintf(buf + buf_len, remaining, " --> ");
if (written > 0 && (size_t)written < remaining)
buf_len += written;
remaining = INITIAL_ENC_BUFFER_CAPACITY - buf_len;
print_mstime_buff(tv->time_ms_hide + encoder->subs_delay,
"%02u:%02u:%02u,%03u", buf + strlen(buf));
sprintf(buf + strlen(buf), "%s", (char *)encoder->encoded_crlf);
"%02u:%02u:%02u,%03u", buf + buf_len);
buf_len = strlen(buf);
remaining = INITIAL_ENC_BUFFER_CAPACITY - buf_len;
written = snprintf(buf + buf_len, remaining, "%s", (char *)encoder->encoded_crlf);
if (written > 0 && (size_t)written < remaining)
buf_len += written;
write_wrapped(encoder->dtvcc_writers[tv->service_number - 1].fd, buf, strlen(buf));
write_wrapped(encoder->dtvcc_writers[tv->service_number - 1].fd, buf, buf_len);
for (int i = 0; i < CCX_DTVCC_SCREENGRID_ROWS; i++)
{
@@ -263,28 +302,47 @@ void dtvcc_write_transcript(dtvcc_writer_ctx *writer, dtvcc_service_decoder *dec
return;
char *buf = (char *)encoder->buffer;
size_t buf_len;
size_t remaining;
int written;
for (int i = 0; i < CCX_DTVCC_SCREENGRID_ROWS; i++)
{
if (!dtvcc_is_row_empty(tv, i))
{
buf[0] = 0;
buf_len = 0;
if (encoder->transcript_settings->showStartTime)
{
print_mstime_buff(tv->time_ms_show + encoder->subs_delay,
"%02u:%02u:%02u,%03u|", buf + strlen(buf));
"%02u:%02u:%02u,%03u|", buf + buf_len);
buf_len = strlen(buf);
}
if (encoder->transcript_settings->showEndTime)
{
print_mstime_buff(tv->time_ms_hide + encoder->subs_delay,
"%02u:%02u:%02u,%03u|", buf + strlen(buf));
"%02u:%02u:%02u,%03u|", buf + buf_len);
buf_len = strlen(buf);
}
if (encoder->transcript_settings->showCC)
sprintf(buf + strlen(buf), "CC1|"); //always CC1 because CEA-708 is field-independent
{
remaining = INITIAL_ENC_BUFFER_CAPACITY - buf_len;
written = snprintf(buf + buf_len, remaining, "CC1|"); // always CC1 because CEA-708 is field-independent
if (written > 0 && (size_t)written < remaining)
buf_len += written;
}
if (encoder->transcript_settings->showMode)
sprintf(buf + strlen(buf), "POP|"); //TODO caption mode(pop, rollup, etc.)
{
remaining = INITIAL_ENC_BUFFER_CAPACITY - buf_len;
written = snprintf(buf + buf_len, remaining, "POP|"); // TODO caption mode(pop, rollup, etc.)
if (written > 0 && (size_t)written < remaining)
buf_len += written;
}
const size_t buf_len = strlen(buf);
if (buf_len != 0)
write_wrapped(encoder->dtvcc_writers[tv->service_number - 1].fd, buf, buf_len);
@@ -300,22 +358,33 @@ void dtvcc_write_sami_header(dtvcc_tv_screen *tv, struct encoder_ctx *encoder)
char *buf = (char *)encoder->buffer;
memset(buf, 0, INITIAL_ENC_BUFFER_CAPACITY);
size_t buf_len = 0;
size_t remaining = INITIAL_ENC_BUFFER_CAPACITY;
int written;
buf_len += sprintf(buf + buf_len, "<sami>%s", encoder->encoded_crlf);
buf_len += sprintf(buf + buf_len, "<head>%s", encoder->encoded_crlf);
buf_len += sprintf(buf + buf_len, "<style type=\"text/css\">%s", encoder->encoded_crlf);
buf_len += sprintf(buf + buf_len, "<!--%s", encoder->encoded_crlf);
buf_len += sprintf(buf + buf_len,
"p {margin-left: 16pt; margin-right: 16pt; margin-bottom: 16pt; margin-top: 16pt;%s",
encoder->encoded_crlf);
buf_len += sprintf(buf + buf_len,
"text-align: center; font-size: 18pt; font-family: arial; font-weight: bold; color: #f0f0f0;}%s",
encoder->encoded_crlf);
buf_len += sprintf(buf + buf_len, ".unknowncc {Name:Unknown; lang:en-US; SAMIType:CC;}%s", encoder->encoded_crlf);
buf_len += sprintf(buf + buf_len, "-->%s", encoder->encoded_crlf);
buf_len += sprintf(buf + buf_len, "</style>%s", encoder->encoded_crlf);
buf_len += sprintf(buf + buf_len, "</head>%s%s", encoder->encoded_crlf, encoder->encoded_crlf);
buf_len += sprintf(buf + buf_len, "<body>%s", encoder->encoded_crlf);
#define SAMI_SNPRINTF(fmt, ...) \
do \
{ \
remaining = INITIAL_ENC_BUFFER_CAPACITY - buf_len; \
written = snprintf(buf + buf_len, remaining, fmt, ##__VA_ARGS__); \
if (written > 0 && (size_t)written < remaining) \
buf_len += written; \
} while (0)
SAMI_SNPRINTF("<sami>%s", encoder->encoded_crlf);
SAMI_SNPRINTF("<head>%s", encoder->encoded_crlf);
SAMI_SNPRINTF("<style type=\"text/css\">%s", encoder->encoded_crlf);
SAMI_SNPRINTF("<!--%s", encoder->encoded_crlf);
SAMI_SNPRINTF("p {margin-left: 16pt; margin-right: 16pt; margin-bottom: 16pt; margin-top: 16pt;%s",
encoder->encoded_crlf);
SAMI_SNPRINTF("text-align: center; font-size: 18pt; font-family: arial; font-weight: bold; color: #f0f0f0;}%s",
encoder->encoded_crlf);
SAMI_SNPRINTF(".unknowncc {Name:Unknown; lang:en-US; SAMIType:CC;}%s", encoder->encoded_crlf);
SAMI_SNPRINTF("-->%s", encoder->encoded_crlf);
SAMI_SNPRINTF("</style>%s", encoder->encoded_crlf);
SAMI_SNPRINTF("</head>%s%s", encoder->encoded_crlf, encoder->encoded_crlf);
SAMI_SNPRINTF("<body>%s", encoder->encoded_crlf);
#undef SAMI_SNPRINTF
write_wrapped(encoder->dtvcc_writers[tv->service_number - 1].fd, buf, buf_len);
}
@@ -323,8 +392,9 @@ void dtvcc_write_sami_header(dtvcc_tv_screen *tv, struct encoder_ctx *encoder)
void dtvcc_write_sami_footer(dtvcc_tv_screen *tv, struct encoder_ctx *encoder)
{
char *buf = (char *)encoder->buffer;
sprintf(buf, "</body></sami>");
write_wrapped(encoder->dtvcc_writers[tv->service_number - 1].fd, buf, strlen(buf));
int written = snprintf(buf, INITIAL_ENC_BUFFER_CAPACITY, "</body></sami>");
if (written > 0 && (size_t)written < INITIAL_ENC_BUFFER_CAPACITY)
write_wrapped(encoder->dtvcc_writers[tv->service_number - 1].fd, buf, written);
write_wrapped(encoder->dtvcc_writers[tv->service_number - 1].fd,
encoder->encoded_crlf, encoder->encoded_crlf_length);
}
@@ -342,12 +412,14 @@ void dtvcc_write_sami(dtvcc_writer_ctx *writer, dtvcc_service_decoder *decoder,
dtvcc_write_sami_header(tv, encoder);
char *buf = (char *)encoder->buffer;
int written;
buf[0] = 0;
sprintf(buf, "<sync start=%llu><p class=\"unknowncc\">%s",
(unsigned long long)tv->time_ms_show + encoder->subs_delay,
encoder->encoded_crlf);
write_wrapped(encoder->dtvcc_writers[tv->service_number - 1].fd, buf, strlen(buf));
written = snprintf(buf, INITIAL_ENC_BUFFER_CAPACITY, "<sync start=%llu><p class=\"unknowncc\">%s",
(unsigned long long)tv->time_ms_show + encoder->subs_delay,
encoder->encoded_crlf);
if (written > 0 && (size_t)written < INITIAL_ENC_BUFFER_CAPACITY)
write_wrapped(encoder->dtvcc_writers[tv->service_number - 1].fd, buf, written);
for (int i = 0; i < CCX_DTVCC_SCREENGRID_ROWS; i++)
{
@@ -361,10 +433,189 @@ void dtvcc_write_sami(dtvcc_writer_ctx *writer, dtvcc_service_decoder *decoder,
}
}
sprintf(buf, "<sync start=%llu><p class=\"unknowncc\">&nbsp;</p></sync>%s%s",
(unsigned long long)tv->time_ms_hide + encoder->subs_delay,
encoder->encoded_crlf, encoder->encoded_crlf);
written = snprintf(buf, INITIAL_ENC_BUFFER_CAPACITY, "<sync start=%llu><p class=\"unknowncc\">&nbsp;</p></sync>%s%s",
(unsigned long long)tv->time_ms_hide + encoder->subs_delay,
encoder->encoded_crlf, encoder->encoded_crlf);
if (written > 0 && (size_t)written < INITIAL_ENC_BUFFER_CAPACITY)
write_wrapped(encoder->dtvcc_writers[tv->service_number - 1].fd, buf, written);
}
unsigned char adjust_odd_parity(const unsigned char value)
{
unsigned int i, ones = 0;
for (i = 0; i < 8; i++)
{
if ((value & (1 << i)) != 0)
{
ones += 1;
}
}
if (ones % 2 == 0)
{
// make the number of ones always odd
return value | 0b10000000;
}
return value;
}
void dtvcc_write_scc_header(dtvcc_tv_screen *tv, struct encoder_ctx *encoder)
{
char *buf = (char *)encoder->buffer;
// 18 characters long + 2 new lines = 20 characters total
memset(buf, 0, INITIAL_ENC_BUFFER_CAPACITY);
int written = snprintf(buf, INITIAL_ENC_BUFFER_CAPACITY, "Scenarist_SCC V1.0\n\n");
if (written > 0 && (size_t)written < INITIAL_ENC_BUFFER_CAPACITY)
write_wrapped(encoder->dtvcc_writers[tv->service_number - 1].fd, buf, written);
}
int count_captions_lines_scc(dtvcc_tv_screen *tv)
{
int count = 0;
for (int i = 0; i < CCX_DTVCC_SCREENGRID_ROWS; i++)
{
if (!dtvcc_is_row_empty(tv, i))
{
count++;
}
}
return count;
}
/** This function is designed to assign appropriate SSC labels for positioning subtitles based on their length.
* In some scenarios where the video stream provides lengthy subtitles that cannot fit within a single line.
* Single-line subtitle can be placed in 15th row(most bottom row)
* 2 line length subtitles can be placed in 14th and 15th row
* 3 line length subtitles can be placed in 13th, 14th and 15th row
*/
void add_needed_scc_labels(char *buf, size_t buf_size, size_t *buf_len, int total_subtitle_count, int current_subtitle_count)
{
size_t remaining = buf_size - *buf_len;
int written;
const char *label;
switch (total_subtitle_count)
{
case 1:
// row 15, column 00
label = " 94e0 94e0";
break;
case 2:
// 9440: row 14, column 00 | 94e0: row 15, column 00
label = (current_subtitle_count == 1) ? " 9440 9440" : " 94e0 94e0";
break;
default:
// 13e0: row 13, column 04 | 9440: row 14, column 00 | 94e0: row 15, column 00
label = (current_subtitle_count == 1) ? " 13e0 13e0" : ((current_subtitle_count == 2) ? " 9440 9440" : " 94e0 94e0");
break;
}
written = snprintf(buf + *buf_len, remaining, "%s", label);
if (written > 0 && (size_t)written < remaining)
*buf_len += written;
}
void dtvcc_write_scc(dtvcc_writer_ctx *writer, dtvcc_service_decoder *decoder, struct encoder_ctx *encoder)
{
dtvcc_tv_screen *tv = decoder->tv;
if (dtvcc_is_screen_empty(tv, encoder))
return;
if (tv->time_ms_show + encoder->subs_delay < 0)
return;
if (tv->cc_count == 2)
dtvcc_write_scc_header(tv, encoder);
char *buf = (char *)encoder->buffer;
size_t buf_len;
size_t remaining;
int written;
struct ccx_boundary_time time_show = get_time(tv->time_ms_show + encoder->subs_delay);
// when hiding subtract a frame (1 frame = 34 ms)
struct ccx_boundary_time time_end = get_time(tv->time_ms_hide + encoder->subs_delay - 34);
#define SCC_SNPRINTF(fmt, ...) \
do \
{ \
remaining = INITIAL_ENC_BUFFER_CAPACITY - buf_len; \
written = snprintf(buf + buf_len, remaining, fmt, ##__VA_ARGS__); \
if (written > 0 && (size_t)written < remaining) \
buf_len += written; \
} while (0)
if (tv->old_cc_time_end > time_show.time_in_ms)
{
// Correct the frame delay
time_show.time_in_ms -= 1000 / 29.97;
print_scc_time(time_show, buf);
buf_len = strlen(buf);
SCC_SNPRINTF("\t942c 942c");
time_show.time_in_ms += 1000 / 29.97;
// Clear the buffer and start pop on caption
SCC_SNPRINTF("94ae 94ae 9420 9420");
}
else if (tv->old_cc_time_end < time_show.time_in_ms)
{
// Clear the screen for new caption
struct ccx_boundary_time time_to_display = get_time(tv->old_cc_time_end);
print_scc_time(time_to_display, buf);
buf_len = strlen(buf);
SCC_SNPRINTF("\t942c 942c \n\n");
// Correct the frame delay
time_show.time_in_ms -= 1000 / 29.97;
// Clear the buffer and start pop on caption in new time
print_scc_time(time_show, buf + buf_len);
buf_len = strlen(buf);
SCC_SNPRINTF("\t94ae 94ae 9420 9420");
time_show.time_in_ms += 1000 / 29.97;
}
else
{
time_show.time_in_ms -= 1000 / 29.97;
print_scc_time(time_show, buf);
buf_len = strlen(buf);
SCC_SNPRINTF("\t942c 942c 94ae 94ae 9420 9420");
time_show.time_in_ms += 1000 / 29.97;
}
int total_subtitle_count = count_captions_lines_scc(tv);
int current_subtitle_count = 0;
for (int i = 0; i < CCX_DTVCC_SCREENGRID_ROWS; i++)
{
if (!dtvcc_is_row_empty(tv, i))
{
current_subtitle_count++;
add_needed_scc_labels(buf, INITIAL_ENC_BUFFER_CAPACITY, &buf_len, total_subtitle_count, current_subtitle_count);
int first, last, bytes_written = 0;
dtvcc_get_write_interval(tv, i, &first, &last);
for (int j = first; j <= last; j++)
{
if (bytes_written % 2 == 0)
SCC_SNPRINTF(" ");
SCC_SNPRINTF("%x", adjust_odd_parity(tv->chars[i][j].sym));
bytes_written += 1;
}
// if byte pair are not even then make it even by adding 0x80 as padding
if (bytes_written % 2 == 1)
SCC_SNPRINTF("80 ");
else
SCC_SNPRINTF(" ");
}
}
// Display caption (942f 942f)
SCC_SNPRINTF("942f 942f \n\n");
#undef SCC_SNPRINTF
write_wrapped(encoder->dtvcc_writers[tv->service_number - 1].fd, buf, strlen(buf));
tv->old_cc_time_end = time_end.time_in_ms;
}
void dtvcc_write(dtvcc_writer_ctx *writer, dtvcc_service_decoder *decoder, struct encoder_ctx *encoder)
@@ -382,6 +633,9 @@ void dtvcc_write(dtvcc_writer_ctx *writer, dtvcc_service_decoder *decoder, struc
case CCX_OF_SAMI:
dtvcc_write_sami(writer, decoder, encoder);
break;
case CCX_OF_SCC:
dtvcc_write_scc(writer, decoder, encoder);
break;
case CCX_OF_MCC:
printf("REALLY BAD... [%s:%d]\n", __FILE__, __LINE__);
break;
@@ -427,7 +681,7 @@ void dtvcc_writer_init(dtvcc_writer_ctx *writer,
const char *ext = get_file_extension(write_format);
char suffix[32];
sprintf(suffix, CCX_DTVCC_FILENAME_TEMPLATE, program_number, service_number);
snprintf(suffix, sizeof(suffix), CCX_DTVCC_FILENAME_TEMPLATE, program_number, service_number);
writer->filename = create_outfilename(base_filename, suffix, ext);
if (!writer->filename)
@@ -438,10 +692,8 @@ void dtvcc_writer_init(dtvcc_writer_ctx *writer,
char *charset = cfg->all_services_charset ? cfg->all_services_charset : cfg->services_charsets[service_number - 1];
#ifdef ENABLE_RUST
writer->fhandle = NULL;
writer->charset = charset;
#endif
if (charset)
{
@@ -459,14 +711,14 @@ void dtvcc_writer_cleanup(dtvcc_writer_ctx *writer)
{
if (writer->fd >= 0 && writer->fd != STDOUT_FILENO)
close(writer->fd);
#if defined(ENABLE_RUST) && defined(WIN32)
#if defined(WIN32)
ccxr_close_handle(writer->fhandle);
writer->charset = NULL;
#endif
free(writer->filename);
if (writer->cd == (iconv_t)-1)
{
//TODO nothing to do here
// TODO nothing to do here
}
else
iconv_close(writer->cd);
@@ -481,7 +733,7 @@ void dtvcc_writer_output(dtvcc_writer_ctx *writer, dtvcc_service_decoder *decode
if (!writer->filename && writer->fd < 0)
return;
if (writer->filename && writer->fd < 0) //first request to write
if (writer->filename && writer->fd < 0) // first request to write
{
ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] "
"dtvcc_writer_output: creating %s\n",

View File

@@ -8,11 +8,11 @@
void dtvcc_write_done(dtvcc_tv_screen *tv, struct encoder_ctx *encoder);
void dtvcc_writer_init(dtvcc_writer_ctx *writer,
char *base_filename,
int program_number,
int service_number,
enum ccx_output_format write_format,
struct encoder_cfg *cfg);
char *base_filename,
int program_number,
int service_number,
enum ccx_output_format write_format,
struct encoder_cfg *cfg);
void dtvcc_writer_cleanup(dtvcc_writer_ctx *writer);
void dtvcc_writer_output(dtvcc_writer_ctx *writer, dtvcc_service_decoder *decoder, struct encoder_ctx *encoder);
@@ -30,6 +30,9 @@ void dtvcc_write_transcript(dtvcc_writer_ctx *writer, dtvcc_service_decoder *dec
void dtvcc_write_sami_header(dtvcc_tv_screen *tv, struct encoder_ctx *encoder);
void dtvcc_write_sami_footer(dtvcc_tv_screen *tv, struct encoder_ctx *encoder);
void dtvcc_write_sami(dtvcc_writer_ctx *writer, dtvcc_service_decoder *decoder, struct encoder_ctx *encoder);
void dtvcc_write_scc_header(dtvcc_tv_screen *tv, struct encoder_ctx *encoder);
void add_needed_scc_labels(char *buf, size_t buf_size, size_t *buf_len, int total_subtitle_count, int current_subtitle_count);
void dtvcc_write_scc(dtvcc_writer_ctx *writer, dtvcc_service_decoder *decoder, struct encoder_ctx *encoder);
void dtvcc_write(dtvcc_writer_ctx *writer, dtvcc_service_decoder *decoder, struct encoder_ctx *encoder);
#endif /*_CCX_DECODERS_708_OUTPUT_H_*/
#endif /*_CCX_DECODERS_708_OUTPUT_H_*/

Some files were not shown because too many files have changed in this diff Show More