1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci* Copyright (c) 2013 Nicolas George 3cabdff1aSopenharmony_ci* 4cabdff1aSopenharmony_ci* This file is part of FFmpeg. 5cabdff1aSopenharmony_ci* 6cabdff1aSopenharmony_ci* FFmpeg is free software; you can redistribute it and/or 7cabdff1aSopenharmony_ci* modify it under the terms of the GNU Lesser General Public License 8cabdff1aSopenharmony_ci* as published by the Free Software Foundation; either 9cabdff1aSopenharmony_ci* version 2.1 of the License, or (at your option) any later version. 10cabdff1aSopenharmony_ci* 11cabdff1aSopenharmony_ci* FFmpeg is distributed in the hope that it will be useful, 12cabdff1aSopenharmony_ci* but WITHOUT ANY WARRANTY; without even the implied warranty of 13cabdff1aSopenharmony_ci* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14cabdff1aSopenharmony_ci* GNU Lesser General Public License for more details. 15cabdff1aSopenharmony_ci* 16cabdff1aSopenharmony_ci* You should have received a copy of the GNU Lesser General Public License 17cabdff1aSopenharmony_ci* along with FFmpeg; if not, write to the Free Software Foundation, Inc., 18cabdff1aSopenharmony_ci* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19cabdff1aSopenharmony_ci*/ 20cabdff1aSopenharmony_ci 21cabdff1aSopenharmony_ci#include "libavutil/adler32.h" 22cabdff1aSopenharmony_ci#include "libavutil/avassert.h" 23cabdff1aSopenharmony_ci#include "libavutil/bprint.h" 24cabdff1aSopenharmony_ci#include "libavutil/imgutils.h" 25cabdff1aSopenharmony_ci#include "libavutil/pixdesc.h" 26cabdff1aSopenharmony_ci#include "libavformat/mux.h" 27cabdff1aSopenharmony_ci#include "avformat.h" 28cabdff1aSopenharmony_ci#include "internal.h" 29cabdff1aSopenharmony_ci 30cabdff1aSopenharmony_ci/* Identical to Adler32 when the type is uint8_t. */ 31cabdff1aSopenharmony_ci#define DEFINE_CKSUM_LINE(name, type, conv) \ 32cabdff1aSopenharmony_cistatic void cksum_line_ ## name(unsigned *cksum, void *data, unsigned size) \ 33cabdff1aSopenharmony_ci{ \ 34cabdff1aSopenharmony_ci type *p = data; \ 35cabdff1aSopenharmony_ci unsigned a = *cksum & 0xFFFF, b = *cksum >> 16; \ 36cabdff1aSopenharmony_ci for (; size > 0; size--, p++) { \ 37cabdff1aSopenharmony_ci a = (a + (unsigned)(conv)) % 65521; \ 38cabdff1aSopenharmony_ci b = (b + a) % 65521; \ 39cabdff1aSopenharmony_ci } \ 40cabdff1aSopenharmony_ci *cksum = a | (b << 16); \ 41cabdff1aSopenharmony_ci} 42cabdff1aSopenharmony_ci 43cabdff1aSopenharmony_ciDEFINE_CKSUM_LINE(u8, uint8_t, *p) 44cabdff1aSopenharmony_ciDEFINE_CKSUM_LINE(s16, int16_t, *p + 0x8000) 45cabdff1aSopenharmony_ciDEFINE_CKSUM_LINE(s32, int32_t, *p + 0x80000000) 46cabdff1aSopenharmony_ciDEFINE_CKSUM_LINE(flt, float, *p * 0x80000000 + 0x80000000) 47cabdff1aSopenharmony_ciDEFINE_CKSUM_LINE(dbl, double, *p * 0x80000000 + 0x80000000) 48cabdff1aSopenharmony_ci 49cabdff1aSopenharmony_cistatic void video_frame_cksum(AVBPrint *bp, AVFrame *frame) 50cabdff1aSopenharmony_ci{ 51cabdff1aSopenharmony_ci const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); 52cabdff1aSopenharmony_ci int i, y; 53cabdff1aSopenharmony_ci uint8_t *data; 54cabdff1aSopenharmony_ci int linesize[5] = { 0 }; 55cabdff1aSopenharmony_ci 56cabdff1aSopenharmony_ci av_bprintf(bp, ", %d x %d", frame->width, frame->height); 57cabdff1aSopenharmony_ci if (!desc) { 58cabdff1aSopenharmony_ci av_bprintf(bp, ", unknown"); 59cabdff1aSopenharmony_ci return; 60cabdff1aSopenharmony_ci } 61cabdff1aSopenharmony_ci if (av_image_fill_linesizes(linesize, frame->format, frame->width) < 0) 62cabdff1aSopenharmony_ci return; 63cabdff1aSopenharmony_ci av_bprintf(bp, ", %s", desc->name); 64cabdff1aSopenharmony_ci for (i = 0; linesize[i]; i++) { 65cabdff1aSopenharmony_ci unsigned cksum = 0; 66cabdff1aSopenharmony_ci int h = frame->height; 67cabdff1aSopenharmony_ci if ((i == 1 || i == 2) && desc->nb_components >= 3) 68cabdff1aSopenharmony_ci h = AV_CEIL_RSHIFT(h, desc->log2_chroma_h); 69cabdff1aSopenharmony_ci data = frame->data[i]; 70cabdff1aSopenharmony_ci for (y = 0; y < h; y++) { 71cabdff1aSopenharmony_ci cksum = av_adler32_update(cksum, data, linesize[i]); 72cabdff1aSopenharmony_ci data += frame->linesize[i]; 73cabdff1aSopenharmony_ci } 74cabdff1aSopenharmony_ci av_bprintf(bp, ", 0x%08x", cksum); 75cabdff1aSopenharmony_ci } 76cabdff1aSopenharmony_ci} 77cabdff1aSopenharmony_ci 78cabdff1aSopenharmony_cistatic void audio_frame_cksum(AVBPrint *bp, AVFrame *frame) 79cabdff1aSopenharmony_ci{ 80cabdff1aSopenharmony_ci int nb_planes, nb_samples, p; 81cabdff1aSopenharmony_ci const char *name; 82cabdff1aSopenharmony_ci 83cabdff1aSopenharmony_ci nb_planes = frame->ch_layout.nb_channels; 84cabdff1aSopenharmony_ci nb_samples = frame->nb_samples; 85cabdff1aSopenharmony_ci if (!av_sample_fmt_is_planar(frame->format)) { 86cabdff1aSopenharmony_ci nb_samples *= nb_planes; 87cabdff1aSopenharmony_ci nb_planes = 1; 88cabdff1aSopenharmony_ci } 89cabdff1aSopenharmony_ci name = av_get_sample_fmt_name(frame->format); 90cabdff1aSopenharmony_ci av_bprintf(bp, ", %d samples", frame->nb_samples); 91cabdff1aSopenharmony_ci av_bprintf(bp, ", %s", name ? name : "unknown"); 92cabdff1aSopenharmony_ci for (p = 0; p < nb_planes; p++) { 93cabdff1aSopenharmony_ci uint32_t cksum = 0; 94cabdff1aSopenharmony_ci void *d = frame->extended_data[p]; 95cabdff1aSopenharmony_ci switch (frame->format) { 96cabdff1aSopenharmony_ci case AV_SAMPLE_FMT_U8: 97cabdff1aSopenharmony_ci case AV_SAMPLE_FMT_U8P: 98cabdff1aSopenharmony_ci cksum_line_u8(&cksum, d, nb_samples); 99cabdff1aSopenharmony_ci break; 100cabdff1aSopenharmony_ci case AV_SAMPLE_FMT_S16: 101cabdff1aSopenharmony_ci case AV_SAMPLE_FMT_S16P: 102cabdff1aSopenharmony_ci cksum_line_s16(&cksum, d, nb_samples); 103cabdff1aSopenharmony_ci break; 104cabdff1aSopenharmony_ci case AV_SAMPLE_FMT_S32: 105cabdff1aSopenharmony_ci case AV_SAMPLE_FMT_S32P: 106cabdff1aSopenharmony_ci cksum_line_s32(&cksum, d, nb_samples); 107cabdff1aSopenharmony_ci break; 108cabdff1aSopenharmony_ci case AV_SAMPLE_FMT_FLT: 109cabdff1aSopenharmony_ci case AV_SAMPLE_FMT_FLTP: 110cabdff1aSopenharmony_ci cksum_line_flt(&cksum, d, nb_samples); 111cabdff1aSopenharmony_ci break; 112cabdff1aSopenharmony_ci case AV_SAMPLE_FMT_DBL: 113cabdff1aSopenharmony_ci case AV_SAMPLE_FMT_DBLP: 114cabdff1aSopenharmony_ci cksum_line_dbl(&cksum, d, nb_samples); 115cabdff1aSopenharmony_ci break; 116cabdff1aSopenharmony_ci default: 117cabdff1aSopenharmony_ci av_assert0(!"reached"); 118cabdff1aSopenharmony_ci } 119cabdff1aSopenharmony_ci av_bprintf(bp, ", 0x%08"PRIx32, cksum); 120cabdff1aSopenharmony_ci } 121cabdff1aSopenharmony_ci} 122cabdff1aSopenharmony_ci 123cabdff1aSopenharmony_cistatic int write_header(struct AVFormatContext *s) 124cabdff1aSopenharmony_ci{ 125cabdff1aSopenharmony_ci return ff_framehash_write_header(s); 126cabdff1aSopenharmony_ci} 127cabdff1aSopenharmony_ci 128cabdff1aSopenharmony_cistatic int write_frame(struct AVFormatContext *s, int stream_index, 129cabdff1aSopenharmony_ci AVFrame **frame, unsigned flags) 130cabdff1aSopenharmony_ci{ 131cabdff1aSopenharmony_ci AVBPrint bp; 132cabdff1aSopenharmony_ci int ret = 0; 133cabdff1aSopenharmony_ci enum AVMediaType type; 134cabdff1aSopenharmony_ci const char *type_name; 135cabdff1aSopenharmony_ci 136cabdff1aSopenharmony_ci if ((flags & AV_WRITE_UNCODED_FRAME_QUERY)) 137cabdff1aSopenharmony_ci return 0; 138cabdff1aSopenharmony_ci 139cabdff1aSopenharmony_ci av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED); 140cabdff1aSopenharmony_ci av_bprintf(&bp, "%d, %10"PRId64"", 141cabdff1aSopenharmony_ci stream_index, (*frame)->pts); 142cabdff1aSopenharmony_ci type = s->streams[stream_index]->codecpar->codec_type; 143cabdff1aSopenharmony_ci type_name = av_get_media_type_string(type); 144cabdff1aSopenharmony_ci av_bprintf(&bp, ", %s", type_name ? type_name : "unknown"); 145cabdff1aSopenharmony_ci switch (type) { 146cabdff1aSopenharmony_ci case AVMEDIA_TYPE_VIDEO: 147cabdff1aSopenharmony_ci video_frame_cksum(&bp, *frame); 148cabdff1aSopenharmony_ci break; 149cabdff1aSopenharmony_ci case AVMEDIA_TYPE_AUDIO: 150cabdff1aSopenharmony_ci audio_frame_cksum(&bp, *frame); 151cabdff1aSopenharmony_ci break; 152cabdff1aSopenharmony_ci } 153cabdff1aSopenharmony_ci 154cabdff1aSopenharmony_ci av_bprint_chars(&bp, '\n', 1); 155cabdff1aSopenharmony_ci if (av_bprint_is_complete(&bp)) 156cabdff1aSopenharmony_ci avio_write(s->pb, bp.str, bp.len); 157cabdff1aSopenharmony_ci else 158cabdff1aSopenharmony_ci ret = AVERROR(ENOMEM); 159cabdff1aSopenharmony_ci av_bprint_finalize(&bp, NULL); 160cabdff1aSopenharmony_ci return ret; 161cabdff1aSopenharmony_ci} 162cabdff1aSopenharmony_ci 163cabdff1aSopenharmony_cistatic int write_packet(struct AVFormatContext *s, AVPacket *pkt) 164cabdff1aSopenharmony_ci{ 165cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 166cabdff1aSopenharmony_ci} 167cabdff1aSopenharmony_ci 168cabdff1aSopenharmony_ciconst AVOutputFormat ff_uncodedframecrc_muxer = { 169cabdff1aSopenharmony_ci .name = "uncodedframecrc", 170cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("uncoded framecrc testing"), 171cabdff1aSopenharmony_ci .audio_codec = AV_CODEC_ID_PCM_S16LE, 172cabdff1aSopenharmony_ci .video_codec = AV_CODEC_ID_RAWVIDEO, 173cabdff1aSopenharmony_ci .write_header = write_header, 174cabdff1aSopenharmony_ci .write_packet = write_packet, 175cabdff1aSopenharmony_ci .write_uncoded_frame = write_frame, 176cabdff1aSopenharmony_ci .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | 177cabdff1aSopenharmony_ci AVFMT_TS_NEGATIVE, 178cabdff1aSopenharmony_ci}; 179