xpra icon
Bug tracker and wiki

This bug tracker and wiki are being discontinued
please use https://github.com/Xpra-org/xpra instead.


Ticket #1107: mpeg4-muxer-v2.patch

File mpeg4-muxer-v2.patch, 19.3 KB (added by Antoine Martin, 5 years ago)

generates mpeg4 container with h264 embedded... to file for now

  • setup.py

     
    16511651            add_keywords([libffmpeg_bin_dir], [libffmpeg_include_dir],
    16521652                         [libffmpeg_lib_dir, libffmpeg_bin_dir],
    16531653                         ["avcodec", "avutil"])
     1654        if "avformat" in pkgs_options[0]:
     1655            add_keywords([libffmpeg_bin_dir], [libffmpeg_include_dir],
     1656                         [libffmpeg_lib_dir, libffmpeg_bin_dir],
     1657                         ["avformat", "avutil"])
    16541658        elif "swscale" in pkgs_options[0]:
    16551659            add_keywords([libffmpeg_bin_dir], [libffmpeg_include_dir],
    16561660                         [libffmpeg_lib_dir, libffmpeg_bin_dir],
     
    24112415
    24122416toggle_packages(enc_ffmpeg_ENABLED, "xpra.codecs.enc_ffmpeg")
    24132417if enc_ffmpeg_ENABLED:
    2414     ffmpeg_pkgconfig = pkgconfig("libavcodec")
     2418    ffmpeg_pkgconfig = pkgconfig("libavcodec", "libavformat")
    24152419    cython_add(Extension("xpra.codecs.enc_ffmpeg.encoder",
    24162420                ["xpra/codecs/enc_ffmpeg/encoder.pyx"]+membuffers_c,
    24172421                **ffmpeg_pkgconfig))
  • xpra/codecs/enc_ffmpeg/encoder.pyx

     
    1414from xpra.codecs.libav_common.av_log import suspend_nonfatal_logging, resume_nonfatal_logging
    1515from xpra.util import AtomicInteger, bytestostr, csv, print_nested_dict
    1616
    17 SAVE_TO_FILE = os.environ.get("XPRA_SAVE_TO_FILE")
     17SAVE_TO_FILE = "1"
     18#os.environ.get("XPRA_SAVE_TO_FILE")
    1819
    1920
    20 from libc.stdint cimport uint8_t, int64_t, uint8_t
     21from libc.stdint cimport uint8_t, int64_t, uint64_t, uint32_t, uint8_t
    2122
    2223cdef extern from "string.h":
    2324    void free(void * ptr) nogil
     
    7273    AVPixelFormat AV_PIX_FMT_BGRA
    7374    AVPixelFormat AV_PIX_FMT_GBRP
    7475
     76
     77cdef extern from "libavformat/avio.h":
     78    ctypedef int AVIODataMarkerType
     79    int AVIO_FLAG_WRITE
     80
     81    ctypedef struct AVIOInterruptCB:
     82        pass
     83
     84    ctypedef struct AVIOContext:
     85        const AVClass *av_class
     86        unsigned char *buffer       #Start of the buffer
     87        int buffer_size             #Maximum buffer size
     88        unsigned char *buf_ptr      #Current position in the buffer
     89        unsigned char *buf_end      #End of the data, may be less than
     90                                    #buffer+buffer_size if the read function returned
     91                                    #less data than requested, e.g. for streams where
     92                                    #no more data has been received yet.
     93        void *opaque                #A private pointer, passed to the read/write/seek/... functions.
     94        int (*read_packet)(void *opaque, uint8_t *buf, int buf_size)
     95        int (*write_packet)(void *opaque, uint8_t *buf, int buf_size)
     96        int64_t (*seek)(void *opaque, int64_t offset, int whence)
     97        int64_t pos                 #position in the file of the current buffer
     98        int must_flush              #true if the next seek should flush
     99        int eof_reached             #true if eof reached
     100        int write_flag              #true if open for writing
     101        int max_packet_size
     102        unsigned long checksum
     103        unsigned char *checksum_ptr
     104        unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size)
     105        int error                   #contains the error code or 0 if no error happened
     106        int (*read_pause)(void *opaque, int pause)
     107        int64_t (*read_seek)(void *opaque, int stream_index, int64_t timestamp, int flags)
     108        int seekable
     109        int64_t maxsize
     110        int direct
     111        int64_t bytes_read
     112        int seek_count;
     113        int writeout_count
     114        int orig_buffer_size
     115        int short_seek_threshold
     116        const char *protocol_whitelist
     117        const char *protocol_blacklist
     118        int (*write_data_type)(void *opaque, uint8_t *buf, int buf_size, AVIODataMarkerType type, int64_t time)
     119        int ignore_boundary_point
     120        AVIODataMarkerType current_type
     121        int64_t last_time
     122
     123    AVIOContext *avio_alloc_context(unsigned char *buffer, int buffer_size, int write_flag,
     124                  void *opaque,
     125                  int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
     126                  int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
     127                  int64_t (*seek)(void *opaque, int64_t offset, int whence))
     128
     129    int avio_open(AVIOContext **s, const char *url, int flags)
     130    int avio_close(AVIOContext *s)
     131    #ctypedef NVENCSTATUS (*PNVENCOPENENCODESESSION)         (void* device, uint32_t deviceType, void** encoder) nogil
     132
     133
    75134cdef extern from "libavcodec/avcodec.h":
    76135    int CODEC_FLAG2_FAST
    77136    int CODEC_CAP_DRAW_HORIZ_BAND
     
    113172    ctypedef struct AVDictionary:
    114173        pass
    115174    ctypedef struct AVPacket:
     175        int64_t pts
     176        int64_t dts
    116177        uint8_t *data
    117         int      size
     178        int     size
     179        int     stream_index
     180        int     flags
     181        AVPacketSideData *side_data
     182        int     side_data_elems
     183        int64_t duration
     184        int64_t pos
    118185
    119186    ctypedef struct AVRational:
    120187        int num
     
    138205        AVRational time_base
    139206
    140207    ctypedef struct AVFormatContext:
    141         pass
     208        const AVClass   *av_class
     209        AVInputFormat   *iformat
     210        AVOutputFormat  *oformat
     211        void            *priv_data
     212        AVIOContext     *pb
     213        int             ctx_flags
     214        unsigned int    nb_streams
     215        AVStream        **streams
     216        char            filename[1024]
     217        int64_t         start_time
     218        int64_t         duration
     219        int             bit_rate
     220        unsigned int    packet_size
     221        int             max_delay
     222        int             flags
     223        unsigned int    probesize
     224        int             max_analyze_duration
     225        const uint8_t   *key
     226        int             keylen
     227        unsigned int    nb_programs
     228        AVProgram       **programs
     229        AVCodecID       video_codec_id
     230        AVCodecID       audio_codec_id
     231        AVCodecID       subtitle_codec_id
     232        unsigned int    max_index_size
     233        unsigned int    max_picture_buffer
     234        unsigned int    nb_chapters
     235        AVChapter       **chapters
     236        AVDictionary    *metadata
     237        int64_t         start_time_realtime
     238        int             fps_probe_size
     239        int             error_recognition
     240        AVIOInterruptCB interrupt_callback
     241        int             debug
     242        int64_t         max_interleave_delta
     243        int             strict_std_compliance
     244        int             event_flags
     245        int             max_ts_probe
     246        int             avoid_negative_ts
     247        AVFormatInternal *internal
     248        void            *opaque
     249        int(*io_open)(AVFormatContext *s, AVIOContext **pb, const char *url, int flags, AVDictionary **options)
     250        void(*io_close)(AVFormatContext *s, AVIOContext *pb)
     251        char *protocol_blacklist
     252        char *protocol_whitelist
    142253
     254    ctypedef int AVMediaType
     255    ctypedef int AVFieldOrder
     256    ctypedef int AVColorRange
     257    ctypedef int AVColorPrimaries
     258    ctypedef int AVColorTransferCharacteristic
     259    ctypedef int AVColorSpace
     260    ctypedef int AVChromaLocation   
     261    ctypedef struct AVCodecParameters:
     262        AVMediaType     codec_type
     263        AVCodecID       codec_id
     264        uint32_t        codec_tag
     265        uint8_t         *extradata
     266        int             extradata_size
     267        int             format
     268        int64_t         bit_rate
     269        int             bits_per_coded_sample
     270        int             bits_per_raw_sample
     271        int             profile
     272        int             level
     273        int             width
     274        int             height
     275        AVRational      sample_aspect_ratio
     276        AVFieldOrder    field_order
     277        AVColorRange    color_range
     278        AVColorPrimaries    color_primaries
     279        AVColorTransferCharacteristic color_trc
     280        AVColorSpace        color_space
     281        AVChromaLocation    chroma_location
     282        int             video_delay
     283        uint64_t        channel_layout
     284        int             channels
     285        int             sample_rate
     286        int             block_align
     287        int             frame_size
     288        int             initial_padding
     289        int             trailing_padding
     290        int             seek_preroll
     291
    143292    AVCodecID AV_CODEC_ID_H264
    144293    AVCodecID AV_CODEC_ID_H265
    145294    AVCodecID AV_CODEC_ID_VP8
     
    163312    void av_packet_unref(AVPacket *pkt) nogil
    164313
    165314
     315cdef extern from "libavutil/log.h":
     316    ctypedef struct AVClass:
     317        pass
     318
     319
     320cdef extern from "libavformat/avformat.h":
     321    ctypedef int AVStreamParseType
     322    ctypedef struct AVInputFormat:
     323        pass
     324    ctypedef struct AVProgram:
     325        pass
     326    ctypedef struct AVChapter:
     327        pass
     328    ctypedef struct AVFormatInternal:
     329        pass
     330    ctypedef struct AVPacketSideData:
     331        pass
     332    ctypedef struct AVStream:
     333        int         index           #stream index in AVFormatContext
     334        int         id
     335        AVCodecContext *codec
     336        AVRational  time_base
     337        int64_t     start_time
     338        int64_t     duration
     339        int64_t     nb_frames       #number of frames in this stream if known or 0
     340        int         disposition
     341        #AVDiscard   discard         #Selects which packets can be discarded at will and do not need to be demuxed.
     342        AVRational  sample_aspect_ratio
     343        AVDictionary *metadata
     344        AVRational  avg_frame_rate
     345        AVPacket    attached_pic
     346        AVPacketSideData *side_data
     347        int         nb_side_data
     348        int         event_flags
     349        int         pts_wrap_bits   #number of bits in pts (used for wrapping control)
     350        int64_t     first_dts
     351        int64_t     cur_dts
     352        int64_t     last_IP_pts
     353        int         last_IP_duration
     354        int         probe_packets
     355        int         codec_info_nb_frames
     356        AVStreamParseType need_parsing
     357        #AVPacketList *last_in_packet_buffer
     358        #AVProbeData probe_data
     359        int         stream_identifier
     360        char        *recommended_encoder_configuration
     361        AVCodecParameters *codecpar
     362
     363    ctypedef struct AVOutputFormat:
     364        const char  *name
     365        const char  *long_name
     366        const char  *mime_type
     367        const char  *extensions
     368        AVCodecID   audio_codec
     369        AVCodecID   video_codec
     370        AVCodecID   subtitle_codec
     371        int         flags       #AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_GLOBALHEADER, AVFMT_NOTIMESTAMPS, AVFMT_VARIABLE_FPS, AVFMT_NODIMENSIONS, AVFMT_NOSTREAMS, AVFMT_ALLOW_FLUSH, AVFMT_TS_NONSTRICT, AVFMT_TS_NEGATIVE More...
     372        #AVCodecTag *const *     codec_tag
     373        int     priv_data_size
     374        int(*write_header)(AVFormatContext *)
     375        int(*write_packet)(AVFormatContext *, AVPacket *pkt)
     376        int(*write_trailer )(AVFormatContext *)
     377        int(*interleave_packet)(AVFormatContext *, AVPacket *out, AVPacket *input, int flush)
     378        int(*query_codec)(AVCodecID id, int std_compliance)
     379        void(*get_output_timestamp )(AVFormatContext *s, int stream, int64_t *dts, int64_t *wall)
     380        int(*control_message )(AVFormatContext *s, int type, void *data, size_t data_size)
     381        int(*write_uncoded_frame )(AVFormatContext *, int stream_index, AVFrame **frame, unsigned flags)
     382        #int(*get_device_list )(AVFormatContext *s, struct AVDeviceInfoList *device_list)
     383        #int(*create_device_capabilities )(AVFormatContext *s, AVDeviceCapabilitiesQuery *caps)
     384        #int(*free_device_capabilities )(AVFormatContext *s, AVDeviceCapabilitiesQuery *caps)
     385        AVCodecID   data_codec
     386        int(*init)(AVFormatContext *)
     387        void(*deinit)(AVFormatContext *)
     388        int(*check_bitstream )(AVFormatContext *, const AVPacket *pkt)
     389
     390    void av_register_all()
     391    AVOutputFormat *av_oformat_next (const AVOutputFormat *f)
     392    int avformat_alloc_output_context2(AVFormatContext **ctx, AVOutputFormat *oformat, const char *format_name, const char *filename)
     393    void avformat_free_context(AVFormatContext *s)
     394
     395    AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c)
     396    int avformat_write_header(AVFormatContext *s, AVDictionary **options)
     397    int av_write_trailer(AVFormatContext *s)
     398    int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt)
     399    #void add_stream(OutputStream *ost, AVFormatContext *oc, AVCodec **codec, AVCodecID codec_id)
     400
     401
    166402CAPS = {
    167403        CODEC_CAP_DRAW_HORIZ_BAND       : "DRAW_HORIZ_BAND",
    168404        CODEC_CAP_DR1                   : "DR1",
     
    218454log("AV_PIX_FMT:")
    219455print_nested_dict(ENUM_TO_FORMAT, print_fn=log.debug)
    220456
     457def get_output_formats():
     458    av_register_all()
     459    cdef AVOutputFormat *fmt = NULL
     460    formats = {}
     461    while True:
     462        fmt = av_oformat_next(fmt)
     463        if fmt==NULL:
     464            break
     465        name = fmt.name
     466        long_name = fmt.long_name
     467        formats[name] = long_name
     468    return formats
     469log("AV Output Formats:")
     470print_nested_dict(get_output_formats(), print_fn=log.debug)
     471
     472cdef AVOutputFormat* get_av_output_format(name):
     473    cdef AVOutputFormat *fmt = NULL
     474    while True:
     475        fmt = av_oformat_next(fmt)
     476        if fmt==NULL:
     477            break
     478        if name==fmt.name:
     479            return fmt
     480    return NULL
     481
     482
    221483def get_version():
    222484    return (LIBAVCODEC_VERSION_MAJOR, LIBAVCODEC_VERSION_MINOR, LIBAVCODEC_VERSION_MICRO)
    223485
     
    300562        This wraps the AVCodecContext and its configuration,
    301563    """
    302564    cdef AVCodec *codec
     565    cdef AVStream *stream
     566    cdef AVFormatContext *format_ctx
    303567    cdef AVCodecContext *codec_ctx
    304568    cdef AVPixelFormat pix_fmt
    305569    cdef object src_format
     
    314578    cdef object __weakref__
    315579
    316580    def init_context(self, unsigned int width, unsigned int height, src_format, dst_formats, encoding, int quality, int speed, scaling, options):    #@DuplicatedSignature
     581        cdef int r
    317582        global CODECS, generation
    318583        assert encoding in CODECS
    319584        assert src_format in get_input_colorspaces(encoding), "invalid colorspace: %s" % src_format
     
    345610        log("%s: \"%s\", codec flags: %s", self.codec.name, self.codec.long_name, csv(v for k,v in CAPS.items() if (self.codec.capabilities & k)))
    346611
    347612        #from here on, we have to call clean_encoder():
    348         self.codec_ctx = avcodec_alloc_context3(self.codec)
     613        #TODO: the muxer should be configurable!
     614        muxer_format = "mp4"
     615        cdef AVOutputFormat *oformat = get_av_output_format(muxer_format)
     616        log("AVOutputFormat(%s)=%#x", muxer_format, <unsigned long> oformat)
     617        if oformat==NULL:
     618            self.clean_encoder()
     619            raise Exception("libavformat does not support %s" % muxer_format)
     620        r = avformat_alloc_output_context2(&self.format_ctx, oformat, muxer_format, NULL)
     621        if r!=0:
     622            self.clean_encoder()
     623            msg = av_error_str(r)
     624            raise Exception("libavformat cannot allocate context: %s" % msg)
     625        log("avformat_alloc_output_context2 returned %i, format context=%#x", r, <unsigned long> self.format_ctx)
     626
     627        self.stream = avformat_new_stream(self.format_ctx, self.codec)
     628        log("avformat_new_stream=%#x", <unsigned long> self.stream)
     629        self.stream.id = 0
     630
     631        self.codec_ctx = self.stream.codec
    349632        if self.codec_ctx==NULL:
    350633            self.clean_encoder()
    351634            raise Exception("failed to allocate codec context!")
     
    369652        self.codec_ctx.thread_count = 0     #auto
    370653        self.codec_ctx.flags2 |= CODEC_FLAG2_FAST   #may cause "no deblock across slices" - which should be fine
    371654        #av_opt_set(c->priv_data, "preset", "slow", 0)
    372         cdef int r = avcodec_open2(self.codec_ctx, self.codec, NULL)
    373         if r<0:
     655        r = avcodec_open2(self.codec_ctx, self.codec, NULL)
     656        if r!=0:
    374657            self.clean_encoder()
    375658            raise Exception("could not open %s encoder context: %s" % (self.encoding, av_error_str(r)))
     659
    376660        self.av_frame = av_frame_alloc()
    377661        if self.av_frame==NULL:
    378662            self.clean_encoder()
     
    379663            raise Exception("could not allocate an AVFrame for encoding")
    380664        self.frames = 0
    381665        log("enc_ffmpeg.Encoder.init_context(%s, %s, %s) self=%s", width, height, src_format, self.get_info())
     666
    382667        gen = generation.increase()
    383         if SAVE_TO_FILE is not None:
    384             filename = SAVE_TO_FILE+"ffmpeg-"+self.encoding+"-"+str(gen)+".%s" % encoding
    385             self.file = open(filename, 'wb')
    386             log.info("saving %s stream to %s", encoding, filename)
     668        filename = SAVE_TO_FILE+"ffmpeg-"+self.encoding+"-"+str(gen)+".%s" % muxer_format
     669        r = avio_open(&self.format_ctx.pb, filename, AVIO_FLAG_WRITE)
     670        if r!=0:
     671            self.clean_encoder()
     672            msg = av_error_str(r)
     673            raise Exception("libavformat cannot open file '%s': %s" % (filename, msg))
     674        log.info("saving %s stream to %s", encoding, filename)
     675        r = avformat_write_header(self.format_ctx, NULL)
     676        if r!=0:
     677            self.clean_encoder()
     678            msg = av_error_str(r)
     679            raise Exception("libavformat failed to write header: %s" % msg)
    387680
     681
    388682    def clean(self):
    389683        self.clean_encoder()
    390684        self.codec = NULL
     
    395689        self.width = 0
    396690        self.height = 0
    397691        self.encoding = ""
    398         f = self.file
    399         if f:
    400             self.file = None
    401             f.close()
    402692
    403693
    404694    def clean_encoder(self):
     
    410700            av_frame_free(&self.av_frame)
    411701            #redundant: self.frame = NULL
    412702
     703        if self.format_ctx!=NULL:
     704            if SAVE_TO_FILE is not None and self.frames>0:
     705                log("clean_encoder() writing trailer to stream")
     706                av_write_trailer(self.format_ctx)
     707
     708                r = avio_close(self.format_ctx.pb)
     709                if r<0:
     710                    log.error("Error closing IO context: %s", av_error_str(r))
     711
     712            log("clean_encoder() freeing av format context %#x", <unsigned long> self.format_ctx)
     713            avformat_free_context(self.format_ctx)
     714            self.format_ctx = NULL
     715            #freed for us already!
     716            self.codec_ctx = NULL
     717
    413718        cdef unsigned long ctx_key          #@DuplicatedSignature
    414719        log("clean_encoder() freeing AVCodecContext: %#x", <unsigned long> self.codec_ctx)
    415720        if self.codec_ctx!=NULL:
     
    419724                log.error(" %s", av_error_str(r))
    420725            av_free(self.codec_ctx)
    421726            self.codec_ctx = NULL
     727
    422728        log("clean_encoder() done")
    423729
    424730    def __repr__(self):                      #@DuplicatedSignature
     
    565871            log("avcodec_receive_packet returned %#x bytes of data", avpkt.size)
    566872            packet_data = avpkt.data[:avpkt.size]
    567873            bufs.append(packet_data)
    568             if self.file and packet_data:
    569                 self.file.write(packet_data)
    570                 self.file.flush()
     874            if SAVE_TO_FILE is not None:
     875                #pkt.flags        |= AV_PKT_FLAG_KEY;
     876                avpkt.stream_index = self.stream.index
     877                av_interleaved_write_frame(self.format_ctx, &avpkt)
    571878        av_packet_unref(&avpkt)
    572879        free(avpkt.data)
    573880        self.frames += 1