/* --------------------------------------------------------------
   transcode.h -- in-process libav transcoder (no ffmpeg subprocess)

   Replaces the ffmpeg-pipe (fork/exec) approach with direct calls
   into libavformat/libavcodec/libswresample. Demuxes incoming MPEG-TS
   bytes, decodes, re-encodes (libx264 video / libfdk_aac or native
   aac audio), and re-muxes to MPEG-TS -- emitting finished 188-byte
   TS packets one at a time through a caller-supplied callback so the
   existing segment/playlist/AES pipeline (pkt_write/seg_fd/write_m3u8)
   is reused unchanged.

   Five supported audio/video cases (see TcOpts):
     1. audio_aac=1, video copy           -> transcode audio only to AAC
     2. audio_aac=1, audio_map=-1          -> ALL input audio tracks -> AAC
     3. AC3 (or any) input audio -> AAC     -> handled automatically; the
                                               decoder is picked per input
                                               stream codec, AC3 included
     4. audio_map=N                         -> single specific audio track
     5. video_h264=1                        -> transcode video via libx264
   -------------------------------------------------------------- */
#ifndef TRANSCODE_H
#define TRANSCODE_H

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

/* One 188-byte finished TS packet, ready for pkt_write(). */
typedef void (*tc_pkt_cb)(void *user, const uint8_t *ts188);

typedef struct {
    /* video */
    int  video_h264;          /* 1 = transcode video with libx264; 0 = passthrough/copy */
    int  video_crf;           /* 0 = unset -> use bitrate; else CRF 0-51 */
    char video_bitrate[32];   /* used when video_crf == 0, e.g. "2000k" */
    char video_preset[32];    /* x264 preset, default "ultrafast" if empty */
    char video_tune[32];      /* x264 tune, optional */
    int  video_threads;       /* 0 = auto */
    int  deinterlace;         /* 1 = yadif-equivalent deinterlace before encode */

    /* audio */
    int  audio_aac;           /* 1 = transcode audio to AAC */
    int  audio_map;           /* -1 = ALL audio streams; >=0 = one stream index (0-based among audio streams) */
    char audio_bitrate[32];   /* CBR bitrate e.g. "128k" */
    char aac_mode[16];        /* "cbr" or "vbr1".."vbr5" */
    int  prefer_fdk;          /* 1 = try libfdk_aac first, fall back to native aac */

    /* misc */
    int  segment_secs;        /* used to size the GOP for forced keyframes */
    int  verbose;              /* 1 = print transcoder lifecycle/error messages to
                                   stderr (probe results, encoder fallbacks, mux
                                   errors); 0 = stay silent except hard failures
                                   that prevent the channel from starting at all */
} TcOpts;

typedef struct Transcoder Transcoder;

/* Create + start a transcoder. cb is invoked (possibly many times, from
 * inside tc_write()) with finished 188-byte TS packets. user is passed
 * through untouched -- caller typically passes their Ch* here.
 * Returns NULL on failure (logs to stderr). */
Transcoder *tc_start(const TcOpts *opts, tc_pkt_cb cb, void *user, const char *chan_name);

/* Feed raw incoming MPEG-TS bytes (any length, need not be 188-aligned
 * across calls -- internal buffer handles re-sync/framing). Non-blocking
 * with respect to the network: all work happens synchronously on the
 * calling thread, so call this from a dedicated per-channel thread, not
 * directly from the shared NIC poll loop, if encode cost is a concern. */
void tc_write(Transcoder *t, const uint8_t *data, int len);

/* Flush + free. Safe to call on a NULL pointer. */
void tc_stop(Transcoder *t);

/* Number of input bytes dropped so far due to ring-buffer overflow
 * (the in-process equivalent of the old ffmpeg-pipe's pipe_drops stat:
 * the pump thread/encoders are too slow for the incoming bitrate).
 * Safe to call from any thread; returns 0 for a NULL pointer. */
uint64_t tc_drop_count(const Transcoder *t);

#ifdef __cplusplus
}
#endif
#endif
