static size_t mmc_read_file(const char *file_name) { loff_t act_read = 0; int rc; struct mmc *mmc; const u8 mmc_dev_num = CONFIG_SYS_MMC_ENV_DEV; mmc = find_mmc_device(mmc_dev_num); if (!mmc) { printf("No SD/MMC/eMMC card found\n"); return 0; } if (mmc_init(mmc)) { printf("%s(%d) init failed\n", IS_SD(mmc) ? "SD" : "MMC", mmc_dev_num); return 0; } /* Load from data partition (0) */ if (fs_set_blk_dev("mmc", "0", FS_TYPE_ANY)) { printf("Error: MMC 0 not found\n"); return 0; } /* Perfrom file read */ rc = fs_read(file_name, get_load_addr(), 0, 0, &act_read); if (rc) return 0; return act_read; }
void print_mmc_devices(char separator) { struct udevice *dev; char *mmc_type; bool first = true; for (uclass_first_device(UCLASS_MMC, &dev); dev; uclass_next_device(&dev), first = false) { struct mmc *m = mmc_get_mmc_dev(dev); if (!first) { printf("%c", separator); if (separator != '\n') puts(" "); } if (m->has_init) mmc_type = IS_SD(m) ? "SD" : "eMMC"; else mmc_type = NULL; printf("%s: %d", m->cfg->name, mmc_get_blk_desc(m)->devnum); if (mmc_type) printf(" (%s)", mmc_type); } printf("\n"); }
char *get_dfu_alt_boot(char *interface, char *devstr) { char *info = "Not supported!"; struct mmc *mmc; char *alt_boot; int dev_num; if (board_is_odroidxu4()) return info; dev_num = simple_strtoul(devstr, NULL, 10); mmc = find_mmc_device(dev_num); if (!mmc) return NULL; if (mmc_init(mmc)) return NULL; if (IS_SD(mmc)) alt_boot = CONFIG_DFU_ALT_BOOT_SD; else alt_boot = CONFIG_DFU_ALT_BOOT_EMMC; return alt_boot; }
static void close_card( decklink_opts_t *decklink_opts ) { decklink_ctx_t *decklink_ctx = &decklink_opts->decklink_ctx; if( decklink_ctx->p_config ) decklink_ctx->p_config->Release(); if( decklink_ctx->p_input ) { decklink_ctx->p_input->StopStreams(); decklink_ctx->p_input->Release(); } if( decklink_ctx->p_card ) decklink_ctx->p_card->Release(); if( decklink_ctx->p_delegate ) decklink_ctx->p_delegate->Release(); if( decklink_ctx->codec ) { avcodec_close( decklink_ctx->codec ); av_free( decklink_ctx->codec ); } if( IS_SD( decklink_opts->video_format ) ) vbi_raw_decoder_destroy( &decklink_ctx->non_display_parser.vbi_decoder ); if( decklink_ctx->avr ) avresample_free( &decklink_ctx->avr ); }
//======================================================================= int sdcard_post_test(int flags) { struct mmc *mmc; int dev_num; dev_num = simple_strtoul("mmcinfo", NULL, 0); mmc = find_mmc_device(dev_num); if (mmc) { mmc_init(mmc); if((mmc->tran_speed == 0) || (mmc->read_bl_len == 0) || (mmc->capacity == 0)) { post_log("<%d>%s:%d: SDCARD: %s\n", SYSTEST_INFO_L2, __FUNCTION__, __LINE__, "no MMC device available."); return -1; } post_log("<%d>SDCARD: Device: %s\n", SYSTEST_INFO_L2, mmc->name); post_log("<%d>SDCARD: Manufacturer ID: %x\n", SYSTEST_INFO_L2, mmc->cid[0] >> 24); post_log("<%d>SDCARD: OEM: %x\n", SYSTEST_INFO_L2, (mmc->cid[0] >> 8) & 0xffff); //post_log("<%d>SDCARD: Name: %c%c%c%c%c\n",SYSTEST_INFO_L2, mmc->cid[0] & 0xff, // (mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff, // (mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff); post_log("<%d>SDCARD: Tran Speed: %d\n", SYSTEST_INFO_L2, mmc->tran_speed); post_log("<%d>SDCARD: Rd Block Len: %d\n", SYSTEST_INFO_L2, mmc->read_bl_len); post_log("<%d>SDCARD: %s version %d.%d\n", SYSTEST_INFO_L2, IS_SD(mmc) ? "SD" : "MMC", (mmc->version >> 4) & 0xf, mmc->version & 0xf); post_log("<%d>SDCARD: High Capacity: %s\n", SYSTEST_INFO_L2, mmc->high_capacity ? "Yes" : "No"); post_log("<%d>SDCARD: Capacity: %lld\n", SYSTEST_INFO_L2, mmc->capacity); post_log("<%d>SDCARD: Bus Width: %d-bit\n", SYSTEST_INFO_L2, mmc->bus_width); } else {
static unsigned long mmc_erase_t(struct mmc *mmc, unsigned long start, unsigned blkcnt) { struct mmc_cmd cmd; unsigned long end; int err, start_cmd, end_cmd; if (mmc->high_capacity) end = start + blkcnt - 1; else { end = (start + blkcnt - 1) * mmc->write_bl_len; start *= mmc->write_bl_len; } if (IS_SD(mmc)) { start_cmd = SD_CMD_ERASE_WR_BLK_START; end_cmd = SD_CMD_ERASE_WR_BLK_END; } else { start_cmd = MMC_CMD_ERASE_GROUP_START; end_cmd = MMC_CMD_ERASE_GROUP_END; } cmd.cmdidx = start_cmd; cmd.cmdarg = start; cmd.resp_type = MMC_RSP_R1; cmd.flags = 0; err = mmc_send_cmd(mmc, &cmd, NULL); if (err) goto err_out; cmd.cmdidx = end_cmd; cmd.cmdarg = end; err = mmc_send_cmd(mmc, &cmd, NULL); if (err) goto err_out; cmd.cmdidx = MMC_CMD_ERASE; cmd.cmdarg = SECURE_ERASE; cmd.resp_type = MMC_RSP_R1b; err = mmc_send_cmd(mmc, &cmd, NULL); if (err) goto err_out; return 0; err_out: mmcdbg("mmc erase failed\n"); return err; }
static inline void mv_sdhci_writeb(struct sdhci_host *host, u8 val, int reg) { struct mmc *mmc = host->mmc; u32 ata = (unsigned long)host->ioaddr + SD_CE_ATA_2; if (!IS_SD(mmc) && reg == SDHCI_HOST_CONTROL) { if (mmc->bus_width == 8) writew(readw(ata) | (MMC_CARD | MMC_WIDTH), ata); else writew(readw(ata) & ~(MMC_CARD | MMC_WIDTH), ata); } writeb(val, host->ioaddr + reg); }
char *get_dfu_alt_boot(char *interface, char *devstr) { struct mmc *mmc; char *alt_boot; int dev_num; dev_num = simple_strtoul(devstr, NULL, 10); mmc = find_mmc_device(dev_num); if (!mmc) return NULL; if (mmc_init(mmc)) return NULL; alt_boot = IS_SD(mmc) ? CONFIG_DFU_ALT_BOOT_SD : CONFIG_DFU_ALT_BOOT_EMMC; return alt_boot; }
/* Platform specific function for post set_ios configuration */ static void xenon_sdhci_set_ios_post(struct sdhci_host *host) { struct xenon_sdhci_priv *priv = host->mmc->priv; uint speed = host->mmc->tran_speed; int pwr_18v = 0; if ((sdhci_readb(host, SDHCI_POWER_CONTROL) & ~SDHCI_POWER_ON) == SDHCI_POWER_180) pwr_18v = 1; /* Set timing variable according to the configured speed */ if (IS_SD(host->mmc)) { /* SD/SDIO */ if (pwr_18v) { if (host->mmc->ddr_mode) priv->timing = MMC_TIMING_UHS_DDR50; else if (speed <= 25000000) priv->timing = MMC_TIMING_UHS_SDR25; else priv->timing = MMC_TIMING_UHS_SDR50; } else { if (speed <= 25000000) priv->timing = MMC_TIMING_LEGACY; else priv->timing = MMC_TIMING_SD_HS; } } else { /* eMMC */ if (host->mmc->ddr_mode) priv->timing = MMC_TIMING_MMC_DDR52; else if (speed <= 26000000) priv->timing = MMC_TIMING_LEGACY; else priv->timing = MMC_TIMING_MMC_HS; } /* Re-init the PHY */ xenon_mmc_phy_set(host); }
static void ftsdc010_clkset(struct mmc *mmc, uint32_t rate) { struct ftsdc010_chip *chip = mmc->priv; struct ftsdc010_mmc __iomem *regs = chip->regs; uint32_t div; for (div = 0; div < 0x7f; ++div) { if (rate >= chip->sclk / (2 * (div + 1))) break; } chip->rate = chip->sclk / (2 * (div + 1)); writel(FTSDC010_CCR_CLK_DIV(div), ®s->ccr); if (IS_SD(mmc)) { setbits_le32(®s->ccr, FTSDC010_CCR_CLK_SD); if (chip->rate > 25000000) setbits_le32(®s->ccr, FTSDC010_CCR_CLK_HISPD); else clrbits_le32(®s->ccr, FTSDC010_CCR_CLK_HISPD); } }
static int mmc_burn_image(size_t image_size) { struct mmc *mmc; lbaint_t start_lba; lbaint_t blk_count; ulong blk_written; int err; const u8 mmc_dev_num = CONFIG_SYS_MMC_ENV_DEV; #ifdef CONFIG_BLK struct blk_desc *blk_desc; #endif mmc = find_mmc_device(mmc_dev_num); if (!mmc) { printf("No SD/MMC/eMMC card found\n"); return -ENOMEDIUM; } err = mmc_init(mmc); if (err) { printf("%s(%d) init failed\n", IS_SD(mmc) ? "SD" : "MMC", mmc_dev_num); return err; } #ifdef CONFIG_SYS_MMC_ENV_PART if (mmc->part_num != CONFIG_SYS_MMC_ENV_PART) { err = mmc_switch_part(mmc_dev_num, CONFIG_SYS_MMC_ENV_PART); if (err) { printf("MMC partition switch failed\n"); return err; } } #endif /* SD reserves LBA-0 for MBR and boots from LBA-1, * MMC/eMMC boots from LBA-0 */ start_lba = IS_SD(mmc) ? 1 : 0; #ifdef CONFIG_BLK blk_count = image_size / mmc->write_bl_len; if (image_size % mmc->write_bl_len) blk_count += 1; blk_desc = mmc_get_blk_desc(mmc); if (!blk_desc) { printf("Error - failed to obtain block descriptor\n"); return -ENODEV; } blk_written = blk_dwrite(blk_desc, start_lba, blk_count, (void *)get_load_addr()); #else blk_count = image_size / mmc->block_dev.blksz; if (image_size % mmc->block_dev.blksz) blk_count += 1; blk_written = mmc->block_dev.block_write(mmc_dev_num, start_lba, blk_count, (void *)get_load_addr()); #endif /* CONFIG_BLK */ if (blk_written != blk_count) { printf("Error - written %#lx blocks\n", blk_written); return -ENOSPC; } printf("Done!\n"); #ifdef CONFIG_SYS_MMC_ENV_PART if (mmc->part_num != CONFIG_SYS_MMC_ENV_PART) mmc_switch_part(mmc_dev_num, mmc->part_num); #endif return 0; }
int init_raw_area_table (block_dev_desc_t * dev_desc) { #if defined(FORCE_MMC1) struct mmc *host = find_mmc_device(1); #else struct mmc *host = find_mmc_device(dev_desc->dev); #endif /* when last block does not have raw_area definition. */ if (raw_area_control.magic_number != MAGIC_NUMBER_MOVI) { int i = 0; member_t *image; u32 capacity; if (host->high_capacity) { capacity = host->capacity; #ifdef CONFIG_S3C6410 if(IS_SD(host)) capacity -= 1024; #endif } else { capacity = host->capacity; } dev_desc->block_read(dev_desc->dev, capacity - (eFUSE_SIZE/MOVI_BLKSIZE) - 1, 1, &raw_area_control); if (raw_area_control.magic_number == MAGIC_NUMBER_MOVI) { return 0; } dbg("Warning: cannot find the raw area table(%p) %08x\n", &raw_area_control, raw_area_control.magic_number); /* add magic number */ raw_area_control.magic_number = MAGIC_NUMBER_MOVI; /* init raw_area will be 16MB */ raw_area_control.start_blk = 16*1024*1024/MOVI_BLKSIZE; raw_area_control.total_blk = capacity; raw_area_control.next_raw_area = 0; strcpy(raw_area_control.description, "initial raw table"); image = raw_area_control.image; #if defined(CONFIG_EVT1) #if defined(CONFIG_FUSED) /* image 0 should be fwbl1 */ image[0].start_blk = (eFUSE_SIZE/MOVI_BLKSIZE); image[0].used_blk = MOVI_FWBL1_BLKCNT; image[0].size = FWBL1_SIZE; image[0].attribute = 0x0; strcpy(image[0].description, "fwbl1"); dbg("fwbl1: %d\n", image[0].start_blk); #endif #endif /* image 1 should be bl2 */ #if defined(CONFIG_EVT1) #if defined(CONFIG_FUSED) image[1].start_blk = image[0].start_blk + MOVI_FWBL1_BLKCNT; #else image[1].start_blk = (eFUSE_SIZE/MOVI_BLKSIZE); #endif #else image[1].start_blk = capacity - (eFUSE_SIZE/MOVI_BLKSIZE) - MOVI_BL1_BLKCNT; #endif image[1].used_blk = MOVI_BL1_BLKCNT; image[1].size = SS_SIZE; image[1].attribute = 0x1; strcpy(image[1].description, "u-boot parted"); dbg("bl1: %d\n", image[1].start_blk); /* image 2 should be environment */ #if defined(CONFIG_EVT1) image[2].start_blk = image[1].start_blk + MOVI_BL1_BLKCNT; #else image[2].start_blk = image[1].start_blk - MOVI_ENV_BLKCNT; #endif image[2].used_blk = MOVI_ENV_BLKCNT; image[2].size = CFG_ENV_SIZE; image[2].attribute = 0x10; strcpy(image[2].description, "environment"); dbg("env: %d\n", image[2].start_blk); /* image 3 should be bl2 */ #if defined(CONFIG_EVT1) image[3].start_blk = image[2].start_blk + MOVI_ENV_BLKCNT; #else image[3].start_blk = image[2].start_blk - MOVI_BL2_BLKCNT; #endif image[3].used_blk = MOVI_BL2_BLKCNT; image[3].size = PART_SIZE_BL; image[3].attribute = 0x2; strcpy(image[3].description, "u-boot"); dbg("bl2: %d\n", image[3].start_blk); /* image 4 should be kernel */ #if defined(CONFIG_EVT1) image[4].start_blk = image[3].start_blk + MOVI_BL2_BLKCNT; #else image[4].start_blk = image[3].start_blk - MOVI_ZIMAGE_BLKCNT; #endif image[4].used_blk = MOVI_ZIMAGE_BLKCNT; image[4].size = PART_SIZE_KERNEL; image[4].attribute = 0x4; strcpy(image[4].description, "kernel"); dbg("knl: %d\n", image[4].start_blk); /* image 5 should be RFS */ #if defined(CONFIG_EVT1) image[5].start_blk = image[4].start_blk + MOVI_ZIMAGE_BLKCNT; #else image[5].start_blk = image[4].start_blk - MOVI_ROOTFS_BLKCNT; #endif image[5].used_blk = MOVI_ROOTFS_BLKCNT; image[5].size = PART_SIZE_ROOTFS; image[5].attribute = 0x8; strcpy(image[5].description, "rfs"); dbg("rfs: %d\n", image[5].start_blk); for (i=6; i<15; i++) { raw_area_control.image[i].start_blk = 0; raw_area_control.image[i].used_blk = 0; } } }
static int open_card( decklink_opts_t *decklink_opts ) { decklink_ctx_t *decklink_ctx = &decklink_opts->decklink_ctx; int found_mode; int ret = 0; int i; int cpu_flags; const int sample_rate = 48000; const char *model_name; BMDDisplayMode wanted_mode_id; IDeckLinkDisplayModeIterator *p_display_iterator = NULL; IDeckLinkIterator *decklink_iterator = NULL; HRESULT result; avcodec_register_all(); decklink_ctx->dec = avcodec_find_decoder( AV_CODEC_ID_V210 ); if( !decklink_ctx->dec ) { fprintf( stderr, "[decklink] Could not find v210 decoder\n" ); goto finish; } decklink_ctx->codec = avcodec_alloc_context3( decklink_ctx->dec ); if( !decklink_ctx->codec ) { fprintf( stderr, "[decklink] Could not allocate AVCodecContext\n" ); goto finish; } decklink_ctx->codec->get_buffer = obe_get_buffer; decklink_ctx->codec->release_buffer = obe_release_buffer; decklink_ctx->codec->reget_buffer = obe_reget_buffer; decklink_ctx->codec->flags |= CODEC_FLAG_EMU_EDGE; /* TODO: setup custom strides */ if( avcodec_open2( decklink_ctx->codec, decklink_ctx->dec, NULL ) < 0 ) { fprintf( stderr, "[decklink] Could not open libavcodec\n" ); goto finish; } decklink_iterator = CreateDeckLinkIteratorInstance(); if( !decklink_iterator ) { fprintf( stderr, "[decklink] DeckLink drivers not found\n" ); ret = -1; goto finish; } if( decklink_opts->card_idx < 0 ) { fprintf( stderr, "[decklink] Invalid card index %d \n", decklink_opts->card_idx ); ret = -1; goto finish; } for( i = 0; i <= decklink_opts->card_idx; ++i ) { if( decklink_ctx->p_card ) decklink_ctx->p_card->Release(); result = decklink_iterator->Next( &decklink_ctx->p_card ); if( result != S_OK ) break; } if( result != S_OK ) { fprintf( stderr, "[decklink] DeckLink PCI card %d not found\n", decklink_opts->card_idx ); ret = -1; goto finish; } result = decklink_ctx->p_card->GetModelName( &model_name ); if( result != S_OK ) { fprintf( stderr, "[decklink] Could not get model name\n" ); ret = -1; goto finish; } syslog( LOG_INFO, "Opened DeckLink PCI card %d (%s)", decklink_opts->card_idx, model_name ); if( decklink_ctx->p_card->QueryInterface( IID_IDeckLinkInput, (void**)&decklink_ctx->p_input) != S_OK ) { fprintf( stderr, "[decklink] Card has no inputs\n" ); ret = -1; goto finish; } /* Set up the video and audio sources. */ if( decklink_ctx->p_card->QueryInterface( IID_IDeckLinkConfiguration, (void**)&decklink_ctx->p_config) != S_OK ) { fprintf( stderr, "[decklink] Failed to get configuration interface\n" ); ret = -1; goto finish; } /* Setup video connection */ for( i = 0; video_conn_tab[i].obe_name != -1; i++ ) { if( video_conn_tab[i].obe_name == decklink_opts->video_conn ) break; } if( video_conn_tab[i].obe_name == -1 ) { fprintf( stderr, "[decklink] Unsupported video input connection\n" ); ret = -1; goto finish; } result = decklink_ctx->p_config->SetInt( bmdDeckLinkConfigVideoInputConnection, video_conn_tab[i].bmd_name ); if( result != S_OK ) { fprintf( stderr, "[decklink] Failed to set video input connection\n" ); ret = -1; goto finish; } /* Setup audio connection */ for( i = 0; audio_conn_tab[i].obe_name != -1; i++ ) { if( audio_conn_tab[i].obe_name == decklink_opts->audio_conn ) break; } if( audio_conn_tab[i].obe_name == -1 ) { fprintf( stderr, "[decklink] Unsupported audio input connection\n" ); ret = -1; goto finish; } result = decklink_ctx->p_config->SetInt( bmdDeckLinkConfigAudioInputConnection, audio_conn_tab[i].bmd_name ); if( result != S_OK ) { fprintf( stderr, "[decklink] Failed to set audio input connection\n" ); ret = -1; goto finish; } /* Get the list of display modes. */ result = decklink_ctx->p_input->GetDisplayModeIterator( &p_display_iterator ); if( result != S_OK ) { fprintf( stderr, "[decklink] Failed to enumerate display modes\n" ); ret = -1; goto finish; } for( i = 0; video_format_tab[i].obe_name != -1; i++ ) { if( video_format_tab[i].obe_name == decklink_opts->video_format ) break; } if( video_format_tab[i].obe_name == -1 ) { fprintf( stderr, "[decklink] Unsupported video format\n" ); ret = -1; goto finish; } wanted_mode_id = video_format_tab[i].bmd_name; found_mode = false; decklink_opts->timebase_num = video_format_tab[i].timebase_num; decklink_opts->timebase_den = video_format_tab[i].timebase_den; for (;;) { IDeckLinkDisplayMode *p_display_mode; result = p_display_iterator->Next( &p_display_mode ); if( result != S_OK || !p_display_mode ) break; BMDDisplayMode mode_id = p_display_mode->GetDisplayMode(); BMDTimeValue frame_duration, time_scale; result = p_display_mode->GetFrameRate( &frame_duration, &time_scale ); if( result != S_OK ) { fprintf( stderr, "[decklink] Failed to get frame rate\n" ); ret = -1; p_display_mode->Release(); goto finish; } if( wanted_mode_id == mode_id ) { found_mode = true; decklink_opts->width = p_display_mode->GetWidth(); decklink_opts->coded_height = p_display_mode->GetHeight(); switch( p_display_mode->GetFieldDominance() ) { case bmdProgressiveFrame: decklink_opts->interlaced = 0; decklink_opts->tff = 0; break; case bmdProgressiveSegmentedFrame: /* Assume tff interlaced - this mode should not be used in broadcast */ decklink_opts->interlaced = 1; decklink_opts->tff = 1; break; case bmdUpperFieldFirst: decklink_opts->interlaced = 1; decklink_opts->tff = 1; break; case bmdLowerFieldFirst: decklink_opts->interlaced = 1; decklink_opts->tff = 0; break; case bmdUnknownFieldDominance: default: /* Assume progressive */ decklink_opts->interlaced = 0; decklink_opts->tff = 0; break; } } p_display_mode->Release(); } decklink_opts->height = decklink_opts->coded_height; if( decklink_opts->coded_height == 486 ) decklink_opts->height = 480; if( !found_mode ) { fprintf( stderr, "[decklink] Unsupported video mode\n" ); ret = -1; goto finish; } cpu_flags = av_get_cpu_flags(); /* Setup VBI and VANC unpack functions */ if( IS_SD( decklink_opts->video_format ) ) { decklink_ctx->unpack_line = obe_v210_line_to_uyvy_c; decklink_ctx->downscale_line = obe_downscale_line_c; decklink_ctx->blank_line = obe_blank_line_uyvy_c; if( cpu_flags & AV_CPU_FLAG_MMX ) decklink_ctx->downscale_line = obe_downscale_line_mmx; if( cpu_flags & AV_CPU_FLAG_SSE2 ) decklink_ctx->downscale_line = obe_downscale_line_sse2; } else { decklink_ctx->unpack_line = obe_v210_line_to_nv20_c; decklink_ctx->blank_line = obe_blank_line_nv20_c; } result = decklink_ctx->p_input->EnableVideoInput( wanted_mode_id, bmdFormat10BitYUV, 0 ); if( result != S_OK ) { fprintf( stderr, "[decklink] Failed to enable video input\n" ); ret = -1; goto finish; } /* Set up audio. */ result = decklink_ctx->p_input->EnableAudioInput( sample_rate, bmdAudioSampleType32bitInteger, decklink_opts->num_channels ); if( result != S_OK ) { fprintf( stderr, "[decklink] Failed to enable audio input\n" ); ret = -1; goto finish; } if( !decklink_opts->probe ) { decklink_ctx->avr = avresample_alloc_context(); if( !decklink_ctx->avr ) { fprintf( stderr, "[decklink-sdiaudio] couldn't setup sample rate conversion \n" ); ret = -1; goto finish; } /* Give libavresample a made up channel map */ av_opt_set_int( decklink_ctx->avr, "in_channel_layout", (1 << decklink_opts->num_channels) - 1, 0 ); av_opt_set_int( decklink_ctx->avr, "in_sample_fmt", AV_SAMPLE_FMT_S32, 0 ); av_opt_set_int( decklink_ctx->avr, "in_sample_rate", 48000, 0 ); av_opt_set_int( decklink_ctx->avr, "out_channel_layout", (1 << decklink_opts->num_channels) - 1, 0 ); av_opt_set_int( decklink_ctx->avr, "out_sample_fmt", AV_SAMPLE_FMT_S32P, 0 ); if( avresample_open( decklink_ctx->avr ) < 0 ) { fprintf( stderr, "Could not open AVResample\n" ); goto finish; } } decklink_ctx->p_delegate = new DeckLinkCaptureDelegate( decklink_opts ); decklink_ctx->p_input->SetCallback( decklink_ctx->p_delegate ); result = decklink_ctx->p_input->StartStreams(); if( result != S_OK ) { fprintf( stderr, "[decklink] Could not start streaming from card\n" ); ret = -1; goto finish; } ret = 0; finish: if( decklink_iterator ) decklink_iterator->Release(); if( p_display_iterator ) p_display_iterator->Release(); if( ret ) close_card( decklink_opts ); return ret; }
HRESULT DeckLinkCaptureDelegate::VideoInputFrameArrived( IDeckLinkVideoInputFrame *videoframe, IDeckLinkAudioInputPacket *audioframe ) { decklink_ctx_t *decklink_ctx = &decklink_opts_->decklink_ctx; obe_raw_frame_t *raw_frame = NULL; AVPacket pkt; AVFrame *frame = NULL; void *frame_bytes, *anc_line; obe_t *h = decklink_ctx->h; int finished = 0, ret, num_anc_lines = 0, anc_line_stride, lines_read = 0, first_line = 0, last_line = 0, line, num_vbi_lines, vii_line; uint32_t *frame_ptr; uint16_t *anc_buf, *anc_buf_pos; uint8_t *vbi_buf; int anc_lines[DECKLINK_VANC_LINES]; IDeckLinkVideoFrameAncillary *ancillary; BMDTimeValue stream_time, frame_duration; if( decklink_opts_->probe_success ) return S_OK; av_init_packet( &pkt ); if( videoframe ) { if( videoframe->GetFlags() & bmdFrameHasNoInputSource ) { syslog( LOG_ERR, "Decklink card index %i: No input signal detected", decklink_opts_->card_idx ); return S_OK; } else if( decklink_opts_->probe ) decklink_opts_->probe_success = 1; /* use SDI ticks as clock source */ videoframe->GetStreamTime( &stream_time, &frame_duration, OBE_CLOCK ); obe_clock_tick( h, (int64_t)stream_time ); if( decklink_ctx->last_frame_time == -1 ) decklink_ctx->last_frame_time = obe_mdate(); else { int64_t cur_frame_time = obe_mdate(); if( cur_frame_time - decklink_ctx->last_frame_time >= SDI_MAX_DELAY ) { syslog( LOG_WARNING, "Decklink card index %i: No frame received for %"PRIi64" ms", decklink_opts_->card_idx, (cur_frame_time - decklink_ctx->last_frame_time) / 1000 ); pthread_mutex_lock( &h->drop_mutex ); h->encoder_drop = h->mux_drop = 1; pthread_mutex_unlock( &h->drop_mutex ); } decklink_ctx->last_frame_time = cur_frame_time; } const int width = videoframe->GetWidth(); const int height = videoframe->GetHeight(); const int stride = videoframe->GetRowBytes(); videoframe->GetBytes( &frame_bytes ); /* TODO: support format switching (rare in SDI) */ int j; for( j = 0; first_active_line[j].format != -1; j++ ) { if( decklink_opts_->video_format == first_active_line[j].format ) break; } videoframe->GetAncillaryData( &ancillary ); /* NTSC starts on line 4 */ line = decklink_opts_->video_format == INPUT_VIDEO_FORMAT_NTSC ? 4 : 1; anc_line_stride = FFALIGN( (width * 2 * sizeof(uint16_t)), 16 ); /* Overallocate slightly for VANC buffer * Some VBI services stray into the active picture so allocate some extra space */ anc_buf = anc_buf_pos = (uint16_t*)av_malloc( DECKLINK_VANC_LINES * anc_line_stride ); if( !anc_buf ) { syslog( LOG_ERR, "Malloc failed\n" ); goto end; } while( 1 ) { /* Some cards have restrictions on what lines can be accessed so try them all * Some buggy decklink cards will randomly refuse access to a particular line so * work around this issue by blanking the line */ if( ancillary->GetBufferForVerticalBlankingLine( line, &anc_line ) == S_OK ) decklink_ctx->unpack_line( (uint32_t*)anc_line, anc_buf_pos, width ); else decklink_ctx->blank_line( anc_buf_pos, width ); anc_buf_pos += anc_line_stride / 2; anc_lines[num_anc_lines++] = line; if( !first_line ) first_line = line; last_line = line; lines_read++; line = sdi_next_line( decklink_opts_->video_format, line ); if( line == first_active_line[j].line ) break; } ancillary->Release(); if( !decklink_opts_->probe ) { raw_frame = new_raw_frame(); if( !raw_frame ) { syslog( LOG_ERR, "Malloc failed\n" ); goto end; } } anc_buf_pos = anc_buf; for( int i = 0; i < num_anc_lines; i++ ) { parse_vanc_line( h, &decklink_ctx->non_display_parser, raw_frame, anc_buf_pos, width, anc_lines[i] ); anc_buf_pos += anc_line_stride / 2; } if( IS_SD( decklink_opts_->video_format ) && first_line != last_line ) { /* Add a some VBI lines to the ancillary buffer */ frame_ptr = (uint32_t*)frame_bytes; /* NTSC starts from line 283 so add an extra line */ num_vbi_lines = NUM_ACTIVE_VBI_LINES + ( decklink_opts_->video_format == INPUT_VIDEO_FORMAT_NTSC ); for( int i = 0; i < num_vbi_lines; i++ ) { decklink_ctx->unpack_line( frame_ptr, anc_buf_pos, width ); anc_buf_pos += anc_line_stride / 2; frame_ptr += stride / 4; last_line = sdi_next_line( decklink_opts_->video_format, last_line ); } num_anc_lines += num_vbi_lines; vbi_buf = (uint8_t*)av_malloc( width * 2 * num_anc_lines ); if( !vbi_buf ) { syslog( LOG_ERR, "Malloc failed\n" ); goto end; } /* Scale the lines from 10-bit to 8-bit */ decklink_ctx->downscale_line( anc_buf, vbi_buf, num_anc_lines ); anc_buf_pos = anc_buf; /* Handle Video Index information */ int tmp_line = first_line; vii_line = decklink_opts_->video_format == INPUT_VIDEO_FORMAT_NTSC ? NTSC_VIDEO_INDEX_LINE : PAL_VIDEO_INDEX_LINE; while( tmp_line < vii_line ) { anc_buf_pos += anc_line_stride / 2; tmp_line++; } if( decode_video_index_information( h, &decklink_ctx->non_display_parser, anc_buf_pos, raw_frame, vii_line ) < 0 ) goto fail; if( !decklink_ctx->has_setup_vbi ) { vbi_raw_decoder_init( &decklink_ctx->non_display_parser.vbi_decoder ); decklink_ctx->non_display_parser.ntsc = decklink_opts_->video_format == INPUT_VIDEO_FORMAT_NTSC; decklink_ctx->non_display_parser.vbi_decoder.start[0] = first_line; decklink_ctx->non_display_parser.vbi_decoder.start[1] = sdi_next_line( decklink_opts_->video_format, first_line ); decklink_ctx->non_display_parser.vbi_decoder.count[0] = last_line - decklink_ctx->non_display_parser.vbi_decoder.start[1] + 1; decklink_ctx->non_display_parser.vbi_decoder.count[1] = decklink_ctx->non_display_parser.vbi_decoder.count[0]; if( setup_vbi_parser( &decklink_ctx->non_display_parser ) < 0 ) goto fail; decklink_ctx->has_setup_vbi = 1; } if( decode_vbi( h, &decklink_ctx->non_display_parser, vbi_buf, raw_frame ) < 0 ) goto fail; av_free( vbi_buf ); } av_free( anc_buf ); if( !decklink_opts_->probe ) { frame = avcodec_alloc_frame(); if( !frame ) { syslog( LOG_ERR, "[decklink]: Could not allocate video frame\n" ); goto end; } decklink_ctx->codec->width = width; decklink_ctx->codec->height = height; pkt.data = (uint8_t*)frame_bytes; pkt.size = stride * height; ret = avcodec_decode_video2( decklink_ctx->codec, frame, &finished, &pkt ); if( ret < 0 || !finished ) { syslog( LOG_ERR, "[decklink]: Could not decode video frame\n" ); goto end; } raw_frame->release_data = obe_release_video_data; raw_frame->release_frame = obe_release_frame; memcpy( raw_frame->alloc_img.stride, frame->linesize, sizeof(raw_frame->alloc_img.stride) ); memcpy( raw_frame->alloc_img.plane, frame->data, sizeof(raw_frame->alloc_img.plane) ); avcodec_free_frame( &frame ); raw_frame->alloc_img.csp = (int)decklink_ctx->codec->pix_fmt; raw_frame->alloc_img.planes = av_pix_fmt_descriptors[raw_frame->alloc_img.csp].nb_components; raw_frame->alloc_img.width = width; raw_frame->alloc_img.height = height; raw_frame->alloc_img.format = decklink_opts_->video_format; raw_frame->timebase_num = decklink_opts_->timebase_num; raw_frame->timebase_den = decklink_opts_->timebase_den; memcpy( &raw_frame->img, &raw_frame->alloc_img, sizeof(raw_frame->alloc_img) ); if( IS_SD( decklink_opts_->video_format ) ) { if( raw_frame->alloc_img.height == 486 ) raw_frame->img.height = 480; raw_frame->img.first_line = first_active_line[j].line; } /* If AFD is present and the stream is SD this will be changed in the video filter */ raw_frame->sar_width = raw_frame->sar_height = 1; raw_frame->pts = stream_time; for( int i = 0; i < decklink_ctx->device->num_input_streams; i++ ) { if( decklink_ctx->device->streams[i]->stream_format == VIDEO_UNCOMPRESSED ) raw_frame->input_stream_id = decklink_ctx->device->streams[i]->input_stream_id; } if( add_to_filter_queue( h, raw_frame ) < 0 ) goto fail; if( send_vbi_and_ttx( h, &decklink_ctx->non_display_parser, raw_frame->pts ) < 0 ) goto fail; decklink_ctx->non_display_parser.num_vbi = 0; decklink_ctx->non_display_parser.num_anc_vbi = 0; } } /* TODO: probe SMPTE 337M audio */ if( audioframe && !decklink_opts_->probe ) { audioframe->GetBytes( &frame_bytes ); raw_frame = new_raw_frame(); if( !raw_frame ) { syslog( LOG_ERR, "Malloc failed\n" ); goto end; } raw_frame->audio_frame.num_samples = audioframe->GetSampleFrameCount(); raw_frame->audio_frame.num_channels = decklink_opts_->num_channels; raw_frame->audio_frame.sample_fmt = AV_SAMPLE_FMT_S32P; if( av_samples_alloc( raw_frame->audio_frame.audio_data, &raw_frame->audio_frame.linesize, decklink_opts_->num_channels, raw_frame->audio_frame.num_samples, (AVSampleFormat)raw_frame->audio_frame.sample_fmt, 0 ) < 0 ) { syslog( LOG_ERR, "Malloc failed\n" ); return -1; } if( avresample_convert( decklink_ctx->avr, raw_frame->audio_frame.audio_data, raw_frame->audio_frame.linesize, raw_frame->audio_frame.num_samples, (uint8_t**)&frame_bytes, 0, raw_frame->audio_frame.num_samples ) < 0 ) { syslog( LOG_ERR, "[decklink] Sample format conversion failed\n" ); return -1; } BMDTimeValue packet_time; audioframe->GetPacketTime( &packet_time, OBE_CLOCK ); raw_frame->pts = packet_time; raw_frame->release_data = obe_release_audio_data; raw_frame->release_frame = obe_release_frame; for( int i = 0; i < decklink_ctx->device->num_input_streams; i++ ) { if( decklink_ctx->device->streams[i]->stream_format == AUDIO_PCM ) raw_frame->input_stream_id = decklink_ctx->device->streams[i]->input_stream_id; } if( add_to_filter_queue( decklink_ctx->h, raw_frame ) < 0 ) goto fail; } end: if( frame ) avcodec_free_frame( &frame ); av_free_packet( &pkt ); return S_OK; fail: if( raw_frame ) { raw_frame->release_data( raw_frame ); raw_frame->release_frame( raw_frame ); } return S_OK; }