Ticket #1107: mpeg4-muxer-v19.patch
File mpeg4-muxer-v19.patch, 42.5 KB (added by , 6 years ago) |
---|
-
../rpmbuild/ffmpeg-xpra.spec
1 1 %global real_name ffmpeg 2 2 Name: ffmpeg-xpra 3 3 Version: 3.2 4 Release: 1%{?dist}4 Release: 2%{?dist} 5 5 Summary: ffmpeg libraries for xpra 6 6 7 7 Group: Applications/Multimedia … … 64 64 --enable-encoder=libvpx_vp9 \ 65 65 --enable-encoder=mpeg4 \ 66 66 --enable-encoder=libx264 \ 67 --enable-encoder=aac \ 67 68 --enable-muxer=mp4 \ 68 69 --enable-muxer=webm \ 69 70 --enable-muxer=matroska \ … … 139 140 140 141 141 142 %changelog 143 * Fri Nov 04 2016 Antoine Martin <antoine@devloop.org.uk> 3.2-2 144 - add aac encoder for html5 client 145 142 146 * Sun Oct 30 2016 Antoine Martin <antoine@devloop.org.uk> 3.2-1 143 147 - new upstream release 144 148 -
xpra/server/window/window_source.py
689 689 690 690 691 691 def update_encoding_selection(self, encoding=None, exclude=[], init=False): 692 log.error("ws.update_encoding_selection(%s, %s, %s)", encoding, exclude, init) 692 693 #now we have the real list of encodings we can use: 693 694 #"rgb32" and "rgb24" encodings are both aliased to "rgb" 694 695 common_encodings = [x for x in self._encoders.keys() if x in self.core_encodings and x not in exclude] … … 703 704 self.encoding = encoding 704 705 else: 705 706 self.encoding = self.common_encodings[0] 706 log(" ws.update_encoding_selection(%s, %s, %s) encoding=%s, common encodings=%s", encoding, exclude, init, self.encoding, self.common_encodings)707 log("update_encoding_selection(%s, %s, %s) encoding=%s, common encodings=%s", encoding, exclude, init, self.encoding, self.common_encodings) 707 708 assert self.encoding is not None 708 709 self.update_quality() 709 710 self.update_speed() -
xpra/server/window/window_video_source.py
288 288 289 289 def update_encoding_selection(self, encoding=None, exclude=[], init=False): 290 290 #override so we don't use encodings that don't have valid csc modes: 291 log("wvs.update_encoding_selection(%s, %s, %s)", encoding, exclude, init) 291 log.error("wvs.update_encoding_selection(%s, %s, %s)", encoding, exclude, init) 292 log.error("video encodings=%s, core encodings=%s", self.video_encodings, self.core_encodings) 293 if exclude: 294 import traceback 295 traceback.print_stack() 292 296 for x in self.video_encodings: 293 297 if x not in self.core_encodings: 298 log.warn("%s not supported by client", x) 294 299 exclude.append(x) 295 300 continue 296 301 csc_modes = self.full_csc_modes.get(x) 302 csclog.info("full_csc_modes[%s]=%s", x, csc_modes) 297 303 if not csc_modes or x not in self.core_encodings: 298 304 exclude.append(x) 299 305 if not init: … … 301 307 else: 302 308 l = log 303 309 l("client does not support any csc modes with %s", x) 310 log.warn("exclude=%s", exclude) 304 311 WindowSource.update_encoding_selection(self, encoding, exclude, init) 305 312 306 313 def do_set_client_properties(self, properties): -
xpra/codecs/enc_ffmpeg/encoder.pyx
4 4 # later version. See the file COPYING for details. 5 5 6 6 import os 7 import time 8 import errno 7 9 import weakref 8 10 from xpra.log import Logger 9 11 log = Logger("encoder", "ffmpeg") … … 12 14 from xpra.codecs.codec_constants import get_subsampling_divs, video_spec 13 15 from xpra.codecs.libav_common.av_log cimport override_logger, restore_logger #@UnresolvedImport 14 16 from xpra.codecs.libav_common.av_log import suspend_nonfatal_logging, resume_nonfatal_logging 15 from xpra.util import AtomicInteger, csv, print_nested_dict, envint 17 from xpra.util import AtomicInteger, csv, print_nested_dict, envint, envbool 16 18 from xpra.os_util import bytestostr 17 19 18 20 SAVE_TO_FILE = os.environ.get("XPRA_SAVE_TO_FILE") … … 19 21 20 22 THREAD_TYPE = envint("XPRA_FFMPEG_THREAD_TYPE", 2) 21 23 THREAD_COUNT= envint("XPRA_FFMPEG_THREAD_COUNT") 24 AUDIO = envbool("XPRA_FFMPEG_MPEG4_AUDIO", False) 22 25 23 26 24 from libc.stdint cimport uint8_t, int64_t 27 from libc.stdint cimport uint8_t, int64_t, uint32_t 25 28 26 29 cdef extern from "../../inline.h": 27 30 pass … … 52 55 #why can't we define this inside the avcodec.h section? (beats me) 53 56 ctypedef unsigned int AVCodecID 54 57 ctypedef long AVPixelFormat 58 ctypedef long AVSampleFormat 55 59 ctypedef int AVPictureType 56 60 57 61 … … 65 69 int AV_PICTURE_TYPE_SP 66 70 int AV_PICTURE_TYPE_BI 67 71 72 cdef extern from "libavutil/dict.h": 73 int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags) 74 void av_dict_free(AVDictionary **m) 75 68 76 cdef extern from "libavutil/pixfmt.h": 69 77 AVPixelFormat AV_PIX_FMT_NONE 70 78 AVPixelFormat AV_PIX_FMT_YUV420P … … 77 85 AVPixelFormat AV_PIX_FMT_BGRA 78 86 AVPixelFormat AV_PIX_FMT_GBRP 79 87 88 cdef extern from "libavutil/samplefmt.h": 89 AVSampleFormat AV_SAMPLE_FMT_S16 90 AVSampleFormat AV_SAMPLE_FMT_FLTP 80 91 92 93 cdef extern from "libavformat/avio.h": 94 ctypedef int AVIODataMarkerType 95 int AVIO_FLAG_WRITE 96 97 ctypedef struct AVIOContext: 98 const AVClass *av_class 99 unsigned char *buffer #Start of the buffer 100 int buffer_size #Maximum buffer size 101 unsigned char *buf_ptr #Current position in the buffer 102 unsigned char *buf_end #End of the data, may be less than 103 #buffer+buffer_size if the read function returned 104 #less data than requested, e.g. for streams where 105 #no more data has been received yet. 106 int64_t pos #position in the file of the current buffer 107 int must_flush #true if the next seek should flush 108 int error #contains the error code or 0 if no error happened 109 int seekable 110 int64_t maxsize 111 int direct 112 int64_t bytes_read 113 114 AVIOContext *avio_alloc_context(unsigned char *buffer, int buffer_size, int write_flag, 115 void *opaque, 116 int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), 117 int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), 118 int64_t (*seek)(void *opaque, int64_t offset, int whence)) 119 120 81 121 cdef extern from "libavcodec/avcodec.h": 82 122 int FF_THREAD_SLICE #allow more than one thread per frame 83 123 int FF_THREAD_FRAME #Decode more than one frame at once … … 174 214 AVRational time_base 175 215 unsigned int codec_tag 176 216 int64_t bit_rate 217 AVSampleFormat sample_fmt 218 int sample_rate 219 int channels 177 220 221 ctypedef struct AVFormatContext: 222 const AVClass *av_class 223 AVOutputFormat *oformat 224 void *priv_data 225 AVIOContext *pb 226 int ctx_flags 227 unsigned int nb_streams 228 AVStream **streams 229 int64_t start_time 230 int64_t duration 231 int bit_rate 232 unsigned int packet_size 233 int max_delay 234 int flags 235 unsigned int probesize 236 int max_analyze_duration 237 AVCodecID video_codec_id 238 AVCodecID audio_codec_id 239 AVCodecID subtitle_codec_id 240 unsigned int max_index_size 241 unsigned int max_picture_buffer 242 unsigned int nb_chapters 243 AVDictionary *metadata 244 int64_t start_time_realtime 245 int strict_std_compliance 246 247 ctypedef int AVFieldOrder 248 ctypedef int AVColorRange 249 ctypedef int AVColorPrimaries 250 ctypedef int AVColorTransferCharacteristic 251 ctypedef int AVColorSpace 252 ctypedef int AVChromaLocation 253 ctypedef struct AVCodecParameters: 254 AVCodecID codec_id 255 uint32_t codec_tag 256 int64_t bit_rate 257 int bits_per_coded_sample 258 int bits_per_raw_sample 259 int profile 260 int level 261 int width 262 int height 263 AVFieldOrder field_order 264 AVColorRange color_range 265 AVColorPrimaries color_primaries 266 AVColorTransferCharacteristic color_trc 267 AVColorSpace color_space 268 AVChromaLocation chroma_location 269 int sample_rate 270 int frame_size 271 178 272 AVCodecID AV_CODEC_ID_H264 179 273 AVCodecID AV_CODEC_ID_H265 180 274 AVCodecID AV_CODEC_ID_VP8 … … 181 275 AVCodecID AV_CODEC_ID_VP9 182 276 AVCodecID AV_CODEC_ID_MPEG4 183 277 278 AVCodecID AV_CODEC_ID_AAC 279 184 280 #init and free: 185 281 void avcodec_register_all() 186 282 AVCodec *avcodec_find_encoder(AVCodecID id) … … 189 285 int avcodec_send_frame(AVCodecContext *avctx,const AVFrame *frame) nogil 190 286 int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) nogil 191 287 288 int av_write_frame(AVFormatContext *s, AVPacket *pkt) 192 289 AVFrame* av_frame_alloc() 193 290 void av_frame_free(AVFrame **frame) 194 291 int avcodec_close(AVCodecContext *avctx) 292 void av_frame_unref(AVFrame *frame) nogil 195 293 void av_init_packet(AVPacket *pkt) nogil 196 294 void av_packet_unref(AVPacket *pkt) nogil 197 295 … … 247 345 #AVClassCategory (*get_category)(void *ctx) 248 346 249 347 348 cdef extern from "libavformat/avformat.h": 349 int AVFMTCTX_NOHEADER #signal that no header is present 350 351 int AVFMT_FLAG_GENPTS #Generate missing pts even if it requires parsing future frames 352 int AVFMT_FLAG_IGNIDX #Ignore index 353 int AVFMT_FLAG_NONBLOCK #Do not block when reading packets from input 354 int AVFMT_FLAG_IGNDTS #Ignore DTS on frames that contain both DTS & PTS 355 int AVFMT_FLAG_NOFILLIN #Do not infer any values from other values, just return what is stored in the container 356 int AVFMT_FLAG_NOPARSE #Do not use AVParsers, you also must set AVFMT_FLAG_NOFILLIN as the fillin code works on frames and no parsing -> no frames. Also seeking to frames can not work if parsing to find frame boundaries has been disabled 357 int AVFMT_FLAG_NOBUFFER #Do not buffer frames when possible 358 int AVFMT_FLAG_CUSTOM_IO #The caller has supplied a custom AVIOContext, don't avio_close() it 359 int AVFMT_FLAG_DISCARD_CORRUPT #Discard frames marked corrupted 360 int AVFMT_FLAG_FLUSH_PACKETS #Flush the AVIOContext every packet 361 int AVFMT_FLAG_BITEXACT 362 int AVFMT_FLAG_MP4A_LATM #Enable RTP MP4A-LATM payload 363 int AVFMT_FLAG_SORT_DTS #try to interleave outputted packets by dts (using this flag can slow demuxing down) 364 int AVFMT_FLAG_PRIV_OPT #Enable use of private options by delaying codec open (this could be made default once all code is converted) 365 int AVFMT_FLAG_KEEP_SIDE_DATA #Don't merge side data but keep it separate. 366 int AVFMT_FLAG_FAST_SEEK #Enable fast, but inaccurate seeks for some formats 367 368 int AVFMT_NOFILE #Demuxer will use avio_open, no opened file should be provided by the caller 369 int AVFMT_NEEDNUMBER #Needs '%d' in filename 370 int AVFMT_SHOW_IDS #Show format stream IDs numbers 371 int AVFMT_RAWPICTURE #Format wants AVPicture structure for raw picture data. @deprecated Not used anymore 372 int AVFMT_GLOBALHEADER #Format wants global header 373 int AVFMT_NOTIMESTAMPS #Format does not need / have any timestamps 374 int AVFMT_GENERIC_INDEX #Use generic index building code 375 int AVFMT_TS_DISCONT #Format allows timestamp discontinuities. Note, muxers always require valid (monotone) timestamps 376 int AVFMT_VARIABLE_FPS #Format allows variable fps 377 int AVFMT_NODIMENSIONS #Format does not need width/height 378 int AVFMT_NOSTREAMS #Format does not require any streams 379 int AVFMT_NOBINSEARCH #Format does not allow to fall back on binary search via read_timestamp 380 int AVFMT_NOGENSEARCH #Format does not allow to fall back on generic search 381 int AVFMT_NO_BYTE_SEEK #Format does not allow seeking by bytes 382 int AVFMT_ALLOW_FLUSH #Format allows flushing. If not set, the muxer will not receive a NULL packet in the write_packet function 383 int AVFMT_TS_NONSTRICT #Format does not require strictly increasing timestamps, but they must still be monotonic 384 int AVFMT_TS_NEGATIVE #Format allows muxing negative timestamps. 385 int AVFMT_SEEK_TO_PTS #Seeking is based on PTS 386 387 ctypedef struct AVStream: 388 int index #stream index in AVFormatContext 389 int id 390 AVCodecContext *codec 391 AVRational time_base 392 int64_t start_time 393 int64_t duration 394 int64_t nb_frames #number of frames in this stream if known or 0 395 #AVDiscard discard #Selects which packets can be discarded at will and do not need to be demuxed. 396 AVRational avg_frame_rate 397 AVCodecParameters *codecpar 398 399 ctypedef struct AVOutputFormat: 400 const char *name 401 const char *long_name 402 const char *mime_type 403 const char *extensions 404 AVCodecID audio_codec 405 AVCodecID video_codec 406 AVCodecID subtitle_codec 407 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... 408 int (*query_codec)(AVCodecID id, int std_compliance) 409 410 void av_register_all() 411 AVOutputFormat *av_oformat_next(const AVOutputFormat *f) 412 int avformat_alloc_output_context2(AVFormatContext **ctx, AVOutputFormat *oformat, const char *format_name, const char *filename) 413 void avformat_free_context(AVFormatContext *s) 414 415 int avcodec_parameters_from_context(AVCodecParameters *par, const AVCodecContext *codec) 416 AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c) 417 int avformat_write_header(AVFormatContext *s, AVDictionary **options) 418 int av_write_trailer(AVFormatContext *s) 419 int av_write_frame(AVFormatContext *s, AVPacket *pkt) 420 421 250 422 AV_OPT_TYPES = { 251 423 AV_OPT_TYPE_FLAGS : "FLAGS", 252 424 AV_OPT_TYPE_INT : "INT", … … 274 446 AV_PKT_FLAG_CORRUPT : "CORRUPT", 275 447 } 276 448 449 AVFMTCTX = { 450 AVFMTCTX_NOHEADER : "NOHEADER", 451 } 452 277 453 CODEC_FLAGS = { 278 454 CODEC_FLAG_UNALIGNED : "UNALIGNED", 279 455 CODEC_FLAG_QSCALE : "QSCALE", … … 298 474 CODEC_FLAG2_FAST : "FAST", 299 475 } 300 476 477 FMT_FLAGS = { 478 AVFMT_FLAG_GENPTS : "GENPTS", 479 AVFMT_FLAG_IGNIDX : "IGNIDX", 480 AVFMT_FLAG_NONBLOCK : "NONBLOCK", 481 AVFMT_FLAG_IGNDTS : "IGNDTS", 482 AVFMT_FLAG_NOFILLIN : "NOFILLIN", 483 AVFMT_FLAG_NOPARSE : "NOPARSE", 484 AVFMT_FLAG_NOBUFFER : "NOBUFFER", 485 AVFMT_FLAG_CUSTOM_IO : "CUSTOM_IO", 486 AVFMT_FLAG_DISCARD_CORRUPT : "DISCARD_CORRUPT", 487 AVFMT_FLAG_FLUSH_PACKETS : "FLUSH_PACKETS", 488 AVFMT_FLAG_BITEXACT : "BITEXACT", 489 AVFMT_FLAG_MP4A_LATM : "MP4A_LATM", 490 AVFMT_FLAG_SORT_DTS : "SORT_DTS", 491 AVFMT_FLAG_PRIV_OPT : "PRIV_OPT", 492 AVFMT_FLAG_KEEP_SIDE_DATA : "KEEP_SIDE_DATA", 493 AVFMT_FLAG_FAST_SEEK : "FAST_SEEK", 494 } 495 496 AVFMT = { 497 AVFMT_NOFILE : "NOFILE", 498 AVFMT_NEEDNUMBER : "NEEDNUMBER", 499 AVFMT_SHOW_IDS : "SHOW_IDS", 500 AVFMT_RAWPICTURE : "RAWPICTURE", 501 AVFMT_GLOBALHEADER : "GLOBALHEADER", 502 AVFMT_NOTIMESTAMPS : "NOTIMESTAMPS", 503 AVFMT_GENERIC_INDEX : "GENERIC_INDEX", 504 AVFMT_TS_DISCONT : "TS_DISCONT", 505 AVFMT_VARIABLE_FPS : "VARIABLE_FPS", 506 AVFMT_NODIMENSIONS : "NODIMENSIONS", 507 AVFMT_NOSTREAMS : "NOSTREAMS", 508 AVFMT_NOBINSEARCH : "NOBINSEARCH", 509 AVFMT_NOGENSEARCH : "NOGENSEARCH", 510 AVFMT_NO_BYTE_SEEK : "NO_BYTE_SEEK", 511 AVFMT_ALLOW_FLUSH : "ALLOW_FLUSH", 512 AVFMT_TS_NONSTRICT : "TS_NONSTRICT", 513 AVFMT_TS_NEGATIVE : "TS_NEGATIVE", 514 AVFMT_SEEK_TO_PTS : "SEEK_TO_PTS", 515 } 516 517 301 518 CAPS = { 302 519 CODEC_CAP_DRAW_HORIZ_BAND : "DRAW_HORIZ_BAND", 303 520 CODEC_CAP_DR1 : "DR1", … … 356 573 def flagscsv(flag_dict, value=0): 357 574 return csv([v for k,v in flag_dict.items() if k&value]) 358 575 576 577 def get_muxer_formats(): 578 av_register_all() 579 cdef AVOutputFormat *fmt = NULL 580 formats = {} 581 while True: 582 fmt = av_oformat_next(fmt) 583 if fmt==NULL: 584 break 585 name = fmt.name 586 long_name = fmt.long_name 587 formats[name] = long_name 588 return formats 589 log("AV Output Formats:") 590 print_nested_dict(get_muxer_formats(), print_fn=log.debug) 591 592 cdef AVOutputFormat* get_av_output_format(name): 593 cdef AVOutputFormat *fmt = NULL 594 while True: 595 fmt = av_oformat_next(fmt) 596 if fmt==NULL: 597 break 598 if name==fmt.name: 599 return fmt 600 return NULL 601 602 359 603 def get_version(): 360 604 return (LIBAVCODEC_VERSION_MAJOR, LIBAVCODEC_VERSION_MINOR, LIBAVCODEC_VERSION_MICRO) 361 605 … … 362 606 avcodec_register_all() 363 607 CODECS = [] 364 608 if avcodec_find_encoder(AV_CODEC_ID_H264)!=NULL: 365 CODECS.append("h264 ")609 CODECS.append("h264+mp4") 366 610 #if avcodec_find_encoder(AV_CODEC_ID_VP8)!=NULL: 367 611 # CODECS.append("vp8") 368 612 #if avcodec_find_encoder(AV_CODEC_ID_VP9)!=NULL: … … 370 614 #if avcodec_find_encoder(AV_CODEC_ID_H265)!=NULL: 371 615 # CODECS.append("h265") 372 616 if avcodec_find_encoder(AV_CODEC_ID_MPEG4)!=NULL: 373 CODECS.append("mpeg4 ")617 CODECS.append("mpeg4+mp4") 374 618 log("enc_ffmpeg CODECS=%s", csv(CODECS)) 375 619 376 620 cdef av_error_str(int errnum): … … 382 626 return bytestostr(err_str[:i]) 383 627 return "error %s" % errnum 384 628 385 DEF EAGAIN = -11629 DEF DEFAULT_BUF_LEN = 64*1024 386 630 387 631 388 632 def init_module(): … … 405 649 return { 406 650 "version" : get_version(), 407 651 "encodings" : get_encodings(), 652 "muxers" : get_muxer_formats(), 408 653 "buffer_api" : get_buffer_api_version(), 409 654 "formats" : f, 410 655 "generation" : generation.get(), … … 423 668 return ["YUV420P"] 424 669 425 670 671 GEN_TO_ENCODER = weakref.WeakValueDictionary() 672 673 674 cdef list_options(void *obj, const AVClass *av_class): 675 if av_class==NULL: 676 return 677 cdef const AVOption *option = <const AVOption*> av_class.option 678 options = [] 679 while option!=NULL: 680 oname = option.name 681 options.append(oname) 682 option = av_opt_next(obj, option) 683 log("%s options: %s", av_class.class_name, csv(options)) 684 cdef void *child = NULL 685 cdef const AVClass *child_class = NULL 686 while True: 687 child = av_opt_child_next(obj, child) 688 if child==NULL: 689 return 690 child_class = (<AVClass**> child)[0] 691 list_options(child, child_class) 692 693 694 cdef int write_packet(void *opaque, uint8_t *buf, int buf_size): 695 global GEN_TO_ENCODER 696 encoder = GEN_TO_ENCODER.get(<unsigned long> opaque) 697 #log.warn("write_packet(%#x, %#x, %#x) encoder=%s", <unsigned long> opaque, <unsigned long> buf, buf_size, type(encoder)) 698 if not encoder: 699 log.error("Error: write_packet called for unregistered encoder %i!", <unsigned long> opaque) 700 return -1 701 return encoder.write_packet(<unsigned long> buf, buf_size) 702 426 703 MAX_WIDTH, MAX_HEIGHT = 4096, 4096 427 704 def get_spec(encoding, colorspace): 428 705 assert encoding in get_encodings(), "invalid encoding: %s (must be one of %s" % (encoding, get_encodings()) … … 437 714 """ 438 715 This wraps the AVCodecContext and its configuration, 439 716 """ 440 cdef AVCodecID codec_id 441 cdef AVCodec *codec 442 cdef AVCodecContext *codec_ctx 717 #muxer: 718 cdef AVFormatContext *muxer_ctx 719 cdef unsigned char *buffer 720 cdef object buffers 721 cdef int64_t offset 722 cdef object muxer_format 723 cdef object file 724 #video: 725 cdef AVCodec *video_codec 726 cdef AVStream *video_stream 727 cdef AVCodecContext *video_ctx 443 728 cdef AVPixelFormat pix_fmt 444 729 cdef object src_format 445 730 cdef AVFrame *av_frame 446 #this is the actual number of images we have returned447 731 cdef unsigned long frames 448 732 cdef unsigned int width 449 733 cdef unsigned int height 450 734 cdef object encoding 451 cdef object file 735 #audio: 736 cdef AVCodec *audio_codec 737 cdef AVStream *audio_stream 738 cdef AVCodecContext *audio_ctx 452 739 453 740 cdef object __weakref__ 454 741 … … 458 745 assert encoding in CODECS 459 746 assert src_format in get_input_colorspaces(encoding), "invalid colorspace: %s" % src_format 460 747 self.encoding = encoding 748 self.muxer_format = encoding.split("+")[1] #ie: "mp4" #"mov", "f4v" 749 assert self.muxer_format=="mp4" 461 750 self.width = width 462 751 self.height = height 463 752 self.src_format = src_format … … 464 753 self.pix_fmt = FORMAT_TO_ENUM.get(src_format, AV_PIX_FMT_NONE) 465 754 if self.pix_fmt==AV_PIX_FMT_NONE: 466 755 raise Exception("invalid pixel format: %s", src_format) 756 self.buffers = [] 467 757 758 codec = self.encoding.split("+")[0] 468 759 avcodec_register_all() 469 if self.encoding=="h264": 470 self.codec_id = AV_CODEC_ID_H264 471 elif self.encoding=="h265": 472 self.codec_id = AV_CODEC_ID_H265 473 elif self.encoding=="vp8": 474 self.codec_id = AV_CODEC_ID_VP8 475 elif self.encoding=="vp9": 476 self.codec_id = AV_CODEC_ID_VP9 477 elif self.encoding=="mpeg4": 478 self.codec_id = AV_CODEC_ID_MPEG4 760 cdef AVCodecID video_codec_id 761 if codec=="h264": 762 video_codec_id = AV_CODEC_ID_H264 763 elif codec=="h265": 764 video_codec_id = AV_CODEC_ID_H265 765 elif codec=="vp8": 766 video_codec_id = AV_CODEC_ID_VP8 767 elif codec=="vp9": 768 video_codec_id = AV_CODEC_ID_VP9 769 elif codec=="mpeg4": 770 video_codec_id = AV_CODEC_ID_MPEG4 479 771 else: 480 772 raise Exception("invalid codec; %s" % self.encoding) 481 self. codec = avcodec_find_encoder(self.codec_id)482 if self. codec==NULL:773 self.video_codec = avcodec_find_encoder(video_codec_id) 774 if self.video_codec==NULL: 483 775 raise Exception("codec %s not found!" % self.encoding) 484 log("%s: \"%s\", codec flags: %s", self. codec.name, self.codec.long_name, flagscsv(CAPS, self.codec.capabilities))776 log("%s: \"%s\", codec flags: %s", self.video_codec.name, self.video_codec.long_name, flagscsv(CAPS, self.video_codec.capabilities)) 485 777 778 #TODO: the muxer should be configurable 486 779 cdef int b_frames = 0 #int(options.get("b-frames")) 487 780 try: 488 781 self.init_encoder(b_frames) … … 494 787 log("enc_ffmpeg.Encoder.init_context(%s, %s, %s) self=%s", self.width, self.height, self.src_format, self.get_info()) 495 788 496 789 def init_encoder(self, int b_frames): 790 global GEN_TO_ENCODER 791 cdef AVOutputFormat *oformat = get_av_output_format(self.muxer_format) 792 if oformat==NULL: 793 raise Exception("libavformat does not support %s" % self.muxer_format) 794 log("init_encoder() AVOutputFormat(%s)=%#x, flags=%s", self.muxer_format, <unsigned long> oformat, flagscsv(AVFMT, oformat.flags)) 795 if oformat.flags & AVFMT_ALLOW_FLUSH==0: 796 raise Exception("AVOutputFormat(%s) does not support flushing!" % self.muxer_format) 797 r = avformat_alloc_output_context2(&self.muxer_ctx, oformat, self.muxer_format, NULL) 798 if r!=0: 799 msg = av_error_str(r) 800 raise Exception("libavformat cannot allocate context: %s" % msg) 801 log("init_encoder() avformat_alloc_output_context2 returned %i, format context=%#x, flags=%s, ctx_flags=%s", r, <unsigned long> self.muxer_ctx, 802 flagscsv(FMT_FLAGS, self.muxer_ctx.flags), flagscsv(AVFMTCTX, self.muxer_ctx.ctx_flags)) 803 list_options(self.muxer_ctx, self.muxer_ctx.av_class) 804 805 cdef int64_t v = 0 806 r = av_opt_get_int(self.muxer_ctx, "movflags", AV_OPT_SEARCH_CHILDREN, &v) 807 if r==0: 808 FF_MOV_FLAG_FRAGMENT = 1<<1 809 FF_MOV_FLAG_EMPTY_MOOV = 1<<2 810 FF_MOV_FLAG_FRAG_KEYFRAME = 1<<3 811 FF_MOV_FLAG_OMIT_TFHD_OFFSET = 1<<8 812 FF_MOV_FLAG_DEFAULT_BASE_MOOF = 1<<10 813 v |= FF_MOV_FLAG_FRAGMENT | FF_MOV_FLAG_EMPTY_MOOV | FF_MOV_FLAG_FRAG_KEYFRAME | FF_MOV_FLAG_OMIT_TFHD_OFFSET | FF_MOV_FLAG_DEFAULT_BASE_MOOF 814 log("movflags=%#x", v) 815 r = av_opt_set_int(self.muxer_ctx, "movflags", v, AV_OPT_SEARCH_CHILDREN) 816 if r!=0: 817 log.error("Error: failed to set movflags") 818 log.error(" %s", av_error_str(r)) 819 497 820 cdef unsigned long gen = generation.increase() 821 GEN_TO_ENCODER[gen] = self 822 self.buffer = <unsigned char*> av_malloc(DEFAULT_BUF_LEN) 823 if self.buffer==NULL: 824 raise Exception("failed to allocate %iKB of memory" % (DEFAULT_BUF_LEN//1024)) 825 self.muxer_ctx.pb = avio_alloc_context(self.buffer, DEFAULT_BUF_LEN, 1, <void *> gen, NULL, write_packet, NULL) 826 if self.muxer_ctx.pb==NULL: 827 raise Exception("libavformat failed to allocate io context") 828 log("init_encoder() saving %s stream to bitstream buffer %#x", self.encoding, <unsigned long> self.buffer) 829 self.muxer_ctx.bit_rate = 500000 830 self.muxer_ctx.start_time_realtime = int(time.time()) 498 831 499 self. codec_ctx = avcodec_alloc_context3(self.codec)500 if self.codec_ctx==NULL:501 raise Exception("failed to allocate codec context!")832 self.video_stream = avformat_new_stream(self.muxer_ctx, NULL) #self.video_codec 833 self.video_stream.id = 0 834 log("init_encoder() video: avformat_new_stream=%#x, nb streams=%i", <unsigned long> self.video_stream, self.muxer_ctx.nb_streams) 502 835 836 self.video_ctx = avcodec_alloc_context3(self.video_codec) 837 if self.video_ctx==NULL: 838 raise Exception("failed to allocate video codec context!") 839 503 840 #we need a framerate.. make one up: 504 self.codec_ctx.framerate.num = 1 505 self.codec_ctx.framerate.den = 25 506 self.codec_ctx.time_base.num = 1 507 self.codec_ctx.time_base.den = 25 508 self.codec_ctx.refcounted_frames = 1 509 self.codec_ctx.max_b_frames = b_frames*1 510 self.codec_ctx.has_b_frames = b_frames 511 self.codec_ctx.delay = 0 512 self.codec_ctx.gop_size = 1 513 self.codec_ctx.width = self.width 514 self.codec_ctx.height = self.height 515 self.codec_ctx.bit_rate = 500000 516 self.codec_ctx.pix_fmt = self.pix_fmt 517 self.codec_ctx.thread_safe_callbacks = 1 518 self.codec_ctx.thread_type = THREAD_TYPE 519 self.codec_ctx.thread_count = THREAD_COUNT #0=auto 520 self.codec_ctx.flags2 |= CODEC_FLAG2_FAST #may cause "no deblock across slices" - which should be fine 841 self.video_ctx.framerate.num = 1 842 self.video_ctx.framerate.den = 25 843 self.video_ctx.time_base.num = 1 844 self.video_ctx.time_base.den = 25 845 self.video_ctx.refcounted_frames = 1 846 self.video_ctx.max_b_frames = b_frames*1 847 self.video_ctx.has_b_frames = b_frames 848 self.video_ctx.delay = 0 849 self.video_ctx.gop_size = 1 850 self.video_ctx.width = self.width 851 self.video_ctx.height = self.height 852 self.video_ctx.bit_rate = 500000 853 self.video_ctx.pix_fmt = self.pix_fmt 854 self.video_ctx.thread_safe_callbacks = 1 855 self.video_ctx.thread_type = THREAD_TYPE 856 self.video_ctx.thread_count = THREAD_COUNT #0=auto 857 #if oformat.flags & AVFMT_GLOBALHEADER: 858 self.video_ctx.flags |= CODEC_FLAG_GLOBAL_HEADER 859 self.video_ctx.flags2 |= CODEC_FLAG2_FAST #may cause "no deblock across slices" - which should be fine 521 860 #av_opt_set(c->priv_data, "preset", "slow", 0) 522 861 log("init_encoder() b-frames=%i, thread-type=%i, thread-count=%i", b_frames, THREAD_TYPE, THREAD_COUNT) 523 log("init_encoder() codec flags: %s", flagscsv(CODEC_FLAGS, self. codec_ctx.flags))524 log("init_encoder() codec flags2: %s", flagscsv(CODEC_FLAGS2, self. codec_ctx.flags2))862 log("init_encoder() codec flags: %s", flagscsv(CODEC_FLAGS, self.video_ctx.flags)) 863 log("init_encoder() codec flags2: %s", flagscsv(CODEC_FLAGS2, self.video_ctx.flags2)) 525 864 526 r = avcodec_open2(self. codec_ctx, self.codec, NULL) #NULL, NULL)865 r = avcodec_open2(self.video_ctx, self.video_codec, NULL) #NULL, NULL) 527 866 if r!=0: 528 867 raise Exception("could not open %s encoder context: %s" % (self.encoding, av_error_str(r))) 529 868 869 r = avcodec_parameters_from_context(self.video_stream.codecpar, self.video_ctx) 870 if r<0: 871 raise Exception("could not copy video context parameters %#x: %s" % (<unsigned long> self.video_stream.codecpar, av_error_str(r))) 872 873 if AUDIO: 874 #audio: 875 self.audio_codec = avcodec_find_encoder(AV_CODEC_ID_AAC) 876 if self.audio_codec==NULL: 877 raise Exception("cannot find audio codec!") 878 log("init_encoder() audio_codec=%#x", <unsigned long> self.audio_codec) 879 self.audio_stream = avformat_new_stream(self.muxer_ctx, NULL) 880 self.audio_stream.id = 1 881 log("init_encoder() audio: avformat_new_stream=%#x, nb streams=%i", <unsigned long> self.audio_stream, self.muxer_ctx.nb_streams) 882 self.audio_ctx = avcodec_alloc_context3(self.audio_codec) 883 log("init_encoder() audio_context=%#x", <unsigned long> self.audio_ctx) 884 self.audio_ctx.sample_fmt = AV_SAMPLE_FMT_FLTP 885 self.audio_ctx.time_base.den = 25 886 self.audio_ctx.time_base.num = 1 887 self.audio_ctx.bit_rate = 64000 888 self.audio_ctx.sample_rate = 44100 889 self.audio_ctx.channels = 2 890 #if audio_codec.capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE: 891 # pass 892 #cdef AVDictionary *opts = NULL 893 #av_dict_set(&opts, "strict", "experimental", 0) 894 #r = avcodec_open2(audio_ctx, audio_codec, &opts) 895 #av_dict_free(&opts) 896 r = avcodec_open2(self.audio_ctx, self.audio_codec, NULL) 897 if r!=0: 898 raise Exception("could not open %s encoder context: %s" % (self.encoding, av_error_str(r))) 899 if r!=0: 900 raise Exception("could not open %s encoder context: %s" % ("aac", av_error_str(r))) 901 r = avcodec_parameters_from_context(self.audio_stream.codecpar, self.audio_ctx) 902 if r<0: 903 raise Exception("could not copy audio context parameters %#x: %s" % (<unsigned long> self.audio_stream.codecpar, av_error_str(r))) 904 905 log("init_encoder() writing %s header", self.muxer_format) 906 r = avformat_write_header(self.muxer_ctx, NULL) 907 if r!=0: 908 msg = av_error_str(r) 909 raise Exception("libavformat failed to write header: %s" % msg) 910 530 911 self.av_frame = av_frame_alloc() 531 912 if self.av_frame==NULL: 532 913 raise Exception("could not allocate an AVFrame for encoding") … … 533 914 self.frames = 0 534 915 535 916 if SAVE_TO_FILE is not None: 536 filename = SAVE_TO_FILE+"-"+s tr(gen)+".%s" % self.encoding917 filename = SAVE_TO_FILE+"-"+self.encoding+"-"+str(gen)+".%s" % self.muxer_format 537 918 self.file = open(filename, 'wb') 538 log.info("saving stream to %s", filename)919 log.info("saving %s stream to %s", self.encoding, filename) 539 920 540 921 541 922 def clean(self): 923 #import traceback 924 #traceback.print_stack() 542 925 try: 543 926 self.clean_encoder() 544 927 except: 545 928 log.error("cleanup failed", exc_info=True) 546 self.codec = NULL 929 self.video_codec = NULL 930 self.audio_codec = NULL 547 931 self.pix_fmt = 0 548 932 self.src_format = "" 549 933 self.av_frame = NULL #should be redundant … … 551 935 self.width = 0 552 936 self.height = 0 553 937 self.encoding = "" 938 self.buffers = [] 554 939 f = self.file 555 940 if f: 556 941 self.file = None … … 562 947 if self.av_frame!=NULL: 563 948 log("clean_encoder() freeing AVFrame: %#x", <unsigned long> self.av_frame) 564 949 av_frame_free(&self.av_frame) 565 log("clean_encoder() freeing AVCodecContext: %#x", <unsigned long> self.codec_ctx) 566 if self.codec_ctx!=NULL: 567 r = avcodec_close(self.codec_ctx) 950 if self.muxer_ctx!=NULL: 951 if self.frames>0: 952 log("clean_encoder() writing trailer to stream") 953 av_write_trailer(self.muxer_ctx) 954 if self.muxer_ctx.pb!=NULL: 955 av_free(self.muxer_ctx.pb) 956 self.muxer_ctx.pb = NULL 957 log("clean_encoder() freeing av format context %#x", <unsigned long> self.muxer_ctx) 958 avformat_free_context(self.muxer_ctx) 959 self.muxer_ctx = NULL 960 log("clean_encoder() freeing bitstream buffer %#x", <unsigned long> self.buffer) 961 if self.buffer!=NULL: 962 av_free(self.buffer) 963 self.buffer = NULL 964 cdef unsigned long ctx_key #@DuplicatedSignature 965 log("clean_encoder() freeing AVCodecContext: %#x", <unsigned long> self.video_ctx) 966 if self.video_ctx!=NULL: 967 r = avcodec_close(self.video_ctx) 568 968 if r!=0: 569 log.error("Error: failed to close encoder context %#x", <unsigned long> self.codec_ctx)969 log.error("Error: failed to close video encoder context %#x", <unsigned long> self.video_ctx) 570 970 log.error(" %s", av_error_str(r)) 571 av_free(self.codec_ctx) 572 self.codec_ctx = NULL 971 av_free(self.video_ctx) 972 self.video_ctx = NULL 973 if self.audio_ctx!=NULL: 974 r = avcodec_close(self.audio_ctx) 975 if r!=0: 976 log.error("Error: failed to close audio encoder context %#x", <unsigned long> self.audio_ctx) 977 log.error(" %s", av_error_str(r)) 978 av_free(self.audio_ctx) 979 self.audio_ctx = NULL 573 980 log("clean_encoder() done") 574 981 575 982 def __repr__(self): #@DuplicatedSignature … … 581 988 info = { 582 989 "version" : get_version(), 583 990 "encoding" : self.encoding, 991 "muxer" : self.muxer_format, 584 992 "formats" : get_input_colorspaces(self.encoding), 585 993 "type" : self.get_type(), 586 994 "frames" : self.frames, … … 587 995 "width" : self.width, 588 996 "height" : self.height, 589 997 } 590 if self.codec: 591 info["codec"] = self.codec.name[:] 592 info["description"] = self.codec.long_name[:] 998 if self.video_codec: 999 info["video-codec"] = self.video_codec.name[:] 1000 info["video-description"] = self.video_codec.long_name[:] 1001 if self.audio_codec: 1002 info["audio-codec"] = self.audio_codec.name[:] 1003 info["audio-description"] = self.audio_codec.long_name[:] 593 1004 if self.src_format: 594 1005 info["src_format"] = self.src_format 595 1006 if not self.is_closed(): 596 info["encoder_width"] = self. codec_ctx.width597 info["encoder_height"] = self. codec_ctx.height1007 info["encoder_width"] = self.video_ctx.width 1008 info["encoder_height"] = self.video_ctx.height 598 1009 else: 599 1010 info["closed"] = True 600 1011 return info 601 1012 602 1013 def is_closed(self): 603 return self. codec_ctx==NULL1014 return self.video_ctx==NULL 604 1015 605 1016 def __dealloc__(self): #@DuplicatedSignature 606 1017 self.clean() … … 645 1056 cdef int ret 646 1057 cdef AVPacket avpkt 647 1058 cdef AVFrame *frame 648 assert self. codec_ctx!=NULL, "no codec context! (not initialized or already closed)"649 assert self. codec!=NULL1059 assert self.video_ctx!=NULL, "no codec context! (not initialized or already closed)" 1060 assert self.video_codec!=NULL 650 1061 651 1062 if image: 652 1063 assert image.get_pixel_format()==self.src_format, "invalid input format %s, expected %s" % (image.get_pixel_format, self.src_format) … … 672 1083 self.av_frame.coded_picture_number = self.frames+1 673 1084 self.av_frame.display_picture_number = self.frames+1 674 1085 #if self.frames==0: 675 #self.av_frame.pict_type = AV_PICTURE_TYPE_I1086 self.av_frame.pict_type = AV_PICTURE_TYPE_I 676 1087 #else: 677 1088 # self.av_frame.pict_type = AV_PICTURE_TYPE_P 678 1089 #self.av_frame.quality = 1 … … 682 1093 frame = NULL 683 1094 684 1095 with nogil: 685 ret = avcodec_send_frame(self. codec_ctx, frame)1096 ret = avcodec_send_frame(self.video_ctx, frame) 686 1097 if ret!=0: 687 1098 self.log_av_error(image, ret, options) 688 1099 raise Exception(av_error_str(ret)) … … 692 1103 avpkt.data = <uint8_t *> xmemalign(buf_len) 693 1104 avpkt.size = buf_len 694 1105 assert ret==0 695 bufs = []696 1106 client_options = {} 697 1107 while ret==0: 698 1108 with nogil: 699 ret = avcodec_receive_packet(self. codec_ctx, &avpkt)700 if ret== EAGAIN:1109 ret = avcodec_receive_packet(self.video_ctx, &avpkt) 1110 if ret==--errno.EAGAIN: 701 1111 client_options["delayed"] = 1 702 1112 log("ffmpeg EAGAIN: delayed picture") 703 1113 break 704 if ret!=0 and bufs: 705 log("avcodec_receive_packet returned error '%s' for image %s, returning existing buffer", av_error_str(ret), image) 1114 if ret!=0: 1115 if not image: 1116 log("avcodec_receive_packet returned error '%s' for flush request", av_error_str(ret)) 1117 else: 1118 log("avcodec_receive_packet returned error '%s' for image %s, returning existing buffer", av_error_str(ret), image) 706 1119 break 707 if ret!=0 and not image:708 log("avcodec_receive_packet returned error '%s' for flush request", av_error_str(ret))709 break710 1120 if ret<0: 711 1121 free(avpkt.data) 712 1122 self.log_av_error(image, ret, options) … … 720 1130 free(avpkt.data) 721 1131 self.log_error(image, "packet", options, "av packet is corrupt") 722 1132 raise Exception("av packet is corrupt") 723 packet_data = avpkt.data[:avpkt.size] 724 bufs.append(packet_data) 1133 1134 avpkt.stream_index = self.video_stream.index 1135 r = av_write_frame(self.muxer_ctx, &avpkt) 1136 log("av_write_frame packet returned %i", r) 1137 if ret<0: 1138 free(avpkt.data) 1139 self.log_av_error(image, ret, options) 1140 raise Exception(av_error_str(ret)) 1141 while True: 1142 r = av_write_frame(self.muxer_ctx, NULL) 1143 log("av_write_frame flush returned %i", r) 1144 if r==1: 1145 break 1146 if ret<0: 1147 free(avpkt.data) 1148 self.log_av_error(image, ret, options) 1149 raise Exception(av_error_str(ret)) 725 1150 av_packet_unref(&avpkt) 726 1151 free(avpkt.data) 727 1152 self.frames += 1 728 data = b"".join(bufs) 729 log("compress_image(%s) %5i bytes (%i buffers) for %4s frame %-3i, client options: %s", image, len(data), len(bufs), self.encoding, self.frames, client_options) 730 if data and self.file: 731 self.file.write(data) 1153 data = b"".join(self.buffers) 1154 log("compress_image(%s) %5i bytes (%i buffers) for %4s frame %-3i, client options: %s", image, len(data), len(self.buffers), self.encoding, self.frames, client_options) 1155 #client_options["raw-buffers"] = self.buffers 1156 if self.buffers and self.file: 1157 for x in self.buffers: 1158 self.file.write(x) 1159 self.buffers = [] 732 1160 return data, client_options 733 1161 734 1162 def flush(self, delayed): … … 737 1165 self.clean() 738 1166 return v 739 1167 1168 def write_packet(self, unsigned long buf, int buf_size): 1169 log("write_packet(%#x, %#x)", <unsigned long> buf, buf_size) 1170 cdef uint8_t *cbuf = <uint8_t*> buf 1171 buffer = cbuf[:buf_size] 1172 self.buffers.append(buffer) 1173 return buf_size 740 1174 1175 741 1176 def selftest(full=False): 742 1177 global CODECS 743 1178 from xpra.codecs.codec_checks import testencoder 744 1179 from xpra.codecs.enc_ffmpeg import encoder 745 1180 try: 746 suspend_nonfatal_logging()1181 #suspend_nonfatal_logging() 747 1182 CODECS = testencoder(encoder, full) 748 1183 finally: 749 resume_nonfatal_logging() 1184 pass 1185 #resume_nonfatal_logging() -
xpra/codecs/loader.py
248 248 249 249 #note: this is just for defining the order of encodings, 250 250 #so we have both core encodings (rgb24/rgb32) and regular encodings (rgb) in here: 251 PREFERED_ENCODING_ORDER = ["h264", "vp9", "vp8", "mpeg4", " png", "png/P", "png/L", "webp", "rgb", "rgb24", "rgb32", "jpeg", "h265"]251 PREFERED_ENCODING_ORDER = ["h264", "vp9", "vp8", "mpeg4", "h264+mp4", "mpeg4+mp4", "png", "png/P", "png/L", "webp", "rgb", "rgb24", "rgb32", "jpeg", "h265"] 252 252 #encoding order for edges (usually one pixel high or wide): 253 253 EDGE_ENCODING_ORDER = ["rgb24", "rgb32", "jpeg", "png", "webp", "png/P", "png/L", "rgb"] 254 254