def image_sequence_encode(self, codec_name): try: codec = Codec(codec_name, 'w') except UnknownCodecError: raise SkipTest() container = av.open(fate_suite('h264/interlaced_crop.mp4')) video_stream = container.streams.video[0] width = 640 height = 480 ctx = codec.create() pix_fmt = ctx.codec.video_formats[0].name ctx.width = width ctx.height = height ctx.time_base = video_stream.codec_context.time_base ctx.pix_fmt = pix_fmt ctx.open() frame_count = 1 path_list = [] for frame in iter_frames(container, video_stream): new_frame = frame.reformat(width, height, pix_fmt) new_packets = ctx.encode(new_frame) self.assertEqual(len(new_packets), 1) new_packet = new_packets[0] path = self.sandboxed('%s/encoder.%04d.%s' % ( codec_name, frame_count, codec_name if codec_name != 'mjpeg' else 'jpg', )) path_list.append(path) with open(path, 'wb') as f: f.write(new_packet) frame_count += 1 if frame_count > 5: break ctx = av.Codec(codec_name, 'r').create() for path in path_list: with open(path, 'rb') as f: size = os.fstat(f.fileno()).st_size packet = Packet(size) size = f.readinto(packet) frame = ctx.decode(packet)[0] self.assertEqual(frame.width, width) self.assertEqual(frame.height, height) self.assertEqual(frame.format.name, pix_fmt)
def image_sequence_encode(self, codec_name): try: codec = Codec(codec_name, "w") except UnknownCodecError: raise SkipTest() container = av.open(fate_suite("h264/interlaced_crop.mp4")) video_stream = container.streams.video[0] width = 640 height = 480 ctx = codec.create() pix_fmt = ctx.codec.video_formats[0].name ctx.width = width ctx.height = height ctx.time_base = video_stream.codec_context.time_base ctx.pix_fmt = pix_fmt ctx.open() frame_count = 1 path_list = [] for frame in iter_frames(container, video_stream): new_frame = frame.reformat(width, height, pix_fmt) new_packets = ctx.encode(new_frame) self.assertEqual(len(new_packets), 1) new_packet = new_packets[0] path = self.sandboxed("%s/encoder.%04d.%s" % ( codec_name, frame_count, codec_name if codec_name != "mjpeg" else "jpg", )) path_list.append(path) with open(path, "wb") as f: f.write(new_packet) frame_count += 1 if frame_count > 5: break ctx = av.Codec(codec_name, "r").create() for path in path_list: with open(path, "rb") as f: size = os.fstat(f.fileno()).st_size packet = Packet(size) size = f.readinto(packet) frame = ctx.decode(packet)[0] self.assertEqual(frame.width, width) self.assertEqual(frame.height, height) self.assertEqual(frame.format.name, pix_fmt)
def test_codec_tag(self): ctx = Codec("mpeg4", "w").create() self.assertEqual(ctx.codec_tag, "\x00\x00\x00\x00") ctx.codec_tag = "xvid" self.assertEqual(ctx.codec_tag, "xvid") # wrong length with self.assertRaises(ValueError) as cm: ctx.codec_tag = "bob" self.assertEqual(str(cm.exception), "Codec tag should be a 4 character string.") # wrong type with self.assertRaises(ValueError) as cm: ctx.codec_tag = 123 self.assertEqual(str(cm.exception), "Codec tag should be a 4 character string.") with av.open(fate_suite("h264/interlaced_crop.mp4")) as container: self.assertEqual(container.streams[0].codec_tag, "avc1")
def _assert_parse(self, codec_name, path): fh = av.open(path) packets = [] for packet in fh.demux(video=0): packets.append(packet) full_source = b"".join(bytes(p) for p in packets) for size in 1024, 8192, 65535: ctx = Codec(codec_name).create() packets = [] for i in range(0, len(full_source), size): block = full_source[i:i + size] packets.extend(ctx.parse(block)) packets.extend(ctx.parse()) parsed_source = b"".join(bytes(p) for p in packets) self.assertEqual(len(parsed_source), len(full_source)) self.assertEqual(full_source, parsed_source)
def test_codec_opus_decoder(self): c = Codec("opus") self.assertEqual(c.name, "opus") self.assertEqual(c.long_name, "Opus") self.assertEqual(c.type, "audio") self.assertTrue(c.is_decoder) self.assertFalse(c.is_encoder) # audio self.assertIsNone(c.audio_formats) self.assertIsNone(c.audio_rates) # video self.assertIsNone(c.video_formats) self.assertIsNone(c.frame_rates)
def test_codec_opus_encoder(self): c = Codec("opus", "w") self.assertIn(c.name, ("opus", "libopus")) self.assertIn(c.long_name, ("Opus", "libopus Opus")) self.assertEqual(c.type, "audio") self.assertTrue(c.is_encoder) self.assertFalse(c.is_decoder) # audio formats = c.audio_formats self.assertTrue(formats) self.assertIsInstance(formats[0], AudioFormat) self.assertTrue(any(f.name in ["flt", "fltp"] for f in formats)) self.assertIsNotNone(c.audio_rates) self.assertIn(48000, c.audio_rates) # video self.assertIsNone(c.video_formats) self.assertIsNone(c.frame_rates)
def test_codec_mpeg4_encoder(self): c = Codec("mpeg4", "w") self.assertEqual(c.name, "mpeg4") self.assertEqual(c.long_name, "MPEG-4 part 2") self.assertEqual(c.type, "video") self.assertIn(c.id, (12, 13)) self.assertTrue(c.is_encoder) self.assertFalse(c.is_decoder) # audio self.assertIsNone(c.audio_formats) self.assertIsNone(c.audio_rates) # video formats = c.video_formats self.assertTrue(formats) self.assertIsInstance(formats[0], VideoFormat) self.assertTrue(any(f.name == "yuv420p" for f in formats)) self.assertIsNone(c.frame_rates)
def audio_encoding(self, codec_name): try: codec = Codec(codec_name, "w") except UnknownCodecError: raise SkipTest() ctx = codec.create() if ctx.codec.experimental: raise SkipTest() sample_fmt = ctx.codec.audio_formats[-1].name sample_rate = 48000 channel_layout = "stereo" channels = 2 ctx.time_base = Fraction(1) / sample_rate ctx.sample_rate = sample_rate ctx.format = sample_fmt ctx.layout = channel_layout ctx.channels = channels ctx.open() resampler = AudioResampler(sample_fmt, channel_layout, sample_rate) container = av.open( fate_suite("audio-reference/chorusnoise_2ch_44kHz_s16.wav")) audio_stream = container.streams.audio[0] path = self.sandboxed("encoder.%s" % codec_name) samples = 0 packet_sizes = [] with open(path, "wb") as f: for frame in iter_frames(container, audio_stream): resampled_frames = resampler.resample(frame) for resampled_frame in resampled_frames: samples += resampled_frame.samples for packet in ctx.encode(resampled_frame): packet_sizes.append(packet.size) f.write(packet) for packet in ctx.encode(None): packet_sizes.append(packet.size) f.write(packet) ctx = Codec(codec_name, "r").create() ctx.sample_rate = sample_rate ctx.format = sample_fmt ctx.layout = channel_layout ctx.channels = channels ctx.open() result_samples = 0 # should have more asserts but not sure what to check # libav and ffmpeg give different results # so can really use checksums for frame in iter_raw_frames(path, packet_sizes, ctx): result_samples += frame.samples self.assertEqual(frame.rate, sample_rate) self.assertEqual(len(frame.layout.channels), channels)
def video_encoding(self, codec_name, options={}, codec_tag=None): try: codec = Codec(codec_name, "w") except UnknownCodecError: raise SkipTest() container = av.open(fate_suite("h264/interlaced_crop.mp4")) video_stream = container.streams.video[0] pix_fmt = options.pop("pix_fmt", "yuv420p") width = options.pop("width", 640) height = options.pop("height", 480) max_frames = options.pop("max_frames", 50) time_base = options.pop("time_base", video_stream.codec_context.time_base) ctx = codec.create() ctx.width = width ctx.height = height ctx.time_base = time_base ctx.framerate = 1 / ctx.time_base ctx.pix_fmt = pix_fmt ctx.options = options # TODO if codec_tag: ctx.codec_tag = codec_tag ctx.open() path = self.sandboxed("encoder.%s" % codec_name) packet_sizes = [] frame_count = 0 with open(path, "wb") as f: for frame in iter_frames(container, video_stream): new_frame = frame.reformat(width, height, pix_fmt) # reset the picture type new_frame.pict_type = PictureType.NONE for packet in ctx.encode(new_frame): packet_sizes.append(packet.size) f.write(packet) frame_count += 1 if frame_count >= max_frames: break for packet in ctx.encode(None): packet_sizes.append(packet.size) f.write(packet) dec_codec_name = codec_name if codec_name == "libx264": dec_codec_name = "h264" ctx = av.Codec(dec_codec_name, "r").create() ctx.open() decoded_frame_count = 0 for frame in iter_raw_frames(path, packet_sizes, ctx): decoded_frame_count += 1 self.assertEqual(frame.width, width) self.assertEqual(frame.height, height) self.assertEqual(frame.format.name, pix_fmt) self.assertEqual(frame_count, decoded_frame_count)
def test_skip_frame_default(self): ctx = Codec('png', 'w').create() self.assertEqual(ctx.skip_frame.name, 'DEFAULT')
def audio_encoding(self, codec_name): try: codec = Codec(codec_name, 'w') except UnknownCodecError: raise SkipTest() ctx = codec.create() if ctx.codec.experimental: raise SkipTest() sample_fmt = ctx.codec.audio_formats[-1].name sample_rate = 48000 channel_layout = "stereo" channels = 2 ctx.time_base = Fraction(1) / sample_rate ctx.sample_rate = sample_rate ctx.format = sample_fmt ctx.layout = channel_layout ctx.channels = channels ctx.open() resampler = AudioResampler(sample_fmt, channel_layout, sample_rate) container = av.open( fate_suite('audio-reference/chorusnoise_2ch_44kHz_s16.wav')) audio_stream = container.streams.audio[0] path = self.sandboxed('encoder.%s' % codec_name) samples = 0 packet_sizes = [] with open(path, 'wb') as f: for frame in iter_frames(container, audio_stream): # We need to let the encoder retime. frame.pts = None """ bad_resampler = AudioResampler(sample_fmt, "mono", sample_rate) bad_frame = bad_resampler.resample(frame) with self.assertRaises(ValueError): next(encoder.encode(bad_frame)) bad_resampler = AudioResampler(sample_fmt, channel_layout, 3000) bad_frame = bad_resampler.resample(frame) with self.assertRaises(ValueError): next(encoder.encode(bad_frame)) bad_resampler = AudioResampler('u8', channel_layout, 3000) bad_frame = bad_resampler.resample(frame) with self.assertRaises(ValueError): next(encoder.encode(bad_frame)) """ resampled_frame = resampler.resample(frame) samples += resampled_frame.samples for packet in ctx.encode(resampled_frame): # bytearray because python can # freaks out if the first byte is NULL f.write(bytearray(packet)) packet_sizes.append(packet.size) for packet in ctx.encode(None): packet_sizes.append(packet.size) f.write(bytearray(packet)) ctx = Codec(codec_name, 'r').create() ctx.time_base = Fraction(1) / sample_rate ctx.sample_rate = sample_rate ctx.format = sample_fmt ctx.layout = channel_layout ctx.channels = channels ctx.open() result_samples = 0 # should have more asserts but not sure what to check # libav and ffmpeg give different results # so can really use checksums for frame in iter_raw_frames(path, packet_sizes, ctx): result_samples += frame.samples self.assertEqual(frame.rate, sample_rate) self.assertEqual(len(frame.layout.channels), channels)
def audio_encoding(self, codec_name): try: codec = Codec(codec_name, 'w') except UnknownCodecError: raise SkipTest() ctx = codec.create() if ctx.codec.experimental: raise SkipTest() sample_fmt = ctx.codec.audio_formats[-1].name sample_rate = 48000 channel_layout = "stereo" channels = 2 ctx.time_base = Fraction(1) / sample_rate ctx.sample_rate = sample_rate ctx.format = sample_fmt ctx.layout = channel_layout ctx.channels = channels ctx.open() resampler = AudioResampler(sample_fmt, channel_layout, sample_rate) container = av.open(fate_suite('audio-reference/chorusnoise_2ch_44kHz_s16.wav')) audio_stream = container.streams.audio[0] path = self.sandboxed('encoder.%s' % codec_name) samples = 0 packet_sizes = [] with open(path, 'wb') as f: for frame in iter_frames(container, audio_stream): # We need to let the encoder retime. frame.pts = None """ bad_resampler = AudioResampler(sample_fmt, "mono", sample_rate) bad_frame = bad_resampler.resample(frame) with self.assertRaises(ValueError): next(encoder.encode(bad_frame)) bad_resampler = AudioResampler(sample_fmt, channel_layout, 3000) bad_frame = bad_resampler.resample(frame) with self.assertRaises(ValueError): next(encoder.encode(bad_frame)) bad_resampler = AudioResampler('u8', channel_layout, 3000) bad_frame = bad_resampler.resample(frame) with self.assertRaises(ValueError): next(encoder.encode(bad_frame)) """ resampled_frame = resampler.resample(frame) samples += resampled_frame.samples for packet in ctx.encode(resampled_frame): # bytearray because python can # freaks out if the first byte is NULL f.write(bytearray(packet)) packet_sizes.append(packet.size) for packet in ctx.encode(None): packet_sizes.append(packet.size) f.write(bytearray(packet)) ctx = Codec(codec_name, 'r').create() ctx.time_base = Fraction(1) / sample_rate ctx.sample_rate = sample_rate ctx.format = sample_fmt ctx.layout = channel_layout ctx.channels = channels ctx.open() result_samples = 0 # should have more asserts but not sure what to check # libav and ffmpeg give different results # so can really use checksums for frame in iter_raw_frames(path, packet_sizes, ctx): result_samples += frame.samples self.assertEqual(frame.rate, sample_rate) self.assertEqual(len(frame.layout.channels), channels)
def test_codec_bogus(self): with self.assertRaises(UnknownCodecError): Codec("bogus123") with self.assertRaises(UnknownCodecError): Codec("bogus123", "w")
import unittest from av import AudioFormat, Codec, VideoFormat, codecs_available from av.codec.codec import UnknownCodecError from .common import TestCase # some older ffmpeg versions have no native opus encoder try: opus_c = Codec("opus", "w") opus_encoder_missing = False except UnknownCodecError: opus_encoder_missing = True class TestCodecs(TestCase): def test_codec_bogus(self): with self.assertRaises(UnknownCodecError): Codec("bogus123") with self.assertRaises(UnknownCodecError): Codec("bogus123", "w") def test_codec_mpeg4_decoder(self): c = Codec("mpeg4") self.assertEqual(c.name, "mpeg4") self.assertEqual(c.long_name, "MPEG-4 part 2") self.assertEqual(c.type, "video") self.assertIn(c.id, (12, 13)) self.assertTrue(c.is_decoder)
def test_skip_frame_default(self): ctx = Codec("png", "w").create() self.assertEqual(ctx.skip_frame.name, "DEFAULT")
def video_encoding(self, codec_name, options={}): try: codec = Codec(codec_name, 'w') except UnknownCodecError: raise SkipTest() container = av.open(fate_suite('h264/interlaced_crop.mp4')) video_stream = container.streams.video[0] pix_fmt = options.pop('pix_fmt', 'yuv420p') width = options.pop('width', 640) height = options.pop('height', 480) max_frames = options.pop('max_frames', 50) time_base = options.pop('time_base', video_stream.codec_context.time_base) ctx = codec.create() ctx.width = width ctx.height = height ctx.time_base = time_base ctx.framerate = 1 / ctx.time_base ctx.pix_fmt = pix_fmt ctx.options = options # TODO ctx.open() path = self.sandboxed('encoder.%s' % codec_name) packet_sizes = [] frame_count = 0 with open(path, 'wb') as f: for frame in iter_frames(container, video_stream): """ bad_frame = frame.reformat(width, 100, pix_fmt) with self.assertRaises(ValueError): ctx.encode(bad_frame) bad_frame = frame.reformat(100, height, pix_fmt) with self.assertRaises(ValueError): ctx.encode(bad_frame) bad_frame = frame.reformat(width, height, "rgb24") with self.assertRaises(ValueError): ctx.encode(bad_frame) """ if frame: frame_count += 1 new_frame = frame.reformat(width, height, pix_fmt) if frame else None for packet in ctx.encode(new_frame): packet_sizes.append(packet.size) f.write(packet) if frame_count >= max_frames: break for packet in ctx.encode(None): packet_sizes.append(packet.size) f.write(packet) dec_codec_name = codec_name if codec_name == 'libx264': dec_codec_name = 'h264' ctx = av.Codec(dec_codec_name, 'r').create() ctx.open() decoded_frame_count = 0 for frame in iter_raw_frames(path, packet_sizes, ctx): decoded_frame_count += 1 self.assertEqual(frame.width, width) self.assertEqual(frame.height, height) self.assertEqual(frame.format.name, pix_fmt) self.assertEqual(frame_count, decoded_frame_count)